Esempio n. 1
0
    def run_operation(
        self,
        operation: Callable[[], OperationReturnType],
        title="Amulet",
        msg="Running Operation",
        throw_exceptions=False,
    ) -> Any:
        def operation_wrapper():
            yield 0, "Disabling Threads"
            self.renderer.disable_threads()
            yield 0, msg
            op = operation()
            if isinstance(op, GeneratorType):
                yield from op
            yield 0, "Creating Undo Point"
            yield from self.create_undo_point_iter()
            return op

        err = None
        out = None
        try:
            out = show_loading_dialog(
                operation_wrapper,
                title,
                msg,
                self,
            )
        except OperationError as e:
            msg = f"Error running operation: {e}"
            log.info(msg)
            self.world.restore_last_undo_point()
            wx.MessageDialog(self, msg, style=wx.OK).ShowModal()
            err = e
        except OperationSuccessful as e:
            msg = str(e)
            log.info(msg)
            self.world.restore_last_undo_point()
            wx.MessageDialog(self, msg, style=wx.OK).ShowModal()
            err = e
        except OperationSilentAbort as e:
            self.world.restore_last_undo_point()
            err = e
        except Exception as e:
            log.error(traceback.format_exc())
            dialog = TracebackDialog(
                self,
                "Exception while running operation",
                str(e),
                traceback.format_exc(),
            )
            dialog.ShowModal()
            dialog.Destroy()
            err = e
            self.world.restore_last_undo_point()

        self.renderer.enable_threads()
        self.renderer.render_world.rebuild_changed()
        if err is not None and throw_exceptions:
            raise err
        return out
Esempio n. 2
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())
Esempio n. 3
0
 def _open_world(self, path: str):
     """Open a world panel add add it to the notebook"""
     if path in self._open_worlds:
         self.world_tab_holder.SetSelection(
             self.world_tab_holder.GetPageIndex(self._open_worlds[path]))
         self._disable_enable()
     else:
         try:
             world = WorldPageUI(self.world_tab_holder, path,
                                 lambda: self.close_world(path))
         except LoaderNoneMatched as e:
             log.error(f"Could not find a loader for this world.\n{e}")
             wx.MessageBox(
                 f"{lang.get('select_world.no_loader_found')}\n{e}")
         except Exception as e:
             log.error(lang.get("select_world.loading_world_failed"),
                       exc_info=True)
             dialog = TracebackDialog(
                 self,
                 lang.get("select_world.loading_world_failed"),
                 str(e),
                 traceback.format_exc(),
             )
             dialog.ShowModal()
             dialog.Destroy()
         else:
             self._open_worlds[path] = world
             self._add_world_tab(world, world.world_name)
Esempio n. 4
0
    def thread_action(self):
        # first check if there is a chunk that exists and needs rebuilding
        camera = numpy.asarray(self.camera_location)[[0, 2]]
        if self._last_rebuild_camera_location is None or numpy.sum(
            (self._last_rebuild_camera_location - camera)**2) > min(
                2048, self.render_distance * 16 - 8):
            # if the camera has moved more than 32 blocks set the rebuild flag
            self._rebuild = True
            self._last_rebuild_camera_location = camera

        chunk_coords = next(self._chunk_rebuilds)
        if chunk_coords is not None:
            # generate the chunk
            chunk = RenderChunk(
                self.context_identifier,
                self.resource_pack,
                self.level,
                self.chunk_manager.region_size,
                chunk_coords,
                self.dimension,
                self.draw_floor,
            )

            try:
                chunk.create_geometry()
            except:
                log.error(
                    f"Failed generating chunk geometry for chunk {chunk_coords}",
                    exc_info=True,
                )

            self.chunk_manager.add_render_chunk(chunk)
    def __init__(self, parent: wx.Window, world_dirs, open_world_callback, sort=True):
        super().__init__(parent)
        sizer = wx.BoxSizer(wx.VERTICAL)
        self.SetSizer(sizer)

        self.worlds = []

        world_formats = []
        for world_path in world_dirs:
            if os.path.isdir(world_path):
                try:
                    world_formats.append(load_format(world_path))
                except FormatError as e:
                    log.info(f"Could not find loader for {world_path} {e}")
                except Exception:
                    log.error(
                        f"Error loading format wrapper for {world_path} {traceback.format_exc()}"
                    )
        if sort:
            world_formats = reversed(sorted(world_formats, key=lambda f: f.last_played))

        for world_format in world_formats:
            try:
                world_button = WorldUIButton(self, world_format, open_world_callback)
                sizer.Add(
                    world_button, 0, wx.LEFT | wx.RIGHT | wx.BOTTOM | wx.EXPAND, 5
                )
                self.worlds.append(world_button)
            except Exception as e:
                log.info(f"Failed to display world button for {world_format.path} {e}")

        self.Layout()
 def _on_open_file(self, evt):
     with wx.FileDialog(
             self.canvas,
             "Open a Minecraft data file",
             wildcard="|".
             join([  # TODO: Automatically load these from the FormatWrapper classes.
                 "All files (*.construction;*.mcstructure;*.schematic)|*.construction;*.mcstructure;*.schematic",
                 "Construction file (*.construction)|*.construction",
                 "Bedrock mcstructure file (*.mcstructure)|*.mcstructure",
                 "Legacy Schematic file (*.schematic)|*.schematic",
                 "Sponge Schematic file (*.schem)|*.schem",
             ]),
             style=wx.FD_OPEN | wx.FD_FILE_MUST_EXIST,
     ) as fileDialog:
         if fileDialog.ShowModal() == wx.ID_CANCEL:
             return
         else:
             pathname = fileDialog.GetPath()
     try:
         level = amulet.load_level(pathname)
     except LoaderNoneMatched:
         wx.MessageBox(f"Could not find a matching loader for {pathname}.")
         log.error(f"Could not find a matching loader for {pathname}.")
     except Exception as e:
         log.error(
             f"Could not open {pathname}. Check the console for more details.\n{traceback.format_exc()}"
         )
         wx.MessageBox(
             f"Could not open {pathname}. Check the console for more details.\n{e}"
         )
     else:
         self.canvas.paste(level, level.dimensions[0])
    def reload_operations(self):
        """Reload all operations and repopulate the UI."""
        # store the id of the old operation
        operation_id = self.active_operation_id

        # reload the operations
        self._operations.reload()

        # repopulate the selection
        self._operation_choice.SetItems(
            {op.identifier: op.name for op in self._operations.operations}
        )

        if operation_id:
            identifiers = self._operation_choice.values

            if identifiers:
                if operation_id in identifiers:
                    self._operation_choice.SetSelection(identifiers.index(operation_id))
                else:
                    log.info(f"Operation {operation_id} was not found.")
                    self._operation_choice.SetSelection(0)
            else:
                log.error("No operations found. Something has gone wrong.")

            self._setup_operation()
            self.canvas.reset_bound_events()
Esempio n. 8
0
    def __init__(self, parent, world_dirs, open_world_callback, sort=True):
        super(WorldList, self).__init__(parent)

        self.worlds = []

        world_formats = []
        for world_path in world_dirs:
            if os.path.isdir(world_path):
                try:
                    world_formats.append(load_format(world_path))
                except FormatError as e:
                    log.info(f"Could not find loader for {world_path} {e}")
                except Exception:
                    log.error(
                        f"Error loading format wrapper for {world_path} {traceback.format_exc()}"
                    )
        if sort:
            world_formats = reversed(sorted(world_formats, key=lambda f: f.last_played))

        for world_format in world_formats:
            try:
                world_button = WorldUIButton(self, world_format, open_world_callback)
                self.add_object(world_button, 0, wx.ALL | wx.EXPAND)
                self.worlds.append(world_button)
            except Exception as e:
                log.info(f"Failed to display world button for {world_format.path} {e}")

        self.Layout()
Esempio n. 9
0
 def _load_dir(self, path: str):
     """Load all operations in a set directory."""
     os.makedirs(path, exist_ok=True)
     for obj_name in os.listdir(path):
         if obj_name in {"__init__.py", "__pycache__"}:
             continue
         obj_path = os.path.join(path, obj_name)
         if os.path.isfile(obj_path) and not obj_path.endswith(".py"):
             continue
         try:
             mod = load_module(obj_path)
         except ImportError:
             log.warning(f"Failed to import {obj_path}.\n{traceback.format_exc()}")
         else:
             if hasattr(mod, "export"):
                 export = mod.export
                 if isinstance(export, dict):
                     self._load_operation(obj_path, export)
                 elif isinstance(export, (list, tuple)):
                     for i, export_dict in export:
                         self._load_operation(f"{obj_path}[{i}]", export_dict)
                 else:
                     log.error(f"The format of export in {obj_path} is invalid.")
             else:
                 log.error(f"export is not present in {obj_path}")
 def _on_drop_files(self, evt: wx.DropFilesEvent):
     """Logic to run when a file is dropped into the canvas."""
     paths = evt.GetFiles()
     if paths:
         pathname = paths[0]
         if os.path.isfile(pathname):
             # TODO: if importing worlds get supported fix this
             try:
                 level = amulet.load_level(pathname)
             except LoaderNoneMatched:
                 msg = f"Could not find a matching loader for {pathname}."
                 wx.MessageBox(msg)
                 log.error(msg)
             except Exception as e:
                 log.error(f"Could not open {pathname}.", exc_info=True)
                 dialog = TracebackDialog(
                     self.canvas,
                     f"Could not open {pathname}.",
                     str(e),
                     traceback.format_exc(),
                 )
                 dialog.ShowModal()
                 dialog.Destroy()
             else:
                 self.canvas.paste(level, level.dimensions[0])
     evt.Skip()
Esempio n. 11
0
    def _generate_chunks(self):
        while self._enabled:
            start_time = time.time()
            # first check if there is a chunk that exists and needs rebuilding
            chunk_coords = next(
                (
                    c for c in self.render_world.chunk_coords() if
                    self.render_world.chunk_manager.render_chunk_needs_rebuild(c)
                ),
                None
            )
            if chunk_coords is not None:
                # if there was a chunk found that needs rebuilding then add the surrounding chunks for rebuilding
                # (this deals with if the chunk was deleted or the blocks up to the chunk boundary were deleted)
                for offset in [(-1, 0), (1, 0), (0, -1), (0, 1)]:
                    chunk_coords_ = (chunk_coords[0] + offset[0], chunk_coords[1] + offset[1])
                    if chunk_coords_ in self.render_world.chunk_manager:
                        self._chunk_rebuilds.add(chunk_coords_)
            elif self._chunk_rebuilds:
                # if a chunk was not found that needs rebuilding due to it changing but a previously
                # identified neighbour chunk needs rebuilding do that.
                chunk_coords = self._chunk_rebuilds.pop()
            else:
                # if no chunks need rebuilding then find a new chunk to load.
                chunk_coords = next(
                    (
                        c for c in self.render_world.chunk_coords() if
                        c not in self.render_world.chunk_manager
                    ),
                    None
                )
            if chunk_coords is not None:
                # if chunk coords is in here then remove it so it doesn't get generated twice.
                if chunk_coords in self._chunk_rebuilds:
                    self._chunk_rebuilds.remove(chunk_coords)

                # generate the chunk
                chunk = RenderChunk(
                    self.render_world,
                    self._region_size,
                    chunk_coords,
                    self.render_world.dimension,
                    self.render_world.texture
                )

                try:
                    chunk.create_geometry()
                except:
                    log.error(f'Failed generating chunk geometry for chunk {chunk_coords}', exc_info=True)

                self.render_world.chunk_manager.add_render_chunk(
                    chunk
                )
            delta_time = time.time() - start_time
            if delta_time < 1/60:
                # go to sleep so this thread doesn't lock up the main thread.
                time.sleep(1/60-delta_time)
Esempio n. 12
0
 def _load(self, export_dict: dict):
     """load the operation."""
     if not isinstance(export_dict, dict):
         log.error(f"The export for {self.identifier} is not a dictionary.")
         return
     if "name" in export_dict and isinstance(export_dict["name"], str):
         self._name = export_dict["name"]
         self._setup(export_dict)
     else:
         log.error(f"Missing or invalid name in {self.identifier}")
Esempio n. 13
0
 def tear_down_events(self):
     """Unbind all events.
     We are allowing users to bind custom events so we should have a way to reset what is bound."""
     for event, handler, source in self._bound_events:
         if source is None:
             while super().Unbind(event):
                 pass
         else:
             if not self.Unbind(event, source, handler=handler):
                 log.error(f"Failed to unbind {event}, {handler}, {source}")
     self._bound_events.clear()
Esempio n. 14
0
    def _setup(self, export_dict: dict):
        """Parse the export dictionary and setup as required."""
        options_path = os.path.abspath(
            os.path.join(
                "config",
                "edit_plugins",
                f"""{''.join(c for c in self._name if c in ValidChrs)}_{
                struct.unpack(
                    "H",
                    hashlib.sha1(
                        self.identifier.encode('utf-8')
                    ).digest()[:2]
                )[0]
                }.config""",  # generate a file name that identifiable to the operation but "unique" to the path
            ))

        if "operation" in export_dict:
            if inspect.isclass(export_dict["operation"]) and issubclass(
                    export_dict["operation"], (wx.Window, wx.Sizer)):
                operation_ui: Type[OperationUI] = export_dict.get(
                    "operation", None)
                if issubclass(operation_ui, OperationUI):
                    self._ui = lambda parent, canvas, world: operation_ui(
                        parent, canvas, world, options_path)
                    self._is_valid = True
                else:
                    log.error(
                        f'"operation" must be a subclass of edit.plugins.OperationUI. {self.identifier}'
                    )

            elif callable(export_dict["operation"]):
                operation = export_dict["operation"]
                if operation.__code__.co_argcount == 4:
                    options = export_dict.get("options", {})
                    if isinstance(options, dict):
                        self._ui = lambda parent, canvas, world: FixedFunctionUI(
                            parent, canvas, world, options_path, operation,
                            options)
                        self._is_valid = True
                    else:
                        log.error(
                            f'"operation" in export must be a dictionary if defined. {self.identifier}'
                        )
                else:
                    log.error(
                        f'"operation" function in export must have 4 inputs. {self.identifier}'
                    )
            else:
                log.error(
                    f'"operation" in export must be a callable, or a subclass of wx.Window or wx.Sizer. {self.identifier}'
                )
        else:
            log.error(
                f'"operation" is not present in export. {self.identifier}')
 def _load_module(self, obj_path: str, mod: ModuleType):
     if hasattr(mod, "export"):
         export = mod.export
         if isinstance(export, dict):
             self._load_operation(obj_path, export)
         elif isinstance(export, (list, tuple)):
             for i, export_dict in export:
                 self._load_operation(f"{obj_path}[{i}]", export_dict)
         else:
             log.error(f"The format of export in {obj_path} is invalid.")
     else:
         log.error(f"export is not present in {obj_path}")
Esempio n. 16
0
 def _open_world(self, path: str):
     """Open a world panel add add it to the notebook"""
     if path in self._open_worlds:
         self.world_tab_holder.SetSelection(
             self.world_tab_holder.FindPage(self._open_worlds[path]))
         self._disable_enable()
     else:
         try:
             world = WorldManagerUI(self.world_tab_holder, path)
         except LoaderNoneMatched as e:
             log.error(e)
             wx.MessageBox(str(e))
         else:
             self._open_worlds[path] = world
             self._add_world_tab(world, world.world_name)
Esempio n. 17
0
 def _change_options(self, evt):
     operation_path = self._operation_choice.GetAny()
     operation = operations.operations[operation_path]
     if "options" in operation.get("features", []):
         pass  # TODO: implement this
     elif "wxoptions" in operation.get("features", []):
         options = operation["wxoptions"](self, self._world(),
                                          operations.options.get(
                                              operation_path, {}))
         if isinstance(options, dict):
             operations.options[operation_path] = options
         else:
             log.error(
                 f"Plugin {operation['name']} at {operation_path} did not return options in a valid format"
             )
     evt.Skip()
Esempio n. 18
0
    def _run_main_operation(
        self,
        operation_path: str,
        operation: OperationType,
        operation_input_definitions: List[str],
        options=None,
        structure=None,
    ) -> Any:
        operation_inputs = []
        for inp in operation_input_definitions:
            if inp == "src_selection":
                selection = self._get_box()
                if selection is None:
                    return
                operation_inputs.append(selection)
            elif inp == "structure":
                operation_inputs.append(structure)
            elif inp == "options":
                if options:
                    plugins.options[operation_path] = options
                    operation_inputs.append(options)
                else:
                    operation_inputs.append(
                        plugins.options.get(operation_path, {}))

        self._canvas.disable_threads()
        try:
            out = show_loading_dialog(
                lambda: operation(self._world, self._canvas.dimension, *
                                  operation_inputs),
                f"Running Operation ?.",
                "Please wait for the operation to finish.",
                self,
            )
            self._world.create_undo_point()
            self._file_panel.update_buttons()
        except Exception as e:
            operation_info = plugins.all_operations[operation_path]
            log.error(
                f'Error occurred while running operation: {operation_info["name"]} v{operation_info["v"]}'
            )
            log.error(f"{e}\n{traceback.format_exc()}")
            wx.MessageBox(f"Error running operation: {e}")
            self._world.restore_last_undo_point()
            out = None
        self._canvas.enable_threads()
        return out
Esempio n. 19
0
    def run_operation(self,
                      operation: Callable[[], OperationReturnType],
                      title="",
                      msg="",
                      throw_exceptions=False) -> Any:
        self._disable_threads()
        err = None
        out = None
        try:
            out = show_loading_dialog(
                operation,
                title,
                msg,
                self,
            )
            self.world.create_undo_point()
            wx.PostEvent(self, CreateUndoEvent())
        except OperationError as e:
            msg = f"Error running operation: {e}"
            log.info(msg)
            self.world.restore_last_undo_point()
            wx.MessageDialog(self, msg, style=wx.OK).ShowModal()
            err = e
        except OperationSuccessful as e:
            msg = str(e)
            log.info(msg)
            self.world.restore_last_undo_point()
            wx.MessageDialog(self, msg, style=wx.OK).ShowModal()
            err = e
        except OperationSilentAbort as e:
            self.world.restore_last_undo_point()
            err = e
        except Exception as e:
            self.world.restore_last_undo_point()
            log.error(traceback.format_exc())
            wx.MessageDialog(
                self,
                f"Exception running operation: {e}\nSee the console for more details",
                style=wx.OK).ShowModal()
            err = e

        self._enable_threads()
        if err is not None and throw_exceptions:
            raise err
        return out
Esempio n. 20
0
 def _convert_method(self):
     global work_count
     try:
         out_world = world_interface.load_format(self.out_world_path)
         log.info(f'Converting world {self.world.world_path} to {out_world.world_path}')
         out_world: WorldFormatWrapper
         out_world.open()
         self.world.save(out_world, self._update_loading_bar)
         out_world.close()
         message = 'World conversion completed'
         log.info(f'Finished converting world {self.world.world_path} to {out_world.world_path}')
     except Exception as e:
         message = f'Error during conversion\n{e}'
         log.error(message, exc_info=True)
     self._update_loading_bar(0, 100)
     self.convert_button.Enable()
     wx.MessageBox(
         message
     )
     work_count -= 1
Esempio n. 21
0
 def _on_drop_files(self, evt: wx.DropFilesEvent):
     paths = evt.GetFiles()
     if paths:
         pathname = paths[0]
         if os.path.isfile(pathname):
             # TODO: if importing worlds get supported fix this
             try:
                 level = amulet.load_level(pathname)
             except LoaderNoneMatched:
                 wx.MessageBox(f"Could not find a matching loader for {pathname}.")
                 log.error(f"Could not find a matching loader for {pathname}.")
             except Exception as e:
                 wx.MessageBox(
                     f"Could not open {pathname}. Check the console for more details.\n{e}"
                 )
                 log.error(
                     f"Could not open {pathname}. Check the console for more details.\n{traceback.format_exc()}"
                 )
             else:
                 self.canvas.paste(level, level.dimensions[0])
     evt.Skip()
 def _setup_operation(self):
     """Remove the old operation and create the UI for the new operation."""
     operation_path = self.active_operation_id
     if operation_path:
         # only reload the operation if the
         operation = self._operations[operation_path]
         if self._active_operation is not None:
             self._active_operation.disable()
         self._operation_sizer.Clear(delete_windows=True)
         try:
             self._active_operation = operation(
                 self.canvas, self.canvas, self.canvas.world
             )
             self._operation_sizer.Add(
                 self._active_operation, *self._active_operation.wx_add_options
             )
             self._active_operation.enable()
         except Exception as e:
             # If something went wrong clear the created UI
             self._active_operation = None
             self._operation_sizer.Clear(delete_windows=True)
             for window in self.canvas.GetChildren():
                 window: wx.Window
                 # remove orphaned windows.
                 # If the Sizer.Add method was not run it will not be in self._operation_sizer
                 if window.GetContainingSizer() is None:
                     window.Destroy()
             log.error("Error loading Operation UI.", exc_info=True)
             dialog = TracebackDialog(
                 self.canvas,
                 "Error loading Operation UI.",
                 str(e),
                 traceback.format_exc(),
             )
             dialog.ShowModal()
             dialog.Destroy()
         finally:
             self._last_active_operation_id = operation.identifier
             self.Layout()
Esempio n. 23
0
 def _convert_method(self):
     global work_count
     try:
         out_world = load_format(self.out_world_path)
         log.info(
             f"Converting world {self.world.level_path} to {out_world.path}"
         )
         out_world: WorldFormatWrapper
         out_world.open()
         self.world.save(out_world, self._update_loading_bar)
         out_world.close()
         message = lang.get("program_convert.conversion_completed")
         log.info(
             f"Finished converting world {self.world.level_path} to {out_world.path}"
         )
     except Exception as e:
         message = f"Error during conversion\n{e}"
         log.error(message, exc_info=True)
     self._update_loading_bar(0, 100)
     self.convert_button.Enable()
     wx.MessageBox(message)
     work_count -= 1
Esempio n. 24
0
 def _open_world(self, path: str):
     """Open a world panel add add it to the notebook"""
     if path in self._open_worlds:
         self.world_tab_holder.SetSelection(
             self.world_tab_holder.GetPageIndex(self._open_worlds[path]))
         self._disable_enable()
     else:
         try:
             world = WorldPageUI(self.world_tab_holder, path,
                                 lambda: self.close_world(path))
         except LoaderNoneMatched as e:
             log.error(f"Could not find a loader for this world.\n{e}")
             wx.MessageBox(f"Could not find a loader for this world.\n{e}")
         except Exception as e:
             log.error(
                 f"Error loading world.\n{e}\n{traceback.format_exc()}")
             wx.MessageBox(
                 f"Error loading world. Check the console for more details.\n{e}"
             )
         else:
             self._open_worlds[path] = world
             self._add_world_tab(world, world.world_name)
Esempio n. 25
0
    def _get_block_info_message(self) -> str:
        x, y, z = self.cursor_location
        try:
            block = self.world.get_block(x, y, z, self.dimension)
            chunk = self.world.get_chunk(x >> 4, z >> 4, self.dimension)
            block_entity = chunk.block_entities.get((x, y, z), None)
            platform = self.world.world_wrapper.platform
            version = self.world.world_wrapper.version
            translator = self.world.translation_manager.get_version(
                platform,
                version,
            )
            (
                version_block,
                version_block_entity,
                _,
            ) = translator.block.from_universal(block,
                                                block_entity,
                                                block_location=(x, y, z))
            if isinstance(version, tuple):
                version_str = ".".join(str(v) for v in version[:4])
            else:
                version_str = str(version)
            block_data_text = f"x: {x}, y: {y}, z: {z}\n\n{platform.capitalize()} {version_str}\n{version_block}"
            if version_block_entity:
                version_block_entity_str = str(version_block_entity)
                block_data_text = f"{block_data_text}\n{version_block_entity_str}"

            block_data_text = f"{block_data_text}\n\nUniversal\n{block}"
            if block_entity:
                block_entity_str = str(block_entity)
                block_data_text = f"{block_data_text}\n{block_entity_str}"

            if chunk.biomes.dimension == 2:
                biome = chunk.biomes[x % 16, z % 16]
                try:
                    block_data_text = (
                        f"{block_data_text}\n\nBiome: {self.world.biome_palette[biome]}"
                    )
                except Exception as e:
                    log.error(e)
            elif chunk.biomes.dimension == 3:
                biome = chunk.biomes[(x % 16) // 4, y // 4, (z % 16) // 4]
                try:
                    block_data_text = (
                        f"{block_data_text}\n\nBiome: {self.world.biome_palette[biome]}"
                    )
                except Exception as e:
                    log.error(e)

        except Exception as e:
            log.error(e)
            return str(e)
        else:
            return block_data_text
Esempio n. 26
0
 def _setup(self, export_dict: dict):
     """Parse the export dictionary and setup as required."""
     if "operation" in export_dict:
         if callable(export_dict["operation"]):
             operation = export_dict["operation"]
             if operation.__code__.co_argcount == 3:
                 self._operation = operation
                 self._is_valid = True
             else:
                 log.error(
                     f'"operation" function in export must have 3 inputs. {self.identifier}'
                 )
         else:
             log.error(
                 f'"operation" in export must be a callable. {self.identifier}'
             )
     else:
         log.error(
             f'"operation" is not present in export. {self.identifier}')
Esempio n. 27
0
    def _setup(self) -> Generator[OperationYieldType, None, None]:
        """Set up objects that take a while to set up."""
        packs = []
        user_packs = [
            load_resource_pack(os.path.join("resource_packs", rp))
            for rp in os.listdir("resource_packs")
            if os.path.isdir(os.path.join("resource_packs", rp))
        ]
        if (
            self.world.level_wrapper.platform == "bedrock"
            and experimental_bedrock_resources
        ):
            packs.append(
                load_resource_pack(
                    os.path.join(
                        os.path.dirname(amulet_edit.__file__),
                        "amulet_resource_pack",
                        "bedrock",
                    )
                )
            )
            yield 0.1, lang.get(
                "program_3d_edit.canvas.downloading_bedrock_vanilla_resource_pack"
            )
            gen = get_bedrock_vanilla_latest_iter()
            try:
                while True:
                    yield next(gen) * 0.4 + 0.1
            except StopIteration as e:
                packs.append(e.value)
            yield 0.5, lang.get("program_3d_edit.canvas.loading_resource_packs")

            packs += [
                pack for pack in user_packs if isinstance(pack, BedrockResourcePack)
            ]
            packs.append(get_bedrock_vanilla_fix())

            translator = self.world.translation_manager.get_version(
                "bedrock", (999, 0, 0)
            )
        else:
            packs.append(
                load_resource_pack(
                    os.path.join(
                        os.path.dirname(amulet_edit.__file__),
                        "amulet_resource_pack",
                        "java",
                    )
                )
            )
            yield 0.1, lang.get(
                "program_3d_edit.canvas.downloading_java_vanilla_resource_pack"
            )
            gen = get_java_vanilla_latest_iter()
            try:
                while True:
                    yield next(gen) * 0.4 + 0.1
            except StopIteration as e:
                packs.append(e.value)
            except Exception as e:
                log.error(
                    str(e),
                    exc_info=True,
                )
                wx.MessageBox(
                    f"{lang.get('program_3d_edit.canvas.downloading_java_vanilla_resource_pack_failed')}\n{e}"
                )

            yield 0.5, lang.get("program_3d_edit.canvas.loading_resource_packs")
            packs += [pack for pack in user_packs if isinstance(pack, JavaResourcePack)]
            packs.append(get_java_vanilla_fix())

            translator = self.world.translation_manager.get_version("java", (999, 0, 0))

        resource_pack = load_resource_pack_manager(packs, load=False)
        for i in resource_pack.reload():
            yield i / 4 + 0.5

        opengl_resource_pack = OpenGLResourcePack(resource_pack, translator)

        yield 0.75, lang.get("program_3d_edit.canvas.creating_texture_atlas")
        for i in opengl_resource_pack.setup():
            yield i / 4 + 0.75

        yield 1.0, lang.get("program_3d_edit.canvas.setting_up_renderer")

        self._renderer: Optional[Renderer] = Renderer(
            self,
            self.world,
            self.context_identifier,
            opengl_resource_pack,
        )
    def _setup(self) -> Generator[OperationYieldType, None, None]:
        """Set up objects that take a while to set up."""
        packs = []
        user_packs = [
            load_resource_pack(os.path.join("resource_packs", rp))
            for rp in os.listdir("resource_packs")
            if os.path.isdir(os.path.join("resource_packs", rp))
        ]
        if (self.world.level_wrapper.platform == "bedrock"
                and experimental_bedrock_resources):
            packs.append(
                load_resource_pack(
                    os.path.join(
                        os.path.dirname(amulet_edit.__file__),
                        "amulet_resource_pack",
                        "bedrock",
                    )))
            yield 0.1, "Downloading Bedrock vanilla resource pack"
            gen = get_bedrock_vanilla_latest_iter()
            try:
                while True:
                    yield next(gen) * 0.4 + 0.1
            except StopIteration as e:
                packs.append(e.value)
            yield 0.5, "Loading resource packs"

            packs += [
                pack for pack in user_packs
                if isinstance(pack, BedrockResourcePack)
            ]
            packs.append(get_bedrock_vanilla_fix())

            translator = self.world.translation_manager.get_version(
                "bedrock", (999, 0, 0))
        else:
            packs.append(
                load_resource_pack(
                    os.path.join(
                        os.path.dirname(amulet_edit.__file__),
                        "amulet_resource_pack",
                        "java",
                    )))
            yield 0.1, "Downloading Java vanilla resource pack"
            gen = get_java_vanilla_latest_iter()
            try:
                while True:
                    yield next(gen) * 0.4 + 0.1
            except StopIteration as e:
                packs.append(e.value)
            except Exception as e:
                log.error(
                    str(e),
                    exc_info=True,
                )
                wx.MessageBox(
                    "Failed to download the latest Java resource pack.\n"
                    "Check your internet connection and restart Amulet.\n"
                    "Check the console for more details.\n"
                    f"{e}")

            yield 0.5, "Loading resource packs"
            packs += [
                pack for pack in user_packs
                if isinstance(pack, JavaResourcePack)
            ]
            packs.append(get_java_vanilla_fix())

            translator = self.world.translation_manager.get_version(
                "java", (999, 0, 0))

        resource_pack = load_resource_pack_manager(packs, load=False)
        for i in resource_pack.reload():
            yield i / 4 + 0.5

        opengl_resource_pack = OpenGLResourcePack(resource_pack, translator)

        yield 0.75, "Creating texture atlas"
        for i in opengl_resource_pack.setup():
            yield i / 4 + 0.75

        yield 1.0, "Setting up renderer"

        self._renderer: Optional[Renderer] = Renderer(
            self,
            self.world,
            self.context_identifier,
            opengl_resource_pack,
        )
Esempio n. 29
0
    def _run_operation(self, operation_path=None) -> Any:
        if operation_path is None:
            operation_path = self._operation_options.operation
        operation = plugins.all_operations[operation_path]
        features = operation.get("features", [])
        operation_input_definitions = operation.get("inputs", [])
        if any(feature in features for feature in ("dst_location_absolute", )):
            if "structure_callable" in operation:
                operation_inputs = []
                for inp in operation.get("structure_callable_inputs", []):
                    if inp == "src_selection":
                        selection = self._get_box()
                        if selection is None:
                            return
                        operation_inputs.append(selection)

                    elif inp == "options":
                        operation_inputs.append(
                            plugins.options.get(operation_path, {}))

                self._operation_options.Disable()

                self._canvas.disable_threads()
                try:
                    structure = show_loading_dialog(
                        lambda: operation["structure_callable"]
                        (self._world, self._canvas.dimension, *operation_inputs
                         ),
                        f'Running structure operation for {operation["name"]}.',
                        "Please wait for the operation to finish.",
                        self,
                    )
                except Exception as e:
                    log.error(
                        f"Error running structure operation: {e}\n{traceback.format_exc()}"
                    )
                    wx.MessageBox(f"Error running structure operation: {e}")
                    self._world.restore_last_undo_point()
                    self._canvas.enable_threads()
                    return
                self._canvas.enable_threads()

                self._operation_options.Enable()
                if not isinstance(structure, Structure):
                    log.error(
                        "Object returned from structure_callable was not a Structure. Aborting."
                    )
                    wx.MessageBox(
                        "Object returned from structure_callable was not a Structure. Aborting."
                    )
                    return
            else:
                selection = self._get_box()
                if selection is None:
                    return
                self._operation_options.Disable()
                structure = show_loading_dialog(
                    lambda: Structure.from_world(self._world, selection, self.
                                                 _canvas.dimension),
                    f'Running structure operation for {operation["name"]}.',
                    "Copying structure from world.",
                    self,
                )
                self._operation_options.Enable()

            if "dst_location_absolute" in features:
                # trigger UI to show select box UI
                self._operation_options.enable_select_destination_ui(
                    operation_path,
                    operation["operation"],
                    operation_input_definitions,
                    structure,
                    plugins.options.get(operation_path, {}),
                )
            else:
                # trigger UI to show select box multiple UI
                raise NotImplementedError

        else:
            self._operation_options.Disable()
            out = self._run_main_operation(operation_path,
                                           operation["operation"],
                                           operation_input_definitions)
            self._operation_options.Enable()
            return out