Пример #1
0
    def _operation(self, world: "World", dimension: Dimension,
                   selection: SelectionGroup) -> OperationReturnType:
        if len(selection.selection_boxes) == 0:
            raise OperationError("No selection was given to export.")
        elif len(selection.selection_boxes) != 1:
            raise OperationError(
                "The mcstructure format only supports a single selection box.")

        path = self._file_picker.GetPath()
        version = self._version_define.version_number

        if isinstance(path, str) and path.endswith(".mcstructure") and version:
            wrapper = MCStructureFormatWrapper(path, "w")
            wrapper.selection = selection
            wrapper.version = version
            wrapper.translation_manager = world.translation_manager
            wrapper.open()
            chunk_count = len(list(selection.chunk_locations()))
            yield 0, f"Exporting {os.path.basename(path)}"
            for chunk_index, (cx,
                              cz) in enumerate(selection.chunk_locations()):
                try:
                    chunk = world.get_chunk(cx, cz, dimension)
                    wrapper.commit_chunk(chunk, world.palette)
                except ChunkLoadError:
                    continue
                yield (chunk_index + 1) / chunk_count

            wrapper.close()
        else:
            raise OperationError(
                "Please specify a save location and version in the options before running."
            )
 def _operation(
     self, world: "World", dimension: Dimension, selection: SelectionGroup
 ) -> OperationReturnType:
     path = self._file_picker.GetPath()
     platform = self._version_define.platform
     version = self._version_define.version_number
     if isinstance(path, str) and platform and version:
         wrapper = ConstructionFormatWrapper(path)
         if wrapper.exists:
             response = wx.MessageDialog(
                 self,
                 f"A file is already present at {path}. Do you want to continue?",
                 style=wx.YES | wx.NO,
             ).ShowModal()
             if response == wx.ID_CANCEL:
                 return
         wrapper.create_and_open(platform, version, selection)
         wrapper.translation_manager = world.translation_manager
         wrapper_dimension = wrapper.dimensions[0]
         chunk_count = len(list(selection.chunk_locations()))
         yield 0, f"Exporting {os.path.basename(path)}"
         for chunk_index, (cx, cz) in enumerate(selection.chunk_locations()):
             try:
                 chunk = world.get_chunk(cx, cz, dimension)
                 wrapper.commit_chunk(chunk, wrapper_dimension)
             except ChunkLoadError:
                 continue
             yield (chunk_index + 1) / chunk_count
         wrapper.save()
         wrapper.close()
     else:
         raise OperationError(
             "Please specify a save location and version in the options before running."
         )
Пример #3
0
    def test_is_rectangular(self):
        box_1 = SelectionBox((0, 0, 0), (5, 5, 5))
        box_2 = SelectionBox((0, 5, 0), (5, 10, 5))
        box_3 = SelectionBox((0, 0, 5), (5, 5, 10))
        box_4 = SelectionBox((0, 5, 5), (5, 10, 10))

        self.assertTrue(SelectionGroup(box_1).is_rectangular)
        self.assertTrue(SelectionGroup((box_1, box_2)).is_rectangular)
        self.assertFalse(SelectionGroup((box_1, box_2, box_3)).is_rectangular)
        self.assertTrue(SelectionGroup((box_1, box_2, box_3, box_4)).is_rectangular)
        self.assertTrue(
            SelectionGroup((box_1, box_2, box_3, box_4, box_2)).is_rectangular
        )
Пример #4
0
 def _on_input_press(self, evt: InputPressEvent):
     if evt.action_id == ACT_BOX_CLICK:
         if not self._editing:
             self._press_time = time.time()
             self._editing = True
             self._start_box = self._pointer.bounds
             self._update_pointer()
     elif evt.action_id == ACT_DESELECT_ALL_BOXES:
         self._selection.selection_group = SelectionGroup()
         self._create_undo()
     elif evt.action_id == ACT_DELESECT_BOX:
         if ACT_DESELECT_ALL_BOXES not in self.canvas.buttons.pressed_actions:
             self._selection.selection_group = SelectionGroup()
             self._create_undo()
     evt.Skip()
Пример #5
0
    def get_chunk_boxes(
        self,
        selection: Union[SelectionGroup, SelectionBox],
        dimension: Dimension,
        create_missing_chunks=False,
    ) -> Generator[Tuple[Chunk, SelectionBox], None, None]:
        """Given a selection will yield chunks and SubSelectionBoxes into that chunk

        :param selection: SelectionGroup or SelectionBox into the world
        :param dimension: The dimension to take effect in (defaults to overworld)
        :param create_missing_chunks: If a chunk does not exist an empty one will be created (defaults to false)
        """

        if isinstance(selection, SelectionBox):
            selection = SelectionGroup([selection])
        selection: SelectionGroup
        for (cx, cz), box in selection.sub_sections(self.sub_chunk_size):
            try:
                chunk = self.get_chunk(cx, cz, dimension)
            except ChunkDoesNotExist:
                if create_missing_chunks:
                    chunk = Chunk(cx, cz)
                    self.put_chunk(chunk, dimension)
                else:
                    continue
            except ChunkLoadError:
                continue

            yield chunk, box
Пример #6
0
    def __init__(self, canvas: "EditCanvas"):
        super().__init__()
        self._selection_corners: Tuple[BoxType, ...] = ()
        self._selection_group: SelectionGroup = SelectionGroup()
        self._canvas = weakref.ref(canvas)

        self._timer = wx.Timer(canvas)
Пример #7
0
        def test_replace_single_block(self):
            subbox1 = SelectionBox((1, 70, 3), (5, 71, 6))
            box1 = SelectionGroup((subbox1, ))

            self.assertEqual(
                "universal_minecraft:stone",
                self.world.get_block(1, 70, 3, OVERWORLD).blockstate,
            )
            self.assertEqual(
                "universal_minecraft:granite[polished=false]",
                self.world.get_block(1, 70, 5, OVERWORLD).blockstate,
            )

            replace(
                self.world,
                OVERWORLD,
                box1,
                {
                    "original_blocks": [
                        Block.from_string_blockstate(
                            "universal_minecraft:granite[polished=false]")
                    ],
                    "replacement_blocks": [
                        Block.from_string_blockstate(
                            "universal_minecraft:stone")
                    ],
                },
            )
            self.world.create_undo_point()

            self.assertEqual(
                "universal_minecraft:stone",
                self.world.get_block(1, 70, 3, OVERWORLD).blockstate,
            )
            self.assertEqual(
                "universal_minecraft:stone",
                self.world.get_block(1, 70, 5, OVERWORLD).blockstate,
            )

            self.world.undo()

            self.assertEqual(
                "universal_minecraft:stone",
                self.world.get_block(1, 70, 3, OVERWORLD).blockstate,
            )
            self.assertEqual(
                "universal_minecraft:granite[polished=false]",
                self.world.get_block(1, 70, 5, OVERWORLD).blockstate,
            )

            self.world.redo()

            self.assertEqual(
                "universal_minecraft:stone",
                self.world.get_block(1, 70, 3, OVERWORLD).blockstate,
            )
            self.assertEqual(
                "universal_minecraft:stone",
                self.world.get_block(1, 70, 5, OVERWORLD).blockstate,
            )
Пример #8
0
    def set_selection_corners(
        self,
        selection_corners: Tuple[Tuple[Tuple[int, int, int], Tuple[int, int,
                                                                   int]], ...],
    ):
        """Set the minimum and maximum points of each selection
        Note this method will not trigger the history logic.
        You may instead want the selection_corners setter method.

        :param selection_corners: The minimum and maximum points of each selection
        :return:
        """
        selections = []
        for points in selection_corners:
            if len(points) == 2 and all(len(point) == 3 for point in points):
                selections.append(
                    tuple(tuple(int(p) for p in point) for point in points))
            else:
                log.error(
                    f"selection_corners must be of the format Tuple[Tuple[Tuple[int, int, int], Tuple[int, int, int]], ...]"
                )

        self.changed = True
        self._selection_corners = tuple(selections)
        self._selection_group = SelectionGroup(
            [SelectionBox(*box) for box in self._selection_corners])
        wx.PostEvent(self._canvas(), SelectionChangeEvent())
Пример #9
0
def export_construction(world: "World", dimension: Dimension,
                        selection: SelectionGroup, options: dict):
    path, platform, version = options.get('path', None), options.get(
        'platform', None), options.get('version', None)
    if isinstance(
            path,
            str) and path.endswith('.construction') and platform and version:
        wrapper = ConstructionFormatWrapper(path, 'w')
        wrapper.platform = platform
        wrapper.version = version
        wrapper.selection = selection
        wrapper.translation_manager = world.translation_manager
        wrapper.open()
        for cx, cz in selection.chunk_locations():
            try:
                chunk = world.get_chunk(cx, cz, dimension)
                wrapper.commit_chunk(chunk, world.palette)
            except ChunkLoadError:
                continue

        wrapper.close()
    else:
        raise Exception(
            'Please specify a save location and version in the options before running.'
        )
Пример #10
0
def prune_chunks(world: "BaseLevel", dimension: Dimension,
                 selection: SelectionGroup):
    chunks = world.all_chunk_coords(dimension).difference(
        selection.chunk_locations())
    for i, (cx, cz) in enumerate(chunks):
        world.delete_chunk(cx, cz, dimension)
        yield (i + 1) / len(chunks)
Пример #11
0
        def test_replace_single_block(self):
            subbox1 = SelectionBox((1, 70, 3), (5, 71, 6))
            box1 = SelectionGroup((subbox1,))

            self.assertEqual(
                "universal_minecraft:stone",
                self.world.get_block(1, 70, 3, "overworld").blockstate,
            )
            self.assertEqual(
                'universal_minecraft:granite[polished="false"]',
                self.world.get_block(1, 70, 5, "overworld").blockstate,
            )

            self.world.run_operation(
                replace,
                "overworld",
                box1,
                {
                    "original_blocks": [
                        blockstate_to_block(
                            "universal_minecraft:granite[polished=false]"
                        )
                    ],
                    "replacement_blocks": [
                        blockstate_to_block("universal_minecraft:stone")
                    ],
                },
            )

            self.assertEqual(
                "universal_minecraft:stone",
                self.world.get_block(1, 70, 3, "overworld").blockstate,
            )
            self.assertEqual(
                "universal_minecraft:stone",
                self.world.get_block(1, 70, 5, "overworld").blockstate,
            )

            self.world.undo()

            self.assertEqual(
                "universal_minecraft:stone",
                self.world.get_block(1, 70, 3, "overworld").blockstate,
            )
            self.assertEqual(
                'universal_minecraft:granite[polished="false"]',
                self.world.get_block(1, 70, 5, "overworld").blockstate,
            )

            self.world.redo()

            self.assertEqual(
                "universal_minecraft:stone",
                self.world.get_block(1, 70, 3, "overworld").blockstate,
            )
            self.assertEqual(
                "universal_minecraft:stone",
                self.world.get_block(1, 70, 5, "overworld").blockstate,
            )
Пример #12
0
 def create_chunks(
     world: BaseLevel,
     dimension: Dimension,
     selection: SelectionGroup,
 ):
     for cx, cz in selection.chunk_locations():
         if not world.has_chunk(cx, cz, dimension):
             world.put_chunk(Chunk(cx, cz), dimension)
Пример #13
0
    def get_coord_box(
        self,
        dimension: Dimension,
        selection: Union[SelectionGroup, SelectionBox, None] = None,
        yield_missing_chunks=False,
    ) -> Generator[Tuple[ChunkCoordinates, SelectionBox], None, None]:
        """Given a selection will yield chunk coordinates and `SelectionBox`es into that chunk
        If not given a selection will use the bounds of the object.

        :param selection: SelectionGroup or SelectionBox into the level
        :param dimension: The dimension to take effect in
        :param yield_missing_chunks: If a chunk does not exist an empty one will be created (defaults to false). Use this with care.
        """
        if isinstance(selection, SelectionBox):
            selection = SelectionGroup(selection)
        elif selection is None:
            selection = self.selection_bounds
        elif not isinstance(selection, SelectionGroup):
            raise TypeError(
                f"Expected a SelectionGroup but got {type(selection)}")

        selection: SelectionGroup
        if yield_missing_chunks or selection.footprint_area < 1_000_000:
            if yield_missing_chunks:
                for coord, box in selection.chunk_boxes(self.sub_chunk_size):
                    yield coord, box
            else:
                for (cx,
                     cz), box in selection.chunk_boxes(self.sub_chunk_size):
                    if self.has_chunk(cx, cz, dimension):
                        yield (cx, cz), box

        else:
            # if the selection gets very large iterating over the whole selection and accessing chunks can get slow
            # instead we are going to iterate over the chunks and get the intersection of the selection
            for cx, cz in self.all_chunk_coords(dimension):
                box = SelectionGroup(
                    SelectionBox.create_chunk_box(cx, cz, self.sub_chunk_size))

                if selection.intersects(box):
                    chunk_selection = selection.intersection(box)
                    for sub_box in chunk_selection.selection_boxes:
                        yield (cx, cz), sub_box
Пример #14
0
    def test_sorted_iterator(self):
        box_1 = SelectionBox((0, 0, 0), (4, 4, 4))
        box_2 = SelectionBox((7, 7, 7), (10, 10, 10))
        box_3 = SelectionBox((15, 15, 15), (20, 20, 20))

        selection_1 = SelectionGroup(
            (
                box_1,
                box_2,
                box_3,
            )
        )
        selection_2 = SelectionGroup(
            (
                box_1,
                box_3,
                box_2,
            )
        )

        self.assertEqual(selection_1, selection_2)
Пример #15
0
    def _operation(
        self, world: "BaseLevel", dimension: Dimension, selection: SelectionGroup
    ) -> OperationReturnType:
        if len(selection.selection_boxes) == 0:
            raise OperationError("No selection was given to export.")
        elif len(selection.selection_boxes) != 1:
            raise OperationError(
                "The Sponge Schematic format only supports a single selection box."
            )

        path = self._file_picker.GetPath()
        version = self._version_define.version_number
        if isinstance(path, str):
            wrapper = SpongeSchemFormatWrapper(path)
            if wrapper.exists:
                response = wx.MessageDialog(
                    self,
                    f"A file is already present at {path}. Do you want to continue?",
                    style=wx.YES | wx.NO,
                ).ShowModal()
                if response == wx.ID_CANCEL:
                    return
            wrapper.create_and_open("java", version, selection, True)
            wrapper.translation_manager = world.translation_manager
            wrapper_dimension = wrapper.dimensions[0]
            chunk_count = len(list(selection.chunk_locations()))
            yield 0, f"Exporting {os.path.basename(path)}"
            for chunk_index, (cx, cz) in enumerate(selection.chunk_locations()):
                try:
                    chunk = world.get_chunk(cx, cz, dimension)
                    wrapper.commit_chunk(chunk, wrapper_dimension)
                except ChunkLoadError:
                    continue
                yield (chunk_index + 1) / chunk_count
            wrapper.save()
            wrapper.close()
        else:
            raise OperationError(
                "Please specify a save location and version in the options before running."
            )
Пример #16
0
 def test_subtract(self):
     box_1 = SelectionGroup(
         SelectionBox(
             (0, 0, 0),
             (32, 32, 32),
         )
     )
     box_2 = SelectionGroup(
         SelectionBox(
             (0, 0, 0),
             (16, 16, 16),
         )
     )
     box_3 = box_1.subtract(box_2)
     box_4 = SelectionGroup(
         (
             SelectionBox((0, 16, 0), (32, 32, 32)),
             SelectionBox((0, 0, 16), (32, 16, 32)),
             SelectionBox((16, 0, 0), (32, 16, 16)),
         )
     )
     self.assertEqual(box_3, box_4)
Пример #17
0
 def _sanitise_selection(self, selection: Union[SelectionGroup,
                                                SelectionBox, None],
                         dimension: Dimension) -> SelectionGroup:
     if isinstance(selection, SelectionBox):
         return SelectionGroup(selection)
     elif isinstance(selection, SelectionGroup):
         return selection
     elif selection is None:
         return self.bounds(dimension)
     else:
         raise ValueError(
             f"Expected SelectionBox, SelectionGroup or None. Got {selection}"
         )
Пример #18
0
        def test_fill_operation(self):
            subbox_1 = SelectionBox((1, 70, 3), (5, 71, 5))
            selection = SelectionGroup((subbox_1, ))

            # Start sanity check
            self.assertEqual(
                "universal_minecraft:stone",
                self.world.get_block(1, 70, 3, OVERWORLD).blockstate,
            )
            self.assertEqual(
                "universal_minecraft:granite[polished=false]",
                self.world.get_block(1, 70, 5, OVERWORLD).blockstate,
            )
            # End sanity check

            generator_unpacker(
                fill(
                    self.world,
                    OVERWORLD,
                    selection,
                    Block.from_string_blockstate("universal_minecraft:stone"),
                ))
            self.world.create_undo_point()

            for x, y, z in selection.blocks:
                self.assertEqual(
                    "universal_minecraft:stone",
                    self.world.get_block(x, y, z, OVERWORLD).blockstate,
                    f"Failed at coordinate ({x},{y},{z})",
                )

            self.world.undo()

            self.assertEqual(
                "universal_minecraft:stone",
                self.world.get_block(1, 70, 3, OVERWORLD).blockstate,
            )

            self.assertEqual(
                "universal_minecraft:granite[polished=false]",
                self.world.get_block(1, 70, 5, OVERWORLD).blockstate,
            )

            self.world.redo()

            for x, y, z in selection.blocks:
                self.assertEqual(
                    "universal_minecraft:stone",
                    self.world.get_block(x, y, z, OVERWORLD).blockstate,
                    f"Failed at coordinate ({x},{y},{z})",
                )
Пример #19
0
        def test_get_blocks(self):
            selection_box = SelectionBox((0, 0, 0), (10, 10, 10))
            for selection in [SelectionGroup([selection_box]), selection_box]:
                chunk, box = next(self.world.get_chunk_boxes(selection, "overworld"))
                self.assertIsInstance(chunk, Chunk)
                self.assertIsInstance(box, SelectionBox)

                chunk, slices, _ = next(
                    self.world.get_chunk_slices(selection, "overworld")
                )
                self.assertIsInstance(chunk, Chunk)
                self.assertIsInstance(slices, tuple)
                for s in slices:
                    self.assertIsInstance(s, slice)
Пример #20
0
 def _clean_selection(self, selection: SelectionGroup) -> SelectionGroup:
     if self.multi_selection:
         return selection
     else:
         if selection:
             return SelectionGroup(
                 sorted(
                     selection.selection_boxes,
                     reverse=True,
                     key=lambda b: b.volume,
                 )[0])
         else:
             raise ObjectReadError(
                 "A single selection was required but none were given.")
Пример #21
0
        def test_delete_chunk(self):
            subbox1 = SelectionBox((1, 1, 1), (5, 5, 5))
            box1 = SelectionGroup((subbox1, ))

            self.assertEqual(
                "universal_minecraft:stone",
                self.world.get_block(1, 70, 3, OVERWORLD).blockstate,
            )
            self.assertEqual(
                "universal_minecraft:granite[polished=false]",
                self.world.get_block(1, 70, 5, OVERWORLD).blockstate,
            )

            generator_unpacker(delete_chunk(self.world, OVERWORLD, box1))
            self.world.create_undo_point()

            with self.assertRaises(ChunkDoesNotExist):
                _ = self.world.get_block(1, 70, 3, OVERWORLD).blockstate

            self.assertEqual(
                0,
                len([
                    x for x in self.world.get_chunk_slice_box(
                        OVERWORLD, subbox1)
                ]),
            )

            self.world.undo()

            self.assertEqual(
                "universal_minecraft:stone",
                self.world.get_block(1, 70, 3, OVERWORLD).blockstate,
            )
            self.assertEqual(
                "universal_minecraft:granite[polished=false]",
                self.world.get_block(1, 70, 5, OVERWORLD).blockstate,
            )

            self.world.redo()

            with self.assertRaises(ChunkDoesNotExist):
                _ = self.world.get_block(1, 70, 3, OVERWORLD).blockstate

            self.assertEqual(
                0,
                len([
                    x for x in self.world.get_chunk_slice_box(
                        OVERWORLD, subbox1)
                ]),
            )
Пример #22
0
        def test_delete_chunk(self):
            subbox1 = SelectionBox((1, 1, 1), (5, 5, 5))
            box1 = SelectionGroup((subbox1, ))

            self.assertEqual(
                "universal_minecraft:stone",
                self.world.get_block(1, 70, 3, "overworld").blockstate,
            )
            self.assertEqual(
                'universal_minecraft:granite[polished="false"]',
                self.world.get_block(1, 70, 5, "overworld").blockstate,
            )

            self.world.run_operation(delete_chunk, "overworld", box1)

            with self.assertRaises(ChunkDoesNotExist):
                _ = self.world.get_block(1, 70, 3, "overworld").blockstate

            self.assertEqual(
                0,
                len([
                    x for x in self.world.get_chunk_slice_box(
                        "overworld", subbox1)
                ]),
            )

            self.world.undo()

            self.assertEqual(
                "universal_minecraft:stone",
                self.world.get_block(1, 70, 3, "overworld").blockstate,
            )
            self.assertEqual(
                'universal_minecraft:granite[polished="false"]',
                self.world.get_block(1, 70, 5, "overworld").blockstate,
            )

            self.world.redo()

            with self.assertRaises(ChunkDoesNotExist):
                _ = self.world.get_block(1, 70, 3, "overworld").blockstate

            self.assertEqual(
                0,
                len([
                    x for x in self.world.get_chunk_slice_box(
                        "overworld", subbox1)
                ]),
            )
Пример #23
0
 def _on_input_release(self, evt: InputReleaseEvent):
     if evt.action_id == ACT_BOX_CLICK:
         if self._editing and time.time() - self._press_time > 0.1:
             self._editing = False
             box = SelectionBox(*self._get_editing_selection())
             if SelectionGroup(box).is_subset(
                     self._selection.selection_group):
                 # subtract
                 self._selection.selection_group = (
                     self._selection.selection_group.subtract(box))
             else:
                 self._selection.selection_group = (
                     self._selection.selection_group.union(box))
             self._create_undo()
     evt.Skip()
Пример #24
0
        def test_fill_operation(self):
            subbox_1 = SelectionBox((1, 70, 3), (5, 71, 5))
            box = SelectionGroup((subbox_1,))

            # Start sanity check
            self.assertEqual(
                "universal_minecraft:stone",
                self.world.get_block(1, 70, 3, "overworld").blockstate,
            )
            self.assertEqual(
                'universal_minecraft:granite[polished="false"]',
                self.world.get_block(1, 70, 5, "overworld").blockstate,
            )
            # End sanity check

            self.world.run_operation(
                fill, "overworld", box, blockstate_to_block("universal_minecraft:stone")
            )

            for x, y, z in box:
                self.assertEqual(
                    "universal_minecraft:stone",
                    self.world.get_block(x, y, z, "overworld").blockstate,
                    f"Failed at coordinate ({x},{y},{z})",
                )

            self.world.undo()

            self.assertEqual(
                "universal_minecraft:stone",
                self.world.get_block(1, 70, 3, "overworld").blockstate,
            )

            self.assertEqual(
                'universal_minecraft:granite[polished="false"]',
                self.world.get_block(1, 70, 5, "overworld").blockstate,
            )

            self.world.redo()

            for x, y, z in box:
                self.assertEqual(
                    "universal_minecraft:stone",
                    self.world.get_block(x, y, z, "overworld").blockstate,
                    f"Failed at coordinate ({x},{y},{z})",
                )
Пример #25
0
        def test_clone_operation(self):
            subbx1 = SelectionBox((1, 70, 3), (2, 71, 4))
            src_box = SelectionGroup((subbx1, ))

            target = {"x": 1, "y": 70, "z": 5}

            self.assertEqual(
                "universal_minecraft:stone",
                self.world.get_block(1, 70, 3, OVERWORLD).blockstate,
            )  # Sanity check
            self.assertEqual(
                "universal_minecraft:granite[polished=false]",
                self.world.get_block(1, 70, 5, OVERWORLD).blockstate,
            )

            clone(self.world, OVERWORLD, src_box, target)
            self.world.create_undo_point()

            self.assertEqual(
                "universal_minecraft:stone",
                self.world.get_block(1, 70, 5, OVERWORLD).blockstate,
            )

            self.world.undo()

            self.assertEqual(
                "universal_minecraft:granite[polished=false]",
                self.world.get_block(1, 70, 5, OVERWORLD).blockstate,
            )

            self.world.redo()

            self.assertEqual(
                "universal_minecraft:stone",
                self.world.get_block(1, 70, 5, OVERWORLD).blockstate,
            )

            self.world.undo()

            self.assertEqual(
                "universal_minecraft:granite[polished=false]",
                self.world.get_block(1, 70, 5, OVERWORLD).blockstate,
            )
Пример #26
0
    def __init__(self, path: PathOrBuffer, mode: str = "r"):
        super().__init__(path)
        assert mode in ("r", "w"), 'Mode must be either "r" or "w".'
        self._mode = mode
        if isinstance(path, str):
            assert path.endswith(".construction"), 'Path must end with ".construction"'
            if mode == "r":
                assert os.path.isfile(path), "File specified does not exist."
        self._data: Optional[Union[ConstructionWriter, ConstructionReader]] = None
        self._open = False
        self._platform = "java"
        self._version = (1, 15, 2)
        self._selection: SelectionGroup = SelectionGroup()

        # used to look up which sections are in a given chunk when loading
        self._chunk_to_section: Optional[Dict[Tuple[int, int], List[int]]] = None

        # used to look up which selection boxes intersect a given chunk (boxes are clipped to the size of the chunk)
        self._chunk_to_box: Optional[Dict[Tuple[int, int], List[SelectionBox]]] = None
Пример #27
0
        def test_clone_operation(self):
            subbx1 = SelectionBox((1, 70, 3), (2, 71, 4))
            src_box = SelectionGroup((subbx1,))

            target = {"x": 1, "y": 70, "z": 5}

            self.assertEqual(
                "universal_minecraft:stone",
                self.world.get_block(1, 70, 3, "overworld").blockstate,
            )  # Sanity check
            self.assertEqual(
                'universal_minecraft:granite[polished="false"]',
                self.world.get_block(1, 70, 5, "overworld").blockstate,
            )

            self.world.run_operation(clone, "overworld", src_box, target)

            self.assertEqual(
                "universal_minecraft:stone",
                self.world.get_block(1, 70, 5, "overworld").blockstate,
            )

            self.world.undo()

            self.assertEqual(
                'universal_minecraft:granite[polished="false"]',
                self.world.get_block(1, 70, 5, "overworld").blockstate,
            )

            self.world.redo()

            self.assertEqual(
                "universal_minecraft:stone",
                self.world.get_block(1, 70, 5, "overworld").blockstate,
            )

            self.world.undo()

            self.assertEqual(
                'universal_minecraft:granite[polished="false"]',
                self.world.get_block(1, 70, 5, "overworld").blockstate,
            )
Пример #28
0
def delete_chunk(
    world: "BaseLevel",
    dimension: Dimension,
    source_box: SelectionGroup,
    load_original: bool = True,
):
    chunks = [(cx, cz) for (cx, cz) in source_box.chunk_locations()
              if world.has_chunk(cx, cz, dimension)]
    iter_count = len(chunks)
    for count, (cx, cz) in enumerate(chunks):
        world.delete_chunk(cx, cz, dimension)

        if not load_original:
            # this part is kind of hacky.
            # Work out a propery API to do this.
            key = dimension, cx, cz
            if key not in world.chunks._history_database:
                world.chunks._register_original_entry(key, Chunk(cx, cz))

        yield (count + 1) / iter_count
Пример #29
0
 def _chunkify_selection(self):
     selections = []
     for box in self.canvas.selection.selection_group.selection_boxes:
         min_point = (
             numpy.floor(box.min_array / self.canvas.world.sub_chunk_size) *
             self.canvas.world.sub_chunk_size)
         max_point = (
             numpy.ceil(box.max_array / self.canvas.world.sub_chunk_size) *
             self.canvas.world.sub_chunk_size)
         bounds = self.canvas.world.bounds(self.canvas.dimension)
         min_point[1] = bounds.min[1]
         max_point[1] = bounds.max[1]
         selections.append(SelectionBox(min_point, max_point))
     selection_group = SelectionGroup(selections)
     if selection_group != self.canvas.selection.selection_group:
         # if the above code modified the selection
         self.canvas.selection.selection_group = selection_group
         # this will indirectly update the renderer by updating the global selection
     elif selection_group != self._selection.selection_group:
         # if the above code did not change the selection but it does not match the renderer
         self._selection.selection_group = selection_group
Пример #30
0
    def _operation(self, world: "World", dimension: Dimension, selection: SelectionGroup) -> OperationReturnType:
        path = self._file_picker.GetPath()
        platform = self._version_define.platform
        version = self._version_define.version
        if isinstance(path, str) and path.endswith('.construction') and platform and version:
            wrapper = ConstructionFormatWrapper(path, 'w')
            wrapper.platform = platform
            wrapper.version = version
            wrapper.selection = selection
            wrapper.translation_manager = world.translation_manager
            wrapper.open()
            for cx, cz in selection.chunk_locations():
                try:
                    chunk = world.get_chunk(cx, cz, dimension)
                    wrapper.commit_chunk(chunk, world.palette)
                except ChunkLoadError:
                    continue

            wrapper.close()
        else:
            raise OperationError('Please specify a save location and version in the options before running.')