def _update_infos(): """Fill in infos of selected scenario to label""" try: difficulty = CampaignEventHandler.get_difficulty_from_file( self.__get_selected_map() ) desc = CampaignEventHandler.get_description_from_file( self.__get_selected_map() ) author = CampaignEventHandler.get_author_from_file( self.__get_selected_map() ) except InvalidScenarioFileFormat, e: self.__show_invalid_scenario_file_popup(e) return
def __init__(self, gui, db): super(Session, self).__init__() self.log.debug("Initing session") self.gui = gui # main gui, not ingame gui self.db = db # main db for game data (game.sqlite) # this saves how often the current game has been saved self.savecounter = 0 self.is_alive = True WorldObject.reset() #game self.random = self.create_rng() self.timer = Timer() Scheduler.create_instance(self.timer) self.manager = self.create_manager() self.view = View(self, (15, 15)) Entities.load(self.db) self.campaign_eventhandler = CampaignEventHandler(self) # dummy handler with no events #GUI self.gui.session = self self.ingame_gui = IngameGui(self, self.gui) self.keylistener = IngameKeyListener(self) self.display_speed() self.selected_instances = set() self.selection_groups = [set()] * 10 # List of sets that holds the player assigned unit groups.
def load(self, savegame, players, is_scenario=False): """Loads a map. @param savegame: path to the savegame database. @param players: iterable of dictionaries containing id, name, color and local @param is_scenario: Bool whether the loaded map is a scenario or not """ if is_scenario: # savegame is a yaml file, that contains reference to actual map file self.campaign_eventhandler = CampaignEventHandler(self, savegame) savegame = os.path.join(SavegameManager.maps_dir, \ self.campaign_eventhandler.get_map_file()) self.log.debug("Session: Loading from %s", savegame) savegame_db = DbReader(savegame) # Initialize new dbreader try: # load how often the game has been saved (used to know the difference between # a loaded and a new game) self.savecounter = SavegameManager.get_metadata(savegame)['savecounter'] except KeyError: self.savecounter = 0 self.world = World(self) # Load horizons.world module (check horizons/world/__init__.py) self.world._init(savegame_db) self.view.load(savegame_db) # load view if not self.is_game_loaded(): # NOTE: this must be sorted before iteration, cause there is no defined order for # iterating a dict, and it must happen in the same order for mp games. for i in sorted(players): self.world.setup_player(i['id'], i['name'], i['color'], i['local']) center = self.world.init_new_world() self.view.center(center[0], center[1]) else: # try to load campaign data self.campaign_eventhandler.load(savegame_db) self.manager.load(savegame_db) # load the manager (there might me old scheduled ticks). 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.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.cursor = SelectionTool(self) self.cursor.apply_select() # Set cursor correctly, menus might need to be opened. assert hasattr(self.world, "player"), 'Error: there is no human player' """
class Session(LivingObject): """Session class represents the games main ingame view and controls cameras and map loading. This is the most important class if you are going to hack on Unknown Horizons, it provides most of the important ingame variables. Here's a small list of commonly used attributes: * manager - horizons.manager instance. Used to execute commands that need to be tick, synchronized check the class for more information. * scheduler - horizons.scheduler instance. Used to execute timed events that do not effect network games but rather control the local simulation. * view - horizons.view instance. Used to control the ingame camera. * ingame_gui - horizons.gui.ingame_gui instance. Used to controll the ingame gui. * cursor - horizons.gui.{navigation/cursor/selection/building}tool instance. Used to controll mouse events, check the classes for more info. * selected_instances - Set that holds the currently selected instances (building, units). * world - horizons.world instance of the currently running horizons. Stores islands, players, for later access. TUTORIAL: For further digging you should now be checking out the load() function. """ timer = livingProperty() manager = livingProperty() view = livingProperty() ingame_gui = livingProperty() keylistener = livingProperty() cursor = livingProperty() world = livingProperty() campaign_eventhandler = livingProperty() log = logging.getLogger('session') def __init__(self, gui, db): super(Session, self).__init__() self.log.debug("Initing session") self.gui = gui # main gui, not ingame gui self.db = db # main db for game data (game.sqlite) # this saves how often the current game has been saved self.savecounter = 0 self.is_alive = True WorldObject.reset() #game self.random = self.create_rng() self.timer = Timer() Scheduler.create_instance(self.timer) self.manager = self.create_manager() self.view = View(self, (15, 15)) Entities.load(self.db) self.campaign_eventhandler = CampaignEventHandler(self) # dummy handler with no events #GUI self.gui.session = self self.ingame_gui = IngameGui(self, self.gui) self.keylistener = IngameKeyListener(self) self.display_speed() self.selected_instances = set() self.selection_groups = [set()] * 10 # List of sets that holds the player assigned unit groups. def start(self): """Acctually starts the game.""" self.timer.activate() def create_manager(self): """Returns instance of command manager (currently MPManager or SPManager)""" raise NotImplementedError def create_rng(self): """Returns a RNG (random number generator). Must support the python random.Random interface""" raise NotImplementedError 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.emitter['ambient'][:]: emitter.stop() horizons.main.fife.emitter['ambient'].remove(emitter) horizons.main.fife.emitter['effects'].stop() horizons.main.fife.emitter['speech'].stop() self.cursor = None self.world = None self.keylistener = None self.ingame_gui = None self.view = None self.manager = None self.timer = None self.campaign_eventhandler = None Scheduler.destroy_instance() self.selected_instances = None self.selection_groups = None def destroy_tool(self): """Initiate the destroy tool""" if not hasattr(self.cursor, 'tear_tool_active') or \ not self.cursor.tear_tool_active: self.cursor = TearingTool(self) self.ingame_gui.hide_menu() def autosave(self): raise NotImplementedError def quicksave(self): raise NotImplementedError def quickload(self): raise NotImplementedError def save(self, savegame): raise NotImplementedError def load(self, savegame, players, is_scenario=False): """Loads a map. @param savegame: path to the savegame database. @param players: iterable of dictionaries containing id, name, color and local @param is_scenario: Bool whether the loaded map is a scenario or not """ if is_scenario: # savegame is a yaml file, that contains reference to actual map file self.campaign_eventhandler = CampaignEventHandler(self, savegame) savegame = os.path.join(SavegameManager.maps_dir, \ self.campaign_eventhandler.get_map_file()) self.log.debug("Session: Loading from %s", savegame) savegame_db = DbReader(savegame) # Initialize new dbreader try: # load how often the game has been saved (used to know the difference between # a loaded and a new game) self.savecounter = SavegameManager.get_metadata(savegame)['savecounter'] except KeyError: self.savecounter = 0 self.world = World(self) # Load horizons.world module (check horizons/world/__init__.py) self.world._init(savegame_db) self.view.load(savegame_db) # load view if not self.is_game_loaded(): # NOTE: this must be sorted before iteration, cause there is no defined order for # iterating a dict, and it must happen in the same order for mp games. for i in sorted(players): self.world.setup_player(i['id'], i['name'], i['color'], i['local']) center = self.world.init_new_world() self.view.center(center[0], center[1]) else: # try to load campaign data self.campaign_eventhandler.load(savegame_db) self.manager.load(savegame_db) # load the manager (there might me old scheduled ticks). 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.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.cursor = SelectionTool(self) self.cursor.apply_select() # Set cursor correctly, menus might need to be opened. assert hasattr(self.world, "player"), 'Error: there is no human player' """ TUTORIAL: From here on you should digg into the classes that are loaded above, especially the world class. (horizons/world/__init__.py). It's where the magic happens and all buildings and units are loaded. """ def generate_map(self): """Generates a map.""" #load map self.db("ATTACH ':memory:' AS map") #... self.world = World(self) self.world._init(self.db) #setup view self.view.center(((self.world.max_x - self.world.min_x) / 2.0), ((self.world.max_y - self.world.min_y) / 2.0)) def speed_set(self, ticks): """Set game speed to ticks ticks per second""" raise NotImplementedError def display_speed(self): text = u'' tps = self.timer.ticks_per_second if tps == 0: # pause text = u'0x' elif tps == GAME_SPEED.TICKS_PER_SECOND: # normal speed, 1x pass # display nothing else: text = unicode(tps/GAME_SPEED.TICKS_PER_SECOND) + u'x' # 2x, 4x, ... self.ingame_gui.display_game_speed(text) def speed_up(self): if self.timer.ticks_per_second in GAME_SPEED.TICK_RATES: i = GAME_SPEED.TICK_RATES.index(self.timer.ticks_per_second) if i + 1 < len(GAME_SPEED.TICK_RATES): self.speed_set(GAME_SPEED.TICK_RATES[i + 1]) else: self.speed_set(GAME_SPEED.TICK_RATES[0]) def speed_down(self): if self.timer.ticks_per_second in GAME_SPEED.TICK_RATES: i = GAME_SPEED.TICK_RATES.index(self.timer.ticks_per_second) if i > 0: self.speed_set(GAME_SPEED.TICK_RATES[i - 1]) else: self.speed_set(GAME_SPEED.TICK_RATES[0]) def speed_pause(self): self.log.debug("Session: Pausing") if not self.speed_is_paused(): self.paused_ticks_per_second = self.timer.ticks_per_second self.speed_set(0) def speed_unpause(self): self.log.debug("Session: Unpausing") if self.speed_is_paused(): self.speed_set(self.paused_ticks_per_second) def speed_toggle_pause(self): if self.speed_is_paused(): self.speed_unpause() else: self.speed_pause() def speed_is_paused(self): return (self.timer.ticks_per_second == 0) def is_game_loaded(self): """Checks if the current game is a new one, or a loaded one. @return: True if game is loaded, else False """ return (self.savecounter > 0)