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
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()
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)
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