def end(self): self.log.debug("Ending session") self.is_alive = False LastActivePlayerSettlementManager().remove() LastActivePlayerSettlementManager.destroy_instance() self.gui.session = None Scheduler().rem_all_classinst_calls(self) ExtScheduler().rem_all_classinst_calls(self) if horizons.main.fife.get_fife_setting("PlaySounds"): for emitter in horizons.main.fife.sound.emitter['ambient'][:]: emitter.stop() horizons.main.fife.sound.emitter['ambient'].remove(emitter) horizons.main.fife.sound.emitter['effects'].stop() horizons.main.fife.sound.emitter['speech'].stop() if hasattr(self, "cursor"): # the line below would crash uglily on ^C self.cursor.remove() self.cursor = None self.world = None self.keylistener = None self.ingame_gui = None self.view = None self.manager = None self.timer = None self.scenario_eventhandler = None Scheduler.destroy_instance() self.selected_instances = None self.selection_groups = None
def end(self): self.mainhud.mapEvents({ 'zoomIn': None, 'zoomOut': None, 'rotateRight': None, 'rotateLeft': None, 'gameMenuButton': None }) self.mainhud.hide() self.mainhud = None self._settings_tab.hide() self._settings_tab = None self.windows.close_all() self.minimap = None self.keylistener = None LastActivePlayerSettlementManager().remove() LastActivePlayerSettlementManager.destroy_instance() ZoomChanged.unsubscribe(self._update_zoom) if self.cursor: self.cursor.remove() self.cursor.end() self.cursor = None super(IngameGui, self).end()
def end(self): self.log.debug("Ending session") self.is_alive = False self.gui.session = None # Has to be done here, cause the manager uses Scheduler! self.end_production_finished_icon_manager() Scheduler().rem_all_classinst_calls(self) ExtScheduler().rem_all_classinst_calls(self) if horizons.globals.fife.get_fife_setting("PlaySounds"): for emitter in horizons.globals.fife.sound.emitter['ambient'][:]: emitter.stop() horizons.globals.fife.sound.emitter['ambient'].remove(emitter) horizons.globals.fife.sound.emitter['effects'].stop() horizons.globals.fife.sound.emitter['speech'].stop() if hasattr(self, "cursor"): # the line below would crash uglily on ^C self.cursor.remove() if hasattr(self, 'cursor') and self.cursor is not None: self.cursor.end() # these will call end() if the attribute still exists by the LivingObject magic self.ingame_gui = None # keep this before world LastActivePlayerSettlementManager().remove() # keep after ingame_gui LastActivePlayerSettlementManager.destroy_instance() self.cursor = None self.world.end() # must be called before the world ref is gone self.world = None self.keylistener = None self.view = None self.manager = None self.timer = None self.scenario_eventhandler = None Scheduler().end() Scheduler.destroy_instance() self.selected_instances = None self.selection_groups = None self.status_icon_manager.end() self.status_icon_manager = None horizons.main._modules.session = None self._clear_caches() # subscriptions shouldn't survive listeners (except the main Gui) self.gui.unsubscribe() AutosaveIntervalChanged.unsubscribe(self._on_autosave_interval_changed) MessageBus().reset() self.gui.subscribe()
def end(self): self.log.debug("Ending session") self.is_alive = False self.gui.session = None Scheduler().rem_all_classinst_calls(self) ExtScheduler().rem_all_classinst_calls(self) if horizons.main.fife.get_fife_setting("PlaySounds"): for emitter in horizons.main.fife.sound.emitter['ambient'][:]: emitter.stop() horizons.main.fife.sound.emitter['ambient'].remove(emitter) horizons.main.fife.sound.emitter['effects'].stop() horizons.main.fife.sound.emitter['speech'].stop() if hasattr(self, "cursor"): # the line below would crash uglily on ^C self.cursor.remove() if hasattr(self, 'cursor') and self.cursor is not None: self.cursor.end() # these will call end() if the attribute still exists by the LivingObject magic self.ingame_gui = None # keep this before world LastActivePlayerSettlementManager().remove() # keep after ingame_gui LastActivePlayerSettlementManager.destroy_instance() self.cursor = None try: # This is likely to throw when the game state is invalid. # Try to continue cleanup afterwards even if this fails. # NOTE: This is not a proper solution, separating sessions by design (e.g. single processes) would be. self.world.end() # must be called before the world ref is gone except Exception: import traceback traceback.print_exc() print 'Exception on world end(), trying to continue to cleanup' self.world = None self.keylistener = None self.view = None self.manager = None self.timer = None self.scenario_eventhandler = None Scheduler().end() Scheduler.destroy_instance() self.selected_instances = None self.selection_groups = None self.status_icon_manager = None self.message_bus = None horizons.main._modules.session = None self._clear_caches()
def end(self): # unsubscribe early, to avoid messages coming in while we're shutting down SpeedChanged.unsubscribe(self._on_speed_changed) NewDisaster.unsubscribe(self._on_new_disaster) NewSettlement.unsubscribe(self._on_new_settlement) PlayerLevelUpgrade.unsubscribe(self._on_player_level_upgrade) MineEmpty.unsubscribe(self._on_mine_empty) ZoomChanged.unsubscribe(self._update_zoom) GuiAction.unsubscribe(self._on_gui_click_action) GuiHover.unsubscribe(self._on_gui_hover_action) GuiCancelAction.unsubscribe(self._on_gui_cancel_action) self.mainhud.mapEvents({ 'zoomIn' : None, 'zoomOut' : None, 'rotateRight' : None, 'rotateLeft': None, 'destroy_tool' : None, 'build' : None, 'diplomacyButton' : None, 'gameMenuButton' : None }) self.mainhud.hide() self.mainhud = None self.windows.close_all() self.message_widget = None self.minimap = None self.resource_overview.end() self.resource_overview = None self.keylistener = None self.cityinfo.end() self.cityinfo = None self.hide_menu() if self.cursor: self.cursor.remove() self.cursor.end() self.cursor = None LastActivePlayerSettlementManager().remove() LastActivePlayerSettlementManager.destroy_instance() self.production_finished_icon_manager.end() self.production_finished_icon_manager = None self.status_icon_manager.end() self.status_icon_manager = None super(IngameGui, self).end()
def __init__(self, session): self.session = session self.cursor = None self.coordinates_tooltip = None self.keylistener = IngameKeyListener(self.session) # used by NavigationTool LastActivePlayerSettlementManager.create_instance(self.session) # Mocks needed to act like the real IngameGui self.show_menu = Dummy self.hide_menu = Dummy # a logbook Dummy is necessary for message_widget to work self.logbook = Dummy self.mainhud = load_uh_widget("minimap.xml") self.mainhud.position_technique = "right+0:top+0" icon = self.mainhud.findChild(name="minimap") self.minimap = Minimap( icon, targetrenderer=horizons.globals.fife.targetrenderer, imagemanager=horizons.globals.fife.imagemanager, session=self.session, view=self.session.view, ) self.mainhud.mapEvents( { "zoomIn": self.session.view.zoom_in, "zoomOut": self.session.view.zoom_out, "rotateRight": Callback.ChainedCallbacks(self.session.view.rotate_right, self.minimap.rotate_right), "rotateLeft": Callback.ChainedCallbacks(self.session.view.rotate_left, self.minimap.rotate_left), "gameMenuButton": self.toggle_pause, } ) self.mainhud.show() ZoomChanged.subscribe(self._update_zoom) # Hide unnecessary buttons in hud for widget in ("build", "speedUp", "speedDown", "destroy_tool", "diplomacyButton", "logbook"): self.mainhud.findChild(name=widget).hide() self.windows = WindowManager() self.message_widget = MessageWidget(self.session) self.pausemenu = PauseMenu(self.session, self, self.windows, in_editor_mode=True) self.help_dialog = HelpDialog(self.windows)
def end(self): self.log.debug("Ending session") self.is_alive = False self.gui.session = None Scheduler().rem_all_classinst_calls(self) ExtScheduler().rem_all_classinst_calls(self) if horizons.main.fife.get_fife_setting("PlaySounds"): for emitter in horizons.main.fife.sound.emitter['ambient'][:]: emitter.stop() horizons.main.fife.sound.emitter['ambient'].remove(emitter) horizons.main.fife.sound.emitter['effects'].stop() horizons.main.fife.sound.emitter['speech'].stop() if hasattr(self, "cursor"): # the line below would crash uglily on ^C self.cursor.remove() if hasattr(self, 'cursor') and self.cursor is not None: self.cursor.end() # these will call end() if the attribute still exists by the LivingObject magic self.ingame_gui = None # keep this before world LastActivePlayerSettlementManager().remove() # keep after ingame_gui LastActivePlayerSettlementManager.destroy_instance() self.cursor = None self.world.end() # must be called before the world ref is gone self.world = None self.keylistener = None self.view = None self.manager = None self.timer = None self.scenario_eventhandler = None Scheduler().end() Scheduler.destroy_instance() self.selected_instances = None self.selection_groups = None self.status_icon_manager = None self.message_bus = None horizons.main._modules.session = None self._clear_caches()
def __init__(self, gui, db, rng_seed=None): super(Session, self).__init__() assert isinstance(db, horizons.util.uhdbaccessor.UhDbAccessor) self.log.debug("Initing session") self.gui = gui # main gui, not ingame gui self.db = db # main db for game data (game.sql) # this saves how often the current game has been saved self.savecounter = 0 self.is_alive = True self._clear_caches() #game self.random = self.create_rng(rng_seed) assert isinstance(self.random, Random) self.timer = self.create_timer() Scheduler.create_instance(self.timer) self.manager = self.create_manager() self.view = View(self) Entities.load(self.db) self.scenario_eventhandler = ScenarioEventHandler(self) # dummy handler with no events self.campaign = {} #GUI self.gui.session = self self.ingame_gui = IngameGui(self, self.gui) self.keylistener = IngameKeyListener(self) self.coordinates_tooltip = None self.display_speed() LastActivePlayerSettlementManager.create_instance(self) self.status_icon_manager = StatusIconManager( renderer=self.view.renderer['GenericRenderer'], layer=self.view.layers[LAYERS.OBJECTS] ) self.production_finished_icon_manager = None self.create_production_finished_icon_manager() self.selected_instances = set() self.selection_groups = [set() for _ in range(10)] # List of sets that holds the player assigned unit groups. self._old_autosave_interval = None
def __init__(self, gui, db, rng_seed=None): super(Session, self).__init__() assert isinstance(db, horizons.util.uhdbaccessor.UhDbAccessor) self.log.debug("Initing session") self.gui = gui # main gui, not ingame gui self.db = db # main db for game data (game.sql) # this saves how often the current game has been saved self.savecounter = 0 self.is_alive = True self._clear_caches() #game self.random = self.create_rng(rng_seed) assert isinstance(self.random, Random) self.timer = self.create_timer() Scheduler.create_instance(self.timer) self.manager = self.create_manager() self.view = View(self) Entities.load(self.db) self.scenario_eventhandler = ScenarioEventHandler( self) # dummy handler with no events #GUI self.gui.session = self self.ingame_gui = IngameGui(self, self.gui) self.keylistener = IngameKeyListener(self) self.coordinates_tooltip = None self.display_speed() LastActivePlayerSettlementManager.create_instance(self) self.status_icon_manager = StatusIconManager( renderer=self.view.renderer['GenericRenderer'], layer=self.view.layers[LAYERS.OBJECTS]) self.production_finished_icon_manager = None self.create_production_finished_icon_manager() self.selected_instances = set() self.selection_groups = [ set() for _ in range(10) ] # List of sets that holds the player assigned unit groups. self._old_autosave_interval = None
def load(self, db): self.message_widget.load(db) self.logbook.load(db) self.resource_overview.load(db) cur_settlement = LastActivePlayerSettlementManager( ).get_current_settlement() self._cityinfo_set(HoverSettlementChanged(self, cur_settlement)) self.minimap.draw() # update minimap to new world
def show(self): self.__remove_changelisteners() self.__current_settlement = LastActivePlayerSettlementManager().get() self.__add_changelisteners() self.__class__.last_active_build_tab = self.tabindex super(BuildTab, self).show() button = self.widget.child_finder("switch_build_menu_config_button") self._set_switch_layout_button_image(button) button.capture(self._switch_build_menu_config)
def __init__(self, gui, db, rng_seed=None): super(Session, self).__init__() assert isinstance(gui, Gui) assert isinstance(db, horizons.util.uhdbaccessor.UhDbAccessor) self.log.debug("Initing session") self.gui = gui # main gui, not ingame gui self.db = db # main db for game data (game.sql) # this saves how often the current game has been saved self.savecounter = 0 self.is_alive = True self.message_bus = MessageBus() # misc WorldObject.reset() NamedComponent.reset() AIPlayer.clear_caches() #game self.random = self.create_rng(rng_seed) assert isinstance(self.random, Random) self.timer = self.create_timer() Scheduler.create_instance(self.timer) self.manager = self.create_manager() self.view = View(self) Entities.load(self.db) self.scenario_eventhandler = ScenarioEventHandler(self) # dummy handler with no events self.campaign = {} #GUI self.gui.session = self self.ingame_gui = IngameGui(self, self.gui) self.keylistener = IngameKeyListener(self) self.coordinates_tooltip = None self.display_speed() LastActivePlayerSettlementManager.create_instance(self) self.status_icon_manager = StatusIconManager(self) self.selected_instances = set() self.selection_groups = [set()] * 10 # List of sets that holds the player assigned unit groups.
def end(self): self.mainhud.mapEvents({ 'zoomIn': None, 'zoomOut': None, 'rotateRight': None, 'rotateLeft': None, 'gameMenuButton': None }) self.minimap = None self.keylistener = None LastActivePlayerSettlementManager().remove() LastActivePlayerSettlementManager.destroy_instance() self.session.view.remove_change_listener(self._update_zoom) if self.cursor: self.cursor.remove() self.cursor.end() self.cursor = None super(IngameGui, self).end()
def __init__(self, session, main_gui): self.session = session self.main_gui = main_gui self.cursor = None self.coordinates_tooltip = None self.keylistener = IngameKeyListener(self.session) # used by NavigationTool LastActivePlayerSettlementManager.create_instance(self.session) # Mocks needed to act like the real IngameGui self.show_menu = Dummy self.hide_menu = Dummy self.mainhud = load_uh_widget('minimap.xml') self.mainhud.position_technique = "right+0:top+0" icon = self.mainhud.findChild(name="minimap") self.minimap = Minimap(icon, targetrenderer=horizons.globals.fife.targetrenderer, imagemanager=horizons.globals.fife.imagemanager, session=self.session, view=self.session.view) self.mainhud.mapEvents({ 'zoomIn': self.session.view.zoom_in, 'zoomOut': self.session.view.zoom_out, 'rotateRight': Callback.ChainedCallbacks(self.session.view.rotate_right, self.minimap.rotate_right), 'rotateLeft': Callback.ChainedCallbacks(self.session.view.rotate_left, self.minimap.rotate_left), 'gameMenuButton': self.toggle_pause, }) self.mainhud.show() self.session.view.add_change_listener(self._update_zoom) # Hide unnecessary buttons in hud for widget in ("build", "speedUp", "speedDown", "destroy_tool", "diplomacyButton", "logbook"): self.mainhud.findChild(name=widget).hide() self.save_map_dialog = SaveMapDialog(self.main_gui, self, self.session) self.pausemenu = PauseMenu(self.session, self.main_gui, self, in_editor_mode=True)
def close_construction_mode(self, update_slots=True): """Return to normal configuration""" self.construction_mode = False if update_slots: # cleanup self._drop_cost_labels() self.set_inventory_instance(None) #self._update_gold() self.gold_gui.show() self._update_gold(force=True) # reshow last settlement self.set_inventory_instance( LastActivePlayerSettlementManager().get(get_current_pos=True) )
def __init__(self, db, rng_seed=None): """ Unfortunately, right now there is no other way to setup Dummy versions of the GUI, View etc., unless we want to patch the references in the session module. """ super(LivingObject, self).__init__() self.gui = Dummy() self.db = db self.savecounter = 0 # this is a new game. self.is_alive = True WorldObject.reset() NamedComponent.reset() AIPlayer.clear_caches() # Game self.random = self.create_rng(rng_seed) self.timer = self.create_timer() Scheduler.create_instance(self.timer) ExtScheduler.create_instance(Dummy) self.manager = self.create_manager() self.view = Dummy() self.view.renderer = Dummy() Entities.load(self.db) self.scenario_eventhandler = Dummy() self.campaign = {} self.message_bus = MessageBus() self.status_icon_manager = StatusIconManager(self) # GUI self.gui.session = self self.ingame_gui = Dummy() LastActivePlayerSettlementManager.create_instance(self) self.selected_instances = set() self.selection_groups = [set()] * 10 # List of sets that holds the player assigned unit groups. GAME_SPEED.TICKS_PER_SECOND = 16
def end(self): self.mainhud.mapEvents({ 'zoomIn' : None, 'zoomOut' : None, 'rotateRight' : None, 'rotateLeft': None, 'destroy_tool' : None, 'build' : None, 'diplomacyButton' : None, 'gameMenuButton' : None }) self.message_widget = None self.minimap = None self.resource_overview.end() self.resource_overview = None self.keylistener = None self.cityinfo.end() self.cityinfo = None self.hide_menu() SettlerUpdate.unsubscribe(self._on_settler_level_change) SpeedChanged.unsubscribe(self._on_speed_changed) self.session.view.remove_change_listener(self._update_zoom) if self.cursor: self.cursor.remove() self.cursor.end() self.cursor = None LastActivePlayerSettlementManager().remove() LastActivePlayerSettlementManager.destroy_instance() self.production_finished_icon_manager.end() self.production_finished_icon_manager = None self.status_icon_manager.end() self.status_icon_manager = None super(IngameGui, self).end()
def load(self, db): self.message_widget.load(db) self.logbook.load(db) self.resource_overview.load(db) if self.session.is_game_loaded(): LastActivePlayerSettlementManager().load(db) cur_settlement = LastActivePlayerSettlementManager( ).get_current_settlement() self.cityinfo.set_settlement(cur_settlement) self.minimap.draw() # update minimap to new world self.current_cursor = 'default' self.cursor = mousetools.SelectionTool(self.session) # Set cursor correctly, menus might need to be opened. # Open menus later; they may need unit data not yet inited self.cursor.apply_select() self.load_selection(db) if not self.session.is_game_loaded(): # Fire a message for new world creation self.message_widget.add('NEW_WORLD') # Show message when the relationship between players changed def notify_change(caller, old_state, new_state, a, b): player1 = "{0!s}".format(a.name) player2 = "{0!s}".format(b.name) data = {'player1': player1, 'player2': player2} string_id = 'DIPLOMACY_STATUS_{old}_{new}'.format( old=old_state.upper(), new=new_state.upper()) self.message_widget.add(string_id=string_id, message_dict=data) self.session.world.diplomacy.add_diplomacy_status_changed_listener( notify_change)
def mouseMoved(self, evt): if not self.session.world.inited: return self.consumed_by_widgets = evt.isConsumedByWidgets() self.tooltip.show_evt(evt) # don't overwrite this last_event_pos instance. Due to class # hierarchy, it would write to the lowest class (e.g. SelectionTool) # and the attribute in NavigationTool would be left unchanged. self.__class__.last_event_pos.set(evt.getX(), evt.getY(), 0) mousepoint = self.__class__.last_event_pos # Status menu update current = self.get_exact_world_location(evt) distance_ge = lambda a, b, epsilon: abs((a.x - b.x)**2 + (a.y - b.y)**2) >= epsilon**2 if distance_ge(current, self.last_exact_world_location, 4): # update every 4 tiles for settlement info self.last_exact_world_location = current # update res bar with settlement-related info LastActivePlayerSettlementManager().update(current) # check if instance update is scheduled if self.__class__.send_hover_instances_update: self._schedule_hover_instance_update() # Mouse scrolling x, y = 0, 0 if mousepoint.x < VIEW.AUTOSCROLL_WIDTH: x -= VIEW.AUTOSCROLL_WIDTH - mousepoint.x elif mousepoint.x > (self.session.view.cam.getViewPort().right() - VIEW.AUTOSCROLL_WIDTH): x += VIEW.AUTOSCROLL_WIDTH + mousepoint.x - self.session.view.cam.getViewPort( ).right() if mousepoint.y < VIEW.AUTOSCROLL_WIDTH: y -= VIEW.AUTOSCROLL_WIDTH - mousepoint.y elif mousepoint.y > (self.session.view.cam.getViewPort().bottom() - VIEW.AUTOSCROLL_WIDTH): y += VIEW.AUTOSCROLL_WIDTH + mousepoint.y - self.session.view.cam.getViewPort( ).bottom() x *= 10 y *= 10 self.session.view.autoscroll(x, y)
def load(self, db): from horizons.util.worldobject import WorldObject for obj in db("SELECT DISTINCT object FROM resource_overview_bar"): obj = obj[0] l = [] for pos, res in db("SELECT position, resource FROM resource_overview_bar where object=?", obj): l.append( (pos, res) ) obj = WorldObject.get_object_by_id(obj) self.resource_configurations[obj] = [ i[1] for i in sorted(l) ] # called when any game (also new ones) start # register at player inventory for gold updates inv = self.session.world.player.get_component(StorageComponent).inventory inv.add_change_listener(self._update_gold, call_listener_now=True) self.gold_gui.show() self._update_gold() # call once more to make pychan happy self.set_inventory_instance( LastActivePlayerSettlementManager().get(get_current_pos=True))
def load(self, options): """Loads a map. Key method for starting a game.""" """ TUTORIAL: Here you see how the vital game elements (and some random things that are also required) are initialised. """ if options.is_scenario: # game_identifier is a yaml file, that contains reference to actual map file self.scenario_eventhandler = ScenarioEventHandler( self, options.game_identifier) # scenario maps can be normal maps or scenario maps: map_filename = self.scenario_eventhandler.get_map_file() options.game_identifier = os.path.join( SavegameManager.scenario_maps_dir, map_filename) if not os.path.exists(options.game_identifier): options.game_identifier = os.path.join( SavegameManager.maps_dir, map_filename) options.is_map = True self.log.debug("Session: Loading from %s", options.game_identifier) savegame_db = SavegameAccessor( options.game_identifier, options.is_map) # Initialize new dbreader savegame_data = SavegameManager.get_metadata(savegame_db.db_path) self.view.resize_layers(savegame_db) # load how often the game has been saved (used to know the difference between # a loaded and a new game) self.savecounter = savegame_data.get('savecounter', 0) if savegame_data.get('rng_state', None): rng_state_list = json.loads(savegame_data['rng_state']) # json treats tuples as lists, but we need tuples here, so convert back def rec_list_to_tuple(x): if isinstance(x, list): return tuple(rec_list_to_tuple(i) for i in x) else: return x rng_state_tuple = rec_list_to_tuple(rng_state_list) # changing the rng is safe for mp, as all players have to have the same map self.random.setstate(rng_state_tuple) self.world = World( self ) # Load horizons.world module (check horizons/world/__init__.py) self.world._init(savegame_db, options.force_player_id, disasters_enabled=options.disasters_enabled) self.view.load(savegame_db) # load view if not self.is_game_loaded(): options.init_new_world(self) else: # try to load scenario data self.scenario_eventhandler.load(savegame_db) self.manager.load( savegame_db ) # load the manager (there might me old scheduled ticks). self.world.init_fish_indexer() # now the fish should exist if self.is_game_loaded(): LastActivePlayerSettlementManager().load( savegame_db) # before ingamegui self.ingame_gui.load( savegame_db) # load the old gui positions and stuff for instance_id in savegame_db( "SELECT id FROM selected WHERE `group` IS NULL" ): # Set old selected instance obj = WorldObject.get_object_by_id(instance_id[0]) self.selected_instances.add(obj) obj.get_component(SelectableComponent).select() for group in xrange(len( self.selection_groups)): # load user defined unit groups for instance_id in savegame_db( "SELECT id FROM selected WHERE `group` = ?", group): self.selection_groups[group].add( WorldObject.get_object_by_id(instance_id[0])) # cursor has to be inited last, else player interacts with a not inited world with it. self.current_cursor = 'default' self.cursor = SelectionTool(self) # Set cursor correctly, menus might need to be opened. # Open menus later; they may need unit data not yet inited self.cursor.apply_select() Scheduler().before_ticking() savegame_db.close() assert hasattr(self.world, "player"), 'Error: there is no human player' """
def __init__(self, session): super(IngameGui, self).__init__() self.session = session assert isinstance(self.session, horizons.session.Session) self.settlement = None self._old_menu = None self.cursor = None self.coordinates_tooltip = None self.keylistener = IngameKeyListener(self.session) self.cityinfo = CityInfo(self) LastActivePlayerSettlementManager.create_instance(self.session) self.message_widget = MessageWidget(self.session) # Windows self.windows = WindowManager() self.show_popup = self.windows.show_popup self.show_error_popup = self.windows.show_error_popup self.logbook = LogBook(self.session, self.windows) self.players_overview = PlayersOverview(self.session) self.players_settlements = PlayersSettlements(self.session) self.players_ships = PlayersShips(self.session) self.chat_dialog = ChatDialog(self.windows, self.session) self.change_name_dialog = ChangeNameDialog(self.windows, self.session) self.pausemenu = PauseMenu(self.session, self, self.windows, in_editor_mode=False) self.help_dialog = HelpDialog(self.windows, session=self.session) # Icon manager self.status_icon_manager = StatusIconManager( renderer=self.session.view.renderer['GenericRenderer'], layer=self.session.view.layers[LAYERS.OBJECTS] ) self.production_finished_icon_manager = ProductionFinishedIconManager( renderer=self.session.view.renderer['GenericRenderer'], layer=self.session.view.layers[LAYERS.OBJECTS] ) # 'minimap' is the guichan gui around the actual minimap, which is saved # in self.minimap self.mainhud = load_uh_widget('minimap.xml') self.mainhud.position_technique = "right:top" icon = self.mainhud.findChild(name="minimap") self.minimap = Minimap(icon, targetrenderer=horizons.globals.fife.targetrenderer, imagemanager=horizons.globals.fife.imagemanager, session=self.session, view=self.session.view) def speed_up(): SpeedUpCommand().execute(self.session) def speed_down(): SpeedDownCommand().execute(self.session) self.mainhud.mapEvents({ 'zoomIn' : self.session.view.zoom_in, 'zoomOut' : self.session.view.zoom_out, 'rotateRight' : Callback.ChainedCallbacks(self.session.view.rotate_right, self.minimap.rotate_right), 'rotateLeft' : Callback.ChainedCallbacks(self.session.view.rotate_left, self.minimap.rotate_left), 'speedUp' : speed_up, 'speedDown' : speed_down, 'destroy_tool' : self.toggle_destroy_tool, 'build' : self.show_build_menu, 'diplomacyButton' : self.show_diplomacy_menu, 'gameMenuButton' : self.toggle_pause, 'logbook' : lambda: self.windows.toggle(self.logbook) }) self.mainhud.show() hotkey_replacements = { 'rotateRight': 'ROTATE_RIGHT', 'rotateLeft': 'ROTATE_LEFT', 'speedUp': 'SPEED_UP', 'speedDown': 'SPEED_DOWN', 'destroy_tool': 'DESTROY_TOOL', 'build': 'BUILD_TOOL', 'gameMenuButton': 'ESCAPE', 'logbook': 'LOGBOOK', } for (widgetname, action) in hotkey_replacements.iteritems(): widget = self.mainhud.findChild(name=widgetname) keys = horizons.globals.fife.get_keys_for_action(action) # No `.upper()` here: "Pause" looks better than "PAUSE". keyname = HOTKEYS.DISPLAY_KEY.get(keys[0], keys[0].capitalize()) widget.helptext = widget.helptext.format(key=keyname) self.resource_overview = ResourceOverviewBar(self.session) # Register for messages SpeedChanged.subscribe(self._on_speed_changed) NewDisaster.subscribe(self._on_new_disaster) NewSettlement.subscribe(self._on_new_settlement) PlayerLevelUpgrade.subscribe(self._on_player_level_upgrade) MineEmpty.subscribe(self._on_mine_empty) ZoomChanged.subscribe(self._update_zoom) self._display_speed(self.session.timer.ticks_per_second)
def __init__(self, session, gui): super(IngameGui, self).__init__() self.session = session assert isinstance(self.session, horizons.session.Session) self.main_gui = gui self.settlement = None self._old_menu = None self.cursor = None self.coordinates_tooltip = None self.keylistener = IngameKeyListener(self.session) self.cityinfo = CityInfo(self) LastActivePlayerSettlementManager.create_instance(self.session) self.message_widget = MessageWidget(self.session) # Windows self.windows = WindowManager() self.logbook = LogBook(self.session, self.windows) self.players_overview = PlayersOverview(self.session) self.players_settlements = PlayersSettlements(self.session) self.players_ships = PlayersShips(self.session) self.chat_dialog = ChatDialog(self.windows, self.session) self.change_name_dialog = ChangeNameDialog(self.windows, self.session) self.pausemenu = PauseMenu(self.session, self, self.windows, in_editor_mode=False) self.help_dialog = HelpDialog(self.windows, session=self.session) # Icon manager self.status_icon_manager = StatusIconManager( renderer=self.session.view.renderer['GenericRenderer'], layer=self.session.view.layers[LAYERS.OBJECTS] ) self.production_finished_icon_manager = ProductionFinishedIconManager( renderer=self.session.view.renderer['GenericRenderer'], layer=self.session.view.layers[LAYERS.OBJECTS] ) # 'minimap' is the guichan gui around the actual minimap, which is saved # in self.minimap self.mainhud = load_uh_widget('minimap.xml') self.mainhud.position_technique = "right+0:top+0" icon = self.mainhud.findChild(name="minimap") self.minimap = Minimap(icon, targetrenderer=horizons.globals.fife.targetrenderer, imagemanager=horizons.globals.fife.imagemanager, session=self.session, view=self.session.view) def speed_up(): SpeedUpCommand().execute(self.session) def speed_down(): SpeedDownCommand().execute(self.session) self.mainhud.mapEvents({ 'zoomIn' : self.session.view.zoom_in, 'zoomOut' : self.session.view.zoom_out, 'rotateRight' : Callback.ChainedCallbacks(self.session.view.rotate_right, self.minimap.rotate_right), 'rotateLeft' : Callback.ChainedCallbacks(self.session.view.rotate_left, self.minimap.rotate_left), 'speedUp' : speed_up, 'speedDown' : speed_down, 'destroy_tool' : self.toggle_destroy_tool, 'build' : self.show_build_menu, 'diplomacyButton' : self.show_diplomacy_menu, 'gameMenuButton' : self.toggle_pause, 'logbook' : lambda: self.windows.toggle(self.logbook) }) self.mainhud.show() self.resource_overview = ResourceOverviewBar(self.session) # Register for messages SpeedChanged.subscribe(self._on_speed_changed) NewDisaster.subscribe(self._on_new_disaster) NewSettlement.subscribe(self._on_new_settlement) PlayerLevelUpgrade.subscribe(self._on_player_level_upgrade) MineEmpty.subscribe(self._on_mine_empty) self.session.view.add_change_listener(self._update_zoom) self._display_speed(self.session.timer.ticks_per_second)
def set_construction_mode(self, resource_source_instance, build_costs): """Show resources relevant to construction and build costs @param resource_source_instance: object with StorageComponent @param build_costs: dict, { res : amount } """ if resource_source_instance is None: # Build moved out of settlement. This is usually not sane and an interaction error. # Use this heuristically computed settlement to fix preconditions. resource_source_instance = LastActivePlayerSettlementManager().get( ) if self.construction_mode and \ resource_source_instance == self.current_instance() and \ build_costs == self._last_build_costs: return # now that's not an update self._last_build_costs = build_costs self.construction_mode = True self.set_inventory_instance(resource_source_instance, keep_construction_mode=True) # label background icons cost_icon_gold = "content/gui/images/background/widgets/resbar_stats_bottom.png" cost_icon_res = "content/gui/images/background/widgets/res_extra_bg.png" res_list = self._get_current_resources() # remove old one before, avoids duplicates self._drop_cost_labels() for res, amount in build_costs.items(): assert res in res_list or res == RES.GOLD cost_label = Label(text="-" + str(amount)) cost_label.stylize(self.__class__.STYLE) # add icon below end of background icon if res in res_list: entry = res_list.index(res) cur_gui = self.gui[entry] reference_icon = cur_gui.findChild(name="background_icon") below = reference_icon.size[1] cost_icon = Icon(image=cost_icon_res, position=(0, below)) cost_label.position = (15, below) # TODO: centering cur_gui.addChild(cost_icon) cur_gui.addChild(cost_label) cur_gui.cost_gui = [cost_label, cost_icon] cur_gui.resizeToContent() # container needs to be bigger now else: # must be gold # there is an icon with scales there, use its positioning reference_icon = self.gold_gui.child_finder( "balance_background") cost_icon = Icon(image=cost_icon_gold, position=(reference_icon.x, reference_icon.y)) cost_label.position = (23, 74) # TODO: centering self.gold_gui.addChild(cost_icon) self.gold_gui.addChild(cost_label) self.gold_gui.cost_gui = [cost_label, cost_icon] self.gold_gui.resizeToContent()
def set_content(self): """Parses self.row_definitions and sets the content accordingly""" settlement = LastActivePlayerSettlementManager().get() def _set_entry(button, icon, building_id): """Configure a single build menu button""" if self.unlocking_strategy == self.__class__.unlocking_strategies.single_per_increment and \ self.get_building_increments()[building_id] > self.session.world.player.settler_level: return building = Entities.buildings[building_id] button.helptext = self.session.db.get_building_tooltip(building_id) enough_res = False # don't show building by default if settlement is not None: # settlement is None when the mouse has left the settlement res_overview = self.session.ingame_gui.resource_overview button.mapEvents({ button.name+"/mouseEntered/buildtab" : Callback(res_overview.set_construction_mode, settlement, building.costs), button.name+"/mouseExited/buildtab" : res_overview.close_construction_mode }) (enough_res, missing_res) = Build.check_resources({}, building.costs, settlement.owner, [settlement]) #check whether to disable build menu icon (not enough res available) if enough_res: icon.image = "content/gui/images/buttons/buildmenu_button_bg.png" path = "content/gui/icons/buildmenu/{id:03d}{{mode}}.png".format(id=building_id) button.down_image = path.format(mode='_h') button.hover_image = path.format(mode='_h') else: icon.image = "content/gui/images/buttons/buildmenu_button_bg_bw.png" path = "content/gui/icons/buildmenu/greyscale/{id:03d}{{mode}}.png".format(id=building_id) button.down_image = path.format(mode='') button.hover_image = path.format(mode='') button.up_image = path.format(mode='') button.capture(Callback(self.build_callback, building_id)) MAX_ROWS = 4 MAX_COLS = 4 for row_num, row in enumerate(self.row_definitions): # we have integers for building types, strings for headlines above slots and None as empty slots column = -1 # can't use enumerate, not always incremented for entry in row: column += 1 position = (10*column) + (row_num+1) # legacy code, first row is 1, 11, 21 if entry is None: continue elif (column + 1) > MAX_COLS: # out of 4x4 bounds err = "Invalid entry '%s': column %s does not exist." % (entry, column + 1) err += " Max. column amount in current layout is %s." % MAX_COLS raise InvalidBuildMenuFileFormat(err) elif row_num > MAX_ROWS: # out of 4x4 bounds err = "Invalid entry '%s': row %s does not exist." % (entry, row_num) err += " Max. row amount in current layout is %s." % MAX_ROWS raise InvalidBuildMenuFileFormat(err) elif isinstance(entry, basestring): column -= 1 # a headline does not take away a slot lbl = self.widget.child_finder('label_{position:02d}'.format(position=position)) lbl.text = _(entry[2:]) if entry.startswith('_ ') else entry elif isinstance(entry, int): button = self.widget.child_finder('button_{position:02d}'.format(position=position)) icon = self.widget.child_finder('icon_{position:02d}'.format(position=position)) _set_entry(button, icon, entry) else: raise InvalidBuildMenuFileFormat("Invalid entry: %s" % entry)
def _do_save(self, savegame): """Actual save code. @param savegame: absolute path""" assert os.path.isabs(savegame) self.log.debug("Session: Saving to %s", savegame) try: if os.path.exists(savegame): os.unlink(savegame) self.savecounter += 1 db = DbReader(savegame) except IOError as e: # usually invalid filename headline = _("Failed to create savegame file") descr = _( "There has been an error while creating your savegame file.") advice = _( "This usually means that the savegame name contains unsupported special characters." ) self.gui.show_error_popup(headline, descr, advice, unicode(e)) return self.save( ) # retry with new savegamename entered by the user # this must not happen with quicksave/autosave except OSError as e: if e.errno == errno.EACCES: self.gui.show_error_popup( _("Access is denied"), _("The savegame file could be read-only or locked by another process." )) return self.save() raise try: read_savegame_template(db) db("BEGIN") self.world.save(db) #self.manager.save(db) self.view.save(db) self.ingame_gui.save(db) self.scenario_eventhandler.save(db) LastActivePlayerSettlementManager().save(db) for instance in self.selected_instances: db("INSERT INTO selected(`group`, id) VALUES(NULL, ?)", instance.worldid) for group in xrange(len(self.selection_groups)): for instance in self.selection_groups[group]: db("INSERT INTO selected(`group`, id) VALUES(?, ?)", group, instance.worldid) rng_state = json.dumps(self.random.getstate()) SavegameManager.write_metadata(db, self.savecounter, rng_state) # make sure everything gets written now db("COMMIT") db.close() return True except: print "Save Exception" traceback.print_exc() db.close() # close db before delete os.unlink(savegame) # remove invalid savegamefile return False
def save(self, db): self.message_widget.save(db) self.logbook.save(db) self.resource_overview.save(db) LastActivePlayerSettlementManager().save(db)
def set_content(self): """Parses self.row_definitions and sets the content accordingly""" settlement = LastActivePlayerSettlementManager().get() def _set_entry(button, icon, building_id): """Configure a single build menu button""" if self.unlocking_strategy == self.__class__.unlocking_strategies.single_per_tier and \ self.get_building_tiers()[building_id] > self.session.world.player.settler_level: return building = Entities.buildings[building_id] button.helptext = building.get_tooltip() # Add necessary resources to tooltip text. # tooltip.py will then place icons from this information. required_resources = '' for resource_id, amount_needed in sorted(building.costs.items()): required_resources += ' {}:{}'.format(resource_id, amount_needed) required_text = '[[Buildmenu{}]]'.format(required_resources) button.helptext = required_text + button.helptext enough_res = False # don't show building by default if settlement is not None: # settlement is None when the mouse has left the settlement res_overview = self.session.ingame_gui.resource_overview show_costs = Callback(res_overview.set_construction_mode, settlement, building.costs) button.mapEvents({ button.name + "/mouseEntered/buildtab": show_costs, button.name + "/mouseExited/buildtab": res_overview.close_construction_mode }) (enough_res, missing_res) = Build.check_resources({}, building.costs, settlement.owner, [settlement]) # Check whether to disable build menu icon (not enough res available). if enough_res: icon.image = "content/gui/images/buttons/buildmenu_button_bg.png" button.path = "icons/buildmenu/{id:03d}".format(id=building_id) else: icon.image = "content/gui/images/buttons/buildmenu_button_bg_bw.png" button.path = "icons/buildmenu/greyscale/{id:03d}".format( id=building_id) button.capture(Callback(self.build_callback, building_id)) for row_num, row in enumerate(self.row_definitions): # we have integers for building types, strings for headlines above slots and None as empty slots column = -1 # can't use enumerate, not always incremented for entry in row: column += 1 position = (10 * column) + ( row_num + 1) # legacy code, first row is 1, 11, 21 if entry is None: continue elif (column + 1) > self.MAX_COLS: # out of 4x4 bounds err = "Invalid entry '{}': column {} does not exist.".format( entry, column + 1) err += " Max. column amount in current layout is {}.".format( self.MAX_COLS) raise InvalidBuildMenuFileFormat(err) elif row_num > self.MAX_ROWS: # out of 4x4 bounds err = "Invalid entry '{}': row {} does not exist.".format( entry, row_num) err += " Max. row amount in current layout is {}.".format( self.MAX_ROWS) raise InvalidBuildMenuFileFormat(err) elif isinstance(entry, str): column -= 1 # a headline does not take away a slot lbl = self.widget.child_finder( 'label_{position:02d}'.format(position=position)) lbl.text = T( entry[2:]) if entry.startswith('_ ') else entry elif isinstance(entry, int): button = self.widget.child_finder( 'button_{position:02d}'.format(position=position)) icon = self.widget.child_finder( 'icon_{position:02d}'.format(position=position)) _set_entry(button, icon, entry) else: raise InvalidBuildMenuFileFormat( "Invalid entry: {}".format(entry))
def __init__(self, session): super(IngameGui, self).__init__() self.session = session assert isinstance(self.session, horizons.session.Session) self.settlement = None self._old_menu = None self.cursor = None self.coordinates_tooltip = None self.keylistener = IngameKeyListener(self.session) self.cityinfo = CityInfo(self) LastActivePlayerSettlementManager.create_instance(self.session) self.message_widget = MessageWidget(self.session) # Windows self.windows = WindowManager() self.show_popup = self.windows.show_popup self.show_error_popup = self.windows.show_error_popup self.logbook = LogBook(self.session, self.windows) self.players_overview = PlayersOverview(self.session) self.players_settlements = PlayersSettlements(self.session) self.players_ships = PlayersShips(self.session) self.chat_dialog = ChatDialog(self.windows, self.session) self.change_name_dialog = ChangeNameDialog(self.windows, self.session) self.pausemenu = PauseMenu(self.session, self, self.windows, in_editor_mode=False) self.help_dialog = HelpDialog(self.windows, session=self.session) # Icon manager self.status_icon_manager = StatusIconManager( renderer=self.session.view.renderer['GenericRenderer'], layer=self.session.view.layers[LAYERS.OBJECTS]) self.production_finished_icon_manager = ProductionFinishedIconManager( renderer=self.session.view.renderer['GenericRenderer'], layer=self.session.view.layers[LAYERS.OBJECTS]) # 'minimap' is the guichan gui around the actual minimap, which is saved # in self.minimap self.mainhud = load_uh_widget('minimap.xml') self.mainhud.position_technique = "right:top" icon = self.mainhud.findChild(name="minimap") self.minimap = Minimap( icon, targetrenderer=horizons.globals.fife.targetrenderer, imagemanager=horizons.globals.fife.imagemanager, session=self.session, view=self.session.view) def speed_up(): SpeedUpCommand().execute(self.session) def speed_down(): SpeedDownCommand().execute(self.session) self.mainhud.mapEvents({ 'zoomIn': self.session.view.zoom_in, 'zoomOut': self.session.view.zoom_out, 'rotateRight': Callback.ChainedCallbacks(self.session.view.rotate_right, self.minimap.rotate_right), 'rotateLeft': Callback.ChainedCallbacks(self.session.view.rotate_left, self.minimap.rotate_left), 'speedUp': speed_up, 'speedDown': speed_down, 'destroy_tool': self.toggle_destroy_tool, 'build': self.show_build_menu, 'diplomacyButton': self.show_diplomacy_menu, 'gameMenuButton': self.toggle_pause, 'logbook': lambda: self.windows.toggle(self.logbook) }) self.mainhud.show() self.resource_overview = ResourceOverviewBar(self.session) # Register for messages SpeedChanged.subscribe(self._on_speed_changed) NewDisaster.subscribe(self._on_new_disaster) NewSettlement.subscribe(self._on_new_settlement) PlayerLevelUpgrade.subscribe(self._on_player_level_upgrade) MineEmpty.subscribe(self._on_mine_empty) self.session.view.add_change_listener(self._update_zoom) self._display_speed(self.session.timer.ticks_per_second)
def __init__(self, session): super(IngameGui, self).__init__() self.session = session assert isinstance(self.session, horizons.session.Session) self.settlement = None self._old_menu = None self.cursor = None self.coordinates_tooltip = None self.keylistener = IngameKeyListener(self.session) self.cityinfo = CityInfo(self) LastActivePlayerSettlementManager.create_instance(self.session) self.message_widget = MessageWidget(self.session) # Windows self.windows = WindowManager() self.open_popup = self.windows.open_popup self.open_error_popup = self.windows.open_error_popup self.logbook = LogBook(self.session, self.windows) self.players_overview = PlayersOverview(self.session) self.players_settlements = PlayersSettlements(self.session) self.players_ships = PlayersShips(self.session) self.chat_dialog = ChatDialog(self.windows, self.session) self.change_name_dialog = ChangeNameDialog(self.windows, self.session) self.pausemenu = PauseMenu(self.session, self, self.windows, in_editor_mode=False) self.help_dialog = HelpDialog(self.windows) # Icon manager self.status_icon_manager = StatusIconManager( renderer=self.session.view.renderer['GenericRenderer'], layer=self.session.view.layers[LAYERS.OBJECTS]) self.production_finished_icon_manager = ProductionFinishedIconManager( renderer=self.session.view.renderer['GenericRenderer'], layer=self.session.view.layers[LAYERS.OBJECTS]) # 'minimap' is the guichan gui around the actual minimap, which is saved # in self.minimap self.mainhud = load_uh_widget('minimap.xml') self.mainhud.position_technique = "right:top" icon = self.mainhud.findChild(name="minimap") self.minimap = Minimap( icon, targetrenderer=horizons.globals.fife.targetrenderer, imagemanager=horizons.globals.fife.imagemanager, session=self.session, view=self.session.view) def speed_up(): SpeedUpCommand().execute(self.session) def speed_down(): SpeedDownCommand().execute(self.session) self.mainhud.mapEvents({ 'zoomIn': self.session.view.zoom_in, 'zoomOut': self.session.view.zoom_out, 'rotateRight': Callback.ChainedCallbacks(self.session.view.rotate_right, self.minimap.rotate_right), 'rotateLeft': Callback.ChainedCallbacks(self.session.view.rotate_left, self.minimap.rotate_left), 'speedUp': speed_up, 'speedDown': speed_down, 'destroy_tool': self.toggle_destroy_tool, 'build': self.show_build_menu, 'diplomacyButton': self.show_diplomacy_menu, 'gameMenuButton': self.toggle_pause, 'logbook': lambda: self.windows.toggle(self.logbook) }) self.mainhud.show() hotkey_replacements = { 'rotateRight': 'ROTATE_RIGHT', 'rotateLeft': 'ROTATE_LEFT', 'speedUp': 'SPEED_UP', 'speedDown': 'SPEED_DOWN', 'destroy_tool': 'DESTROY_TOOL', 'build': 'BUILD_TOOL', 'gameMenuButton': 'ESCAPE', 'logbook': 'LOGBOOK', } for (widgetname, action) in hotkey_replacements.iteritems(): widget = self.mainhud.findChild(name=widgetname) keys = horizons.globals.fife.get_keys_for_action(action) # No `.upper()` here: "Pause" looks better than "PAUSE". keyname = HOTKEYS.DISPLAY_KEY.get(keys[0], keys[0].capitalize()) widget.helptext = widget.helptext.format(key=keyname) self.resource_overview = ResourceOverviewBar(self.session) # Register for messages SpeedChanged.subscribe(self._on_speed_changed) NewDisaster.subscribe(self._on_new_disaster) NewSettlement.subscribe(self._on_new_settlement) PlayerLevelUpgrade.subscribe(self._on_player_level_upgrade) MineEmpty.subscribe(self._on_mine_empty) ZoomChanged.subscribe(self._update_zoom) self._display_speed(self.session.timer.ticks_per_second)