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(
                        world_interface.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()
    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.context_identifier,
                    self.render_world.resource_pack,
                    self.render_world.world,
                    self._region_size,
                    chunk_coords,
                    self.render_world.dimension,
                )

                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)
    def run_operation(
        self,
        operation: Callable[[], OperationReturnType],
        title="Amulet",
        msg="Running Operation",
        throw_exceptions=False,
    ) -> Any:
        def operation_wrapper():
            yield 0, "Disabling Threads"
            self._disable_threads()
            yield 0, msg
            op = operation()
            if isinstance(op, GeneratorType):
                yield from op
            return op

        err = None
        out = None
        try:
            out = show_loading_dialog(
                operation_wrapper,
                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
Example #4
0
 def reset_bound_events(self):
     """Unbind all events and re-bind the default events.
     We are allowing users to bind custom events so we should have a way to reset what is bound."""
     handled_events = set()
     for event, handler, source in self._bound_events:
         if source is None:
             if event not in handled_events:
                 handled_events.add(event)
                 super().Unbind(event)
         else:
             if not self.Unbind(event, source, handler=handler):
                 log.error(f"Failed to unbind {event}, {handler}, {source}")
     self._bind_base_events()
Example #5
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(e)
             wx.MessageBox(str(e))
         else:
             self._open_worlds[path] = world
             self._add_world_tab(world, world.world_name)
 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.\n{e}")
         else:
             self._open_worlds[path] = world
             self._add_world_tab(world, world.world_name)
Example #7
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