Example #1
0
	def autosave(self):
		"""Called automatically in an interval"""
		self.log.debug("Session: autosaving")
		success = self._do_save(SavegameManager.create_autosave_filename())
		if success:
			SavegameManager.delete_dispensable_savegames(autosaves=True)
			self.ingame_gui.message_widget.add('AUTOSAVE')
Example #2
0
 def autosave(self):
     """Called automatically in an interval"""
     self.log.debug("Session: autosaving")
     success = self._do_save(SavegameManager.create_autosave_filename())
     if success:
         SavegameManager.delete_dispensable_savegames(autosaves=True)
         self.ingame_gui.message_widget.add('AUTOSAVE')
Example #3
0
def prepare_multiplayer(game, trader_enabled=True, pirate_enabled=True, natural_resource_multiplier=1):
	"""Starts a multiplayer game server
	TODO: actual game data parameter passing
	"""
	_modules.gui.show_loading_screen()

	global preloading
	preload_game_join(preloading)

	# remove cursor while loading
	horizons.globals.fife.cursor.set(fife_module.CURSOR_NONE)
	horizons.globals.fife.engine.pump()
	horizons.globals.fife.set_cursor_image('default')

	# destruct old session (right now, without waiting for gc)
	if _modules.session is not None and _modules.session.is_alive:
		_modules.session.end()
	# start new session
	from horizons.mpsession import MPSession
	# get random seed for game
	uuid = game.uuid
	random = sum([ int(uuid[i : i + 2], 16) for i in range(0, len(uuid), 2) ])
	_modules.session = MPSession(horizons.globals.db, NetworkInterface(), rng_seed=random)

	# NOTE: this data passing is only temporary, maybe use a player class/struct
	if game.is_savegame:
		map_file = SavegameManager.get_multiplayersave_map(game.map_name)
	else:
		map_file = SavegameManager.get_map(game.map_name)

	options = StartGameOptions.create_start_multiplayer(map_file, game.get_player_list(), not game.is_savegame)
	_modules.session.load(options)
Example #4
0
def _start_map(
    map_name,
    ai_players=0,
    is_scenario=False,
    pirate_enabled=True,
    trader_enabled=True,
    force_player_id=None,
    is_map=False,
):
    """Start a map specified by user
	@param map_name: name of map or path to map
	@return: bool, whether loading succeeded"""
    if is_scenario:
        savegames = SavegameManager.get_available_scenarios(locales=True)
    else:
        savegames = SavegameManager.get_maps()
    map_file = _find_matching_map(map_name, savegames)
    if not map_file:
        return False

    options = StartGameOptions.create_start_singleplayer(
        map_file, is_scenario, ai_players, trader_enabled, pirate_enabled, force_player_id, is_map
    )
    start_singleplayer(options)
    return True
Example #5
0
def _start_map(map_name, ai_players=0, human_ai=False, is_scenario=False, campaign=None, pirate_enabled=True, trader_enabled=True, force_player_id=None):
	"""Start a map specified by user
	@param map_name: name of map or path to map
	@return: bool, whether loading succeded"""
	# check for exact/partial matches in map list first
	maps = SavegameManager.get_available_scenarios() if is_scenario else SavegameManager.get_maps()
	map_file = None
	for i in xrange(0, len(maps[1])):
		# exact match
		if maps[1][i] == map_name:
			map_file = maps[0][i]
			break
		# check for partial match
		if maps[1][i].startswith(map_name):
			if map_file is not None:
				# multiple matches, collect all for output
				map_file += u'\n' + maps[0][i]
			else:
				map_file = maps[0][i]
	if map_file is None:
		# not a map name, check for path to file or fail
		if os.path.exists(map_name):
			map_file = map_name
		else:
			#xgettext:python-format
			print u"Error: Cannot find map '{name}'.".format(name=map_name)
			return False
	if len(map_file.splitlines()) > 1:
		print "Error: Found multiple matches:"
		for match in map_file.splitlines():
			print os.path.basename(match)
		return False
	load_game(ai_players, human_ai, map_file, is_scenario, campaign=campaign,
	          trader_enabled=trader_enabled, pirate_enabled=pirate_enabled, force_player_id=force_player_id)
	return True
Example #6
0
 def autosave(self):
     """Called automatically in an interval"""
     self.log.debug("Session: autosaving")
     # call saving through horizons.main and not directly through session, so that save errors are handled
     success = self.save(SavegameManager.create_autosave_filename())
     if success:
         SavegameManager.delete_dispensable_savegames(autosaves=True)
def test_delete_game(gui):
    """Test deleting a savegame."""

    _copy_savegame('boatbuilder')
    _copy_savegame('ai_settlement')
    assert os.path.exists(SavegameManager.create_filename('boatbuilder'))
    assert os.path.exists(SavegameManager.create_filename('ai_settlement'))

    def confirm_deletion():
        def close_dialog():
            gui.trigger('load_game_window', 'cancelButton')

        with gui.handler(close_dialog):
            gui.trigger('popup_window', 'okButton')

    def func1():
        gui.find('savegamelist').select(u'boatbuilder')

        with gui.handler(confirm_deletion):
            gui.trigger('load_game_window', 'deleteButton')

    with gui.handler(func1):
        gui.trigger('menu', 'load_button')

    assert not os.path.exists(SavegameManager.create_filename('boatbuilder'))
    assert os.path.exists(SavegameManager.create_filename('ai_settlement'))
def goal_reached(session, goal_number):
	"""The player reaches a certain goal in the current scenario."""
	# TODO : if we want, we could make this work in "scenario" mode
	#        to allow the player to reach goals in scenarios even if
	#        no campaign was has been loaded.
	if session.campaign:
		SavegameManager.mark_goal_reached(session.campaign, goal_number)
Example #9
0
def _start_map(map_name, is_scenario = False):
	"""Start a map specified by user
	@return: bool, whether loading succeded"""
	maps = SavegameManager.get_scenarios() if is_scenario else SavegameManager.get_maps()
	map_file = None
	for i in xrange(0, len(maps[1])):
		# exact match
		if maps[1][i] == map_name:
			map_file = maps[0][i]
			break
		# check for partial match
		if maps[1][i].startswith(map_name):
			if map_file is not None:
				# multiple matches, collect all for output
				map_file += u'\n' + maps[0][i]
			else:
				map_file = maps[0][i]
	if map_file is None:
		print _("Error: Cannot find map \"%s\".") % map_name
		return False
	if len(map_file.splitlines()) > 1:
		print _("Error: Found multiple matches: ")
		for match in map_file.splitlines():
			print os.path.basename(match)
		return False
	load_game(map_file, is_scenario)
	return True
Example #10
0
def goal_reached(session, goal_number):
    """Called when player reached a goal in a scenario"""
    # TODO : if we want, we could make this work in "scenario" mode
    #        to allow the player to reach goals in scenarios even if
    #        he didn't load the campaign.
    if session.campaign:
        SavegameManager.mark_goal_reached(session.campaign, goal_number)
Example #11
0
    def show(self):
        # Campaign and scenarios data
        scenario_list = self._gui.findChild(name="scenario_list")
        campaign_info = SavegameManager.get_campaign_info(
            name=self.session.campaign['campaign_name'])
        available_scenarios = SavegameManager.get_available_scenarios()[
            1]  # [0] is the list of xml files, we don't need it
        scenarios = [
            s for s in campaign_info.get('scenario_names', [])
            if s in available_scenarios
        ]
        self._gui.distributeInitialData({'scenario_list': scenarios})
        # select the first one
        self._gui.distributeData({
            'scenario_list': 0,
        })

        def _update_infos():
            self.selected_scenario = scenarios[self._gui.collectData(
                "scenario_list")]
            data = SavegameManager.get_scenario_info(
                name=self.selected_scenario)
            text = [
                _("Difficulty: ") + unicode(data.get('difficulty', '')),
                _("Author: ") + unicode(data.get('author', '')),
                _("Description: ") + unicode(data.get('description', '')),
            ]
            self._gui.findChild(
                name="scenario_details").text = u"\n".join(text)

        self._gui.findChild(name="scenario_list").capture(_update_infos)
        _update_infos()
        self._gui.show()
Example #12
0
def prepare_multiplayer(game, trader_enabled = True, pirate_enabled = True, natural_resource_multiplier = 1):
	"""Starts a multiplayer game server
	TODO: acctual game data parameter passing
	"""
	global fife, preloading, db

	preload_game_join(preloading)

	# remove cursor while loading
	fife.cursor.set(fife_module.CURSOR_NONE)
	fife.engine.pump()
	fife.set_cursor_image('default')

	# hide whatever is displayed before the game starts
	_modules.gui.hide()

	# destruct old session (right now, without waiting for gc)
	if _modules.session is not None and _modules.session.is_alive:
		_modules.session.end()
	# start new session
	from mpsession import MPSession
	# get random seed for game
	uuid = game.get_uuid()
	random = sum([ int(uuid[i : i + 2], 16) for i in range(0, len(uuid), 2) ])
	_modules.session = MPSession(_modules.gui, db, NetworkInterface(), rng_seed=random)
	# NOTE: this data passing is only temporary, maybe use a player class/struct
	if game.load:
		map_file = SavegameManager.get_multiplayersave_map( game.get_map_name() )
	else:
		map_file = SavegameManager.get_map( game.get_map_name() )

	_modules.session.load(map_file,
	                      game.get_player_list(), trader_enabled, pirate_enabled, natural_resource_multiplier)
Example #13
0
			def sanity_checker(string):
				try:
					SavegameManager.create_multiplayersave_filename(string)
				except RuntimeError:
					return False
				else:
					return True
Example #14
0
def test_save_game_override(gui):
	"""Test saving a game."""

	_copy_savegame()
	old_size = os.path.getsize(SavegameManager.create_filename('boatbuilder'))

	# FIXME escape doesn't work
	#gui.press_key(gui.Key.ESCAPE)
	gui.trigger('mainhud/gameMenuButton')

	def func1():
		gui.find('savegamelist').select(u'boatbuilder')

		# handle "do you want to override file" popup
		def func2():
			gui.trigger('popup_window/okButton')

		with gui.handler(func2):
			gui.trigger('load_game_window/okButton')

	with gui.handler(func1):
		gui.trigger('menu/button_images/savegameButton')

	assert os.path.exists(SavegameManager.create_filename('boatbuilder'))
	new_size = os.path.getsize(SavegameManager.create_filename('boatbuilder'))
	assert old_size != new_size
def test_save_game_override(gui):
    """Test saving a game."""

    _copy_savegame()
    old_size = os.path.getsize(SavegameManager.create_filename('boatbuilder'))

    # FIXME escape doesn't work
    #gui.press_key(gui.Key.ESCAPE)
    gui.trigger('mainhud', 'gameMenuButton')

    def func1():
        gui.find('savegamelist').select(u'boatbuilder')

        # handle "do you want to override file" popup
        def func2():
            gui.trigger('popup_window', 'okButton')

        with gui.handler(func2):
            gui.trigger('load_game_window', 'okButton')

    with gui.handler(func1):
        gui.trigger('menu', 'savegameButton')

    assert os.path.exists(SavegameManager.create_filename('boatbuilder'))
    new_size = os.path.getsize(SavegameManager.create_filename('boatbuilder'))
    assert old_size != new_size
Example #16
0
def test_delete_game(gui):
	"""Test deleting a savegame."""

	_copy_savegame('boatbuilder')
	_copy_savegame('ai_settlement')
	assert os.path.exists(SavegameManager.create_filename('boatbuilder'))
	assert os.path.exists(SavegameManager.create_filename('ai_settlement'))

	def confirm_deletion():
		def close_dialog():
			gui.trigger('load_game_window/cancelButton')

		with gui.handler(close_dialog):
			gui.trigger('popup_window/okButton')

	def func1():
		gui.find('savegamelist').select(u'boatbuilder')

		with gui.handler(confirm_deletion):
			gui.trigger('load_game_window/deleteButton')

	with gui.handler(func1):
		gui.trigger('menu/load_button')

	assert not os.path.exists(SavegameManager.create_filename('boatbuilder'))
	assert os.path.exists(SavegameManager.create_filename('ai_settlement'))
Example #17
0
def prepare_multiplayer(game, trader_enabled=True, pirate_enabled=True, natural_resource_multiplier=1):
	"""Starts a multiplayer game server
	TODO: actual game data parameter passing
	"""
	_modules.gui.show_loading_screen()

	preloader.wait_for_finish()

	# remove cursor while loading
	horizons.globals.fife.cursor.set(fife_module.CURSOR_NONE)
	horizons.globals.fife.engine.pump()
	horizons.globals.fife.set_cursor_image('default')

	# destruct old session (right now, without waiting for gc)
	if _modules.session is not None and _modules.session.is_alive:
		_modules.session.end()
	# start new session
	from horizons.mpsession import MPSession
	# get random seed for game
	uuid = game.uuid
	random = sum([int(uuid[i : i + 2], 16) for i in range(0, len(uuid), 2)])
	_modules.session = MPSession(horizons.globals.db, NetworkInterface(), rng_seed=random)

	# NOTE: this data passing is only temporary, maybe use a player class/struct
	if game.is_savegame:
		map_file = SavegameManager.get_multiplayersave_map(game.map_name)
	else:
		map_file = SavegameManager.get_map(game.map_name)

	options = StartGameOptions.create_start_multiplayer(map_file, game.get_player_list(), not game.is_savegame)
	_modules.session.load(options)
	def show(self):
		# Campaign and scenarios data
		campaign_info = SavegameManager.get_campaign_info(name = self.session.campaign['campaign_name'])
		available_scenarios = SavegameManager.get_available_scenarios()[1] # [0] is the list of xml files, we don't need it
		scenarios = [s for s in campaign_info.get('scenario_names', []) if s in available_scenarios]
		self._gui.distributeInitialData({'scenario_list' : scenarios})
		# select the first one
		self._gui.distributeData({ 'scenario_list' : 0, })
		def _update_infos():
			self.selected_scenario = scenarios[self._gui.collectData("scenario_list")]
			data = SavegameManager.get_scenario_info(name = self.selected_scenario)
			#xgettext:python-format
			text = [_("Difficulty: {difficulty}").format(difficulty=data.get('difficulty', '')),
			        _("Author: {author}").format(author=data.get('author', '')),
			        _("Description: {desc}").format(desc=data.get('description', '')),
			       ]
			self._gui.findChild(name="scenario_details").text = u"\n".join(text)
		self._gui.findChild(name="scenario_list").mapEvents({
		  'scenario_list/action': _update_infos,
		  'scenario_list/mouseWheelMovedUp'   : _update_infos,
		  'scenario_list/mouseWheelMovedDown' : _update_infos
		})


		_update_infos()
		self._gui.show()
Example #19
0
	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 ZeroDivisionError as err:
			# TODO:
			# this should say WindowsError, but that somehow now leads to a NameError
			if err.winerror == 5:
				self.gui.show_error_popup(_("Access is denied"), \
				                          _("The savegame file is probably read-only."))
				return self.save()
			elif err.winerror == 32:
				self.gui.show_error_popup(_("File used by another process"), \
				                          _("The savegame file is currently used by another program."))
				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 get's 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
Example #20
0
def _start_map(map_name, is_scenario=False):
    """Start a map specified by user
	@return: bool, whether loading succeded"""
    maps = SavegameManager.get_scenarios(
    ) if is_scenario else SavegameManager.get_maps()
    map_file = None
    for i in xrange(0, len(maps[1])):
        # exact match
        if maps[1][i] == map_name:
            map_file = maps[0][i]
            break
        # check for partial match
        if maps[1][i].startswith(map_name):
            if map_file is not None:
                # multiple matches, collect all for output
                map_file += u'\n' + maps[0][i]
            else:
                map_file = maps[0][i]
    if map_file is None:
        print _("Error: Cannot find map \"%s\".") % map_name
        return False
    if len(map_file.splitlines()) > 1:
        print _("Error: Found multiple matches: ")
        for match in map_file.splitlines():
            print os.path.basename(match)
        return False
    load_game(map_file, is_scenario)
    return True
Example #21
0
def goal_reached(session, goal_number):
	"""Called when player reached a goal in a scenario"""
	# TODO : if we want, we could make this work in "scenario" mode
	#        to allow the player to reach goals in scenarios even if
	#        he didn't load the campaign.
	if session.campaign:
		SavegameManager.mark_goal_reached(session.campaign, goal_number)
Example #22
0
	def autosave(self):
		"""Called automatically in an interval"""
		self.log.debug("Session: autosaving")
		# call saving through horizons.main and not directly through session, so that save errors are handled
		success = self.save(SavegameManager.create_autosave_filename())
		if success:
			SavegameManager.delete_dispensable_savegames(autosaves = True)
    def show(self):
        # Campaign and scenarios data
        scenario_list = self._gui.findChild(name="scenario_list")
        campaign_info = SavegameManager.get_campaign_info(name=self.session.campaign["campaign_name"])
        available_scenarios = SavegameManager.get_available_scenarios()[
            1
        ]  # [0] is the list of xml files, we don't need it
        scenarios = [s for s in campaign_info.get("scenario_names", []) if s in available_scenarios]
        self._gui.distributeInitialData({"scenario_list": scenarios})
        # select the first one
        self._gui.distributeData({"scenario_list": 0})

        def _update_infos():
            self.selected_scenario = scenarios[self._gui.collectData("scenario_list")]
            data = SavegameManager.get_scenario_info(name=self.selected_scenario)
            text = [
                _("Difficulty: ") + unicode(data.get("difficulty", "")),
                _("Author: ") + unicode(data.get("author", "")),
                _("Description: ") + unicode(data.get("description", "")),
            ]
            self._gui.findChild(name="scenario_details").text = u"\n".join(text)

        self._gui.findChild(name="scenario_list").capture(_update_infos)
        _update_infos()
        self._gui.show()
Example #24
0
    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 = T("Failed to create savegame file")
            descr = T(
                "There has been an error while creating your savegame file.")
            advice = T(
                "This usually means that the savegame name contains unsupported special characters."
            )
            self.ingame_gui.open_error_popup(headline, descr, advice,
                                             unicode(e))
            # retry with new savegamename entered by the user
            # (this must not happen with quicksave/autosave)
            return self.save()
        except OSError as e:
            if e.errno != errno.EACCES:
                raise
            self.ingame_gui.open_error_popup(
                T("Access is denied"),
                T("The savegame file could be read-only or locked by another process."
                  ))
            return self.save()

        try:
            read_savegame_template(db)

            db("BEGIN")
            self.world.save(db)
            self.view.save(db)
            self.ingame_gui.save(db)
            self.scenario_eventhandler.save(db)

            # Store RNG state
            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 Exception:
            self.log.error("Save Exception:")
            traceback.print_exc()
            # remove invalid savegamefile (but close db connection before deleting)
            db.close()
            os.unlink(savegame)
            return False
Example #25
0
    def autosave(self):
        """Called automatically in an interval"""
        if self.in_editor_mode():
            return

        self.log.debug("Session: autosaving")
        success = self._do_save(SavegameManager.create_autosave_filename())
        if success:
            SavegameManager.delete_dispensable_savegames(autosaves=True)
            self.ingame_gui.message_widget.add(point=None, string_id="AUTOSAVE")
Example #26
0
 def quicksave(self):
     """Called when user presses the quicksave hotkey"""
     self.log.debug("Session: quicksaving")
     # call saving through horizons.main and not directly through session, so that save errors are handled
     success = self.save(SavegameManager.create_quicksave_filename())
     if success:
         self.ingame_gui.message_widget.add(None, None, 'QUICKSAVE')
         SavegameManager.delete_dispensable_savegames(quicksaves=True)
     else:
         self.gui.show_popup(_('Error'), _('Failed to quicksave.'))
Example #27
0
	def quicksave(self):
		"""Called when user presses the quicksave hotkey"""
		self.log.debug("Session: quicksaving")
		# call saving through horizons.main and not directly through session, so that save errors are handled
		success = self.save(SavegameManager.create_quicksave_filename())
		if success:
			self.ingame_gui.message_widget.add(None, None, 'QUICKSAVE')
			SavegameManager.delete_dispensable_savegames(quicksaves = True)
		else:
			self.gui.show_popup(_('Error'), _('Failed to quicksave.'))
Example #28
0
    def save(self, savegamename=None):
        """Saves a game
		@param savegamename: string with the full path of the savegame file or None to let user pick one
		@return: bool, whether save was successfull
		"""
        if savegamename is None:
            savegamename = self.gui.show_select_savegame(mode='save')
            if savegamename is None:
                return False  # user aborted dialog
            savegamename = SavegameManager.create_filename(savegamename)

        savegame = savegamename
        assert os.path.isabs(savegame)
        self.log.debug("Session: Saving to %s", savegame)
        try:
            if os.path.exists(savegame):
                os.unlink(savegame)
            shutil.copyfile(PATHS.SAVEGAME_TEMPLATE, savegame)
            self.savecounter += 1

            db = DbReader(savegame)
        except IOError:  # usually invalid filename
            self.gui.show_popup(_("Invalid filename"),
                                _("You entered an invalid filename."))
            return self.save(
            )  # retry with new savegamename entered by the user
            # this must not happen with quicksave/autosave

        try:
            db("BEGIN")
            self.world.save(db)
            #self.manager.save(db)
            self.view.save(db)
            self.ingame_gui.save(db)
            self.scenario_eventhandler.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)

            SavegameManager.write_metadata(db, self.savecounter)
            # make sure everything get's 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
Example #29
0
    def autosave(self):
        """Called automatically in an interval"""
        if self.in_editor_mode():
            return

        self.log.debug("Session: autosaving")
        success = self._do_save(SavegameManager.create_autosave_filename())
        if success:
            SavegameManager.delete_dispensable_savegames(autosaves=True)
            self.ingame_gui.message_widget.add(point=None,
                                               string_id='AUTOSAVE')
    def prepare(self):
        if self._mode == 'load':
            self._map_files, self._map_file_display = SavegameManager.get_saves(
            )
            if not self._map_files:
                self._windows.open_popup(
                    T("No saved games"),
                    T("There are no saved games to load."))
                return False
        elif self._mode == 'save':
            self._map_files, self._map_file_display = SavegameManager.get_regular_saves(
            )
        elif self._mode == 'editor-save':
            self._map_files, self._map_file_display = SavegameManager.get_maps(
            )

        self._gui.distributeInitialData(
            {'savegamelist': self._map_file_display})
        if self._mode == 'load':
            self._gui.distributeData({'savegamelist': 0})

        self._cb = self._create_show_savegame_details(self._gui,
                                                      self._map_files,
                                                      'savegamelist')
        if self._mode in ('save', 'editor-save'):

            def selected_changed():
                """Fills in the name of the savegame in the textbox when selected in the list"""
                if self._gui.collectData(
                        'savegamelist'
                ) == -1:  # set blank if nothing is selected
                    self._gui.findChild(name="savegamefile").text = u""
                else:
                    savegamefile = self._map_file_display[
                        self._gui.collectData('savegamelist')]
                    self._gui.distributeData({'savegamefile': savegamefile})

            self._cb = Callback.ChainedCallbacks(self._cb, selected_changed)

        self._cb()  # Refresh data on start
        self._gui.mapEvents({'savegamelist/action': self._cb})
        self._gui.findChild(name="savegamelist").capture(
            self._cb, event_name="keyPressed")
        self._gui.findChild(name="savegamelist").capture(
            self.check_double_click, event_name="mousePressed")

        self.return_events = {
            OkButton.DEFAULT_NAME: True,
            CancelButton.DEFAULT_NAME: False,
            DeleteButton.DEFAULT_NAME: 'delete'
        }
        if self._mode in ('save', 'editor-save'):
            self.return_events['savegamefile'] = True
Example #31
0
	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.ingame_gui.show_error_popup(headline, descr, advice, unicode(e))
			# retry with new savegamename entered by the user
			# (this must not happen with quicksave/autosave)
			return self.save()
		except OSError as e:
			if e.errno != errno.EACCES:
				raise
			self.ingame_gui.show_error_popup(
				_("Access is denied"),
				_("The savegame file could be read-only or locked by another process.")
			)
			return self.save()

		try:
			read_savegame_template(db)

			db("BEGIN")
			self.world.save(db)
			self.view.save(db)
			self.ingame_gui.save(db)
			self.scenario_eventhandler.save(db)

			# Store RNG state
			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 Exception:
			self.log.error("Save Exception:")
			traceback.print_exc()
			# remove invalid savegamefile (but close db connection before deleting)
			db.close()
			os.unlink(savegame)
			return False
Example #32
0
	def save(self, savegamename=None):
		"""Saves a game
		@param savegamename: string with the full path of the savegame file or None to let user pick one
		@return: bool, whether save was successfull
		"""
		if savegamename is None:
			savegamename = self.gui.show_select_savegame(mode='save')
			if savegamename is None:
				return False # user aborted dialog
			savegamename = SavegameManager.create_filename(savegamename)

		savegame = savegamename
		assert os.path.isabs(savegame)
		self.log.debug("Session: Saving to %s", savegame)
		try:
			if os.path.exists(savegame):
				os.unlink(savegame)
			shutil.copyfile(PATHS.SAVEGAME_TEMPLATE, savegame)
			self.savecounter += 1

			db = DbReader(savegame)
		except IOError: # usually invalid filename
			self.gui.show_popup(_("Invalid filename"), _("You entered an invalid filename."))
			return self.save() # retry with new savegamename entered by the user
			# this must not happen with quicksave/autosave

		try:
			db("BEGIN")
			self.world.save(db)
			#self.manager.save(db)
			self.view.save(db)
			self.ingame_gui.save(db)
			self.scenario_eventhandler.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)

			SavegameManager.write_metadata(db, self.savecounter)
			# make sure everything get's 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
Example #33
0
	def quicksave(self):
		"""Called when user presses the quicksave hotkey"""
		self.log.debug("Session: quicksaving")
		# call saving through horizons.main and not directly through session, so that save errors are handled
		success = self._do_save(SavegameManager.create_quicksave_filename())
		if success:
			SavegameManager.delete_dispensable_savegames(quicksaves=True)
			self.ingame_gui.message_widget.add('QUICKSAVE')
		else:
			headline = _("Failed to quicksave.")
			descr = _("An error happened during quicksave.") + u"\n" + _("Your game has not been saved.")
			advice = _("If this error happens again, please contact the development team: "
			           "{website}").format(website="http://unknown-horizons.org/support/")
			self.ingame_gui.open_error_popup(headline, descr, advice)
Example #34
0
	def quicksave(self):
		"""Called when user presses the quicksave hotkey"""
		self.log.debug("Session: quicksaving")
		# call saving through horizons.main and not directly through session, so that save errors are handled
		success = self._do_save(SavegameManager.create_quicksave_filename())
		if success:
			SavegameManager.delete_dispensable_savegames(quicksaves=True)
			self.ingame_gui.message_widget.add('QUICKSAVE')
		else:
			headline = T("Failed to quicksave.")
			descr = T("An error happened during quicksave.") + "\n" + T("Your game has not been saved.")
			advice = T("If this error happens again, please contact the development team: "
			           "{website}").format(website="http://unknown-horizons.org/support/")
			self.ingame_gui.open_error_popup(headline, descr, advice)
Example #35
0
def _start_map(map_name, ai_players=0, human_ai=False, is_scenario=False, campaign=None,
               pirate_enabled=True, trader_enabled=True, force_player_id=None):
	"""Start a map specified by user
	@param map_name: name of map or path to map
	@return: bool, whether loading succeded"""
	if is_scenario:
		savegames = SavegameManager.get_available_scenarios(locales=True)
	else:
		savegames = SavegameManager.get_maps()
	map_file = _find_matching_map(map_name, savegames)
	if not map_file:
		return False
	load_game(ai_players, human_ai, map_file, is_scenario, campaign=campaign,
	          trader_enabled=trader_enabled, pirate_enabled=pirate_enabled, force_player_id=force_player_id)
	return True
    def _delete_savegame(self, map_files):
        """Deletes the selected savegame if the user confirms
		self._gui has to contain the widget "savegamelist"
		@param map_files: list of files that corresponds to the entries of 'savegamelist'
		@return: True if something was deleted, else False
		"""
        selected_item = self._gui.collectData("savegamelist")
        if selected_item == -1 or selected_item >= len(map_files):
            self._windows.open_popup(
                T("No file selected"),
                T("You need to select a savegame to delete."))
            return False
        selected_file = map_files[selected_item]
        message = T(
            "Do you really want to delete the savegame '{name}'?").format(
                name=SavegameManager.get_savegamename_from_filename(
                    selected_file))
        if self._windows.open_popup(T("Confirm deletion"),
                                    message,
                                    show_cancel_button=True):
            try:
                os.unlink(selected_file)
                return True
            except:
                self._windows.open_popup(T("Error!"),
                                         T("Failed to delete savefile!"))
                return False
        else:  # player cancelled deletion
            return False
	def show(self):
		self._aidata.hide()

		self._files, maps_display = SavegameManager.get_available_scenarios(hide_test_scenarios=True)

		# get the map files and their display names. display tutorials on top.
		prefer_tutorial = lambda x: ('tutorial' not in x, x)
		maps_display.sort(key=prefer_tutorial)
		self._files.sort(key=prefer_tutorial)

		self._gui.distributeInitialData({'maplist' : maps_display})
		if maps_display:
			self._gui.distributeData({'maplist': 0})

		# add all locales to lang list, select current locale as default and sort
		lang_list = self._gui.findChild(name="uni_langlist")
		lang_list.items = self._get_available_languages()
		cur_locale = horizons.globals.fife.get_locale()
		if LANGUAGENAMES[cur_locale] in lang_list.items:
			lang_list.selected = lang_list.items.index(LANGUAGENAMES[cur_locale])
		else:
			lang_list.selected = 0

		self._gui.mapEvents({
			'maplist/action': self._update_infos,
			'uni_langlist/action': self._update_infos,
		})
		self._update_infos()
Example #38
0
	def save(self, savegamename=None):
		"""Saves a game
		@param savegamename: string with the full path of the savegame file or None to let user pick one
		@return: bool, whether no error happened (user aborting dialog means success)
		"""
		if savegamename is None:
			savegamename = self.gui.show_select_savegame(mode='save')
			if savegamename is None:
				return True # user aborted dialog
			savegamename = SavegameManager.create_filename(savegamename)

		savegame = savegamename
		assert os.path.isabs(savegame)
		self.log.debug("Session: Saving to %s", savegame)
		try:
			if os.path.exists(savegame):
				os.unlink(savegame)
			shutil.copyfile(PATHS.SAVEGAME_TEMPLATE, savegame)
			self.savecounter += 1

			db = DbReader(savegame)
		except IOError, 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
Example #39
0
    def save(self, savegamename=None):
        """Saves a game
		@param savegamename: string with the full path of the savegame file or None to let user pick one
		@return: bool, whether no error happened (user aborting dialog means success)
		"""
        if savegamename is None:
            savegamename = self.gui.show_select_savegame(mode='save')
            if savegamename is None:
                return True  # user aborted dialog
            savegamename = SavegameManager.create_filename(savegamename)

        savegame = savegamename
        assert os.path.isabs(savegame)
        self.log.debug("Session: Saving to %s", savegame)
        try:
            if os.path.exists(savegame):
                os.unlink(savegame)
            shutil.copyfile(PATHS.SAVEGAME_TEMPLATE, savegame)
            self.savecounter += 1

            db = DbReader(savegame)
        except IOError, 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
	def show(self):
		self._files, self._maps_display = SavegameManager.get_maps()

		self._gui.distributeInitialData({
			'maplist': self._maps_display,
			'playerlimit': range(2, MULTIPLAYER.MAX_PLAYER_COUNT)
		})

		if self._maps_display: # select first entry
			self._gui.distributeData({
				'maplist': 0,
				'playerlimit': 0
			})
			self._update_infos()

		self._gui.findChild(name="maplist").mapEvents({
			'maplist/action': self._update_infos
		})
		
		gamenametextfield = self._gui.findChild(name='gamename')
		def gamename_clicked():
			if gamenametextfield.text == 'Unnamed Game':
				gamenametextfield.text = ""
		gamenametextfield.capture(gamename_clicked, event_name='mouseClicked')
		self._gui.show()
Example #41
0
def _load_map(savegamename):
    """Load a map specified by user
	@return: bool, whether loading succeded"""
    saves = SavegameManager.get_saves()
    map_file = None
    for i in xrange(0, len(saves[1])):
        # exact match
        if saves[1][i] == savegamename:
            map_file = saves[0][i]
            break
        # check for partial match
        if saves[1][i].startswith(savegamename):
            if map_file is not None:
                # multiple matches, collect all for output
                map_file += u'\n' + saves[0][i]
            else:
                map_file = saves[0][i]
    if map_file is None:
        print _("Error: Cannot find savegame \"%s\".") % savegamename
        return False
    if len(map_file.splitlines()) > 1:
        print _("Error: Found multiple matches: ")
        for match in map_file.splitlines():
            print os.path.basename(match)
        return False
    load_game(map_file)
    return True
Example #42
0
 def quicksave(self):
     self.ingame_gui.open_popup(
         T("Not possible"),
         T("Save/load for multiplayer games is not possible yet"))
     return  #TODO disabled for now, see #2151 for details
     SaveCommand(
         SavegameManager.create_multiplayer_quicksave_name()).execute(self)
	def __create_game(self, load=None, chosen_map=None):
		"""
		Actually create a game, join it, and display the lobby.

		@param load: game data tuple for creating loaded games
		@param chosen_map: the name of the map to start a new game on (overrides the gui)
		"""
		# create the game
		if load:
			mapname, gamename = load
			path = SavegameManager.get_multiplayersave_map(mapname)
			maxplayers = SavegameAccessor.get_players_num(path)
			load = SavegameAccessor.get_hash(path)
		else:
			mapindex = None
			if chosen_map is not None:
				for i, map in enumerate(self.maps_display):
					if map == chosen_map:
						mapindex = i
						break

			if mapindex is None:
				mapindex = self.current.collectData('maplist')
			mapname = self.maps_display[mapindex]
			maxplayers = self.current.collectData('playerlimit') + 2 # 1 is the first entry
			gamename = self.current.collectData('gamename')
			load = None

		game = NetworkInterface().creategame(mapname, maxplayers, gamename, load)
		if game is None:
			return

		self.__show_gamelobby()
    def show(self):
        self._files, self._maps_display = SavegameManager.get_maps()

        self._gui.distributeInitialData({
            'maplist':
            self._maps_display,
            'playerlimit':
            range(2, MULTIPLAYER.MAX_PLAYER_COUNT)
        })

        if self._maps_display:  # select first entry
            self._gui.distributeData({'maplist': 0, 'playerlimit': 0})
            self._update_infos()

        self._gui.findChild(name="maplist").mapEvents(
            {'maplist/action': self._update_infos})

        gamenametextfield = self._gui.findChild(name='gamename')

        def gamename_clicked():
            if gamenametextfield.text == 'Unnamed Game':
                gamenametextfield.text = ""

        gamenametextfield.capture(gamename_clicked, event_name='mouseClicked')
        self._gui.show()
 def _update_free_map_infos(self):
     number_of_players = SavegameManager.get_recommended_number_of_players(
         self._get_selected_map())
     #xgettext:python-format
     self.current.findChild(name="recommended_number_of_players_lbl").text = \
      _("Recommended number of players: {number}").format(number=number_of_players)
     self.map_preview.update_map(self._get_selected_map())
		def _update_infos():
			mapindex = self.current.collectData('maplist')
			mapfile = self.current.files[mapindex]
			number_of_players = SavegameManager.get_recommended_number_of_players(mapfile)
			#xgettext:python-format
			self.current.findChild(name="recommended_number_of_players_lbl").text = \
					_("Recommended number of players: {number}").format(number=number_of_players)
Example #47
0
def _start_campaign(campaign_name):
	"""Finds the first scenario in this campaign and
	loads it.
	@return: bool, whether loading succeded"""
	if os.path.exists(campaign_name):
		# a file was specified. In order to make sure everything works properly,
		# we need to copy the file over to the UH campaign directory.
		# This is not very clean, but it's safe.

		if not campaign_name.endswith(".yaml"):
			print _("Error: campaign filenames have to end in \".yaml\".")
			return False

		# check if the user specified a file in the UH campaign dir
		campaign_basename = os.path.basename( campaign_name )
		path_in_campaign_dir = os.path.join(SavegameManager.campaigns_dir, campaign_basename)
		if not (os.path.exists(path_in_campaign_dir) and \
		        os.path.samefile(campaign_name, path_in_campaign_dir)):
			print _("Due to technical reasons, the campaign file will be copied to the UH campaign directory (%s).") % SavegameManager.campaigns_dir + \
			      "\n" + _("This means that changes in the file you specified will not apply to the game directly.") + \
			      _("To see the changes, either always start UH with the current arguments or edit the file %s.") % path_in_campaign_dir
			shutil.copy(campaign_name, SavegameManager.campaigns_dir)
		# use campaign file name below
		campaign_name = os.path.splitext( campaign_basename )[0]
	campaign = SavegameManager.get_campaign_info(name = campaign_name)
	if not campaign:
		print _("Error: Cannot find campaign \"%s\".") % campaign_name
		return False
	scenarios = [sc.get('level') for sc in campaign.get('scenarios',[])]
	if not scenarios:
		return False
	return _start_map(scenarios[0], 0, False, is_scenario = True, campaign = {'campaign_name': campaign_name, 'scenario_index': 0, 'scenario_name': scenarios[0]})
	def show(self):
		self._aidata.hide()

		self._scenarios = SavegameManager.get_available_scenarios()

		# get the map files and their display names. display tutorials on top.
		self.maps_display = self._scenarios.keys()
		if not self.maps_display:
			return

		prefer_tutorial = lambda x: ('tutorial' not in x, x)
		self.maps_display.sort(key=prefer_tutorial)

		self._gui.distributeInitialData({'maplist' : self.maps_display})
		self._gui.distributeData({'maplist': 0})

		# add all locales to lang list, select current locale as default and sort
		scenario_langs = list(set(l for s in self._scenarios.values() for l, filename in s))
		lang_list = self._gui.findChild(name="uni_langlist")
		lang_list.items = sorted([LANGUAGENAMES[l] for l in scenario_langs])

		cur_locale = horizons.globals.fife.get_locale()
		if LANGUAGENAMES[cur_locale] in lang_list.items:
			lang_list.selected = lang_list.items.index(LANGUAGENAMES[cur_locale])
		else:
			lang_list.selected = 0

		self._gui.mapEvents({
			'maplist/action': self._update_infos,
			'uni_langlist/action': self._update_infos,
		})
		self._update_infos()
Example #49
0
    def show(self):
        self._aidata.hide()

        self._scenarios = SavegameManager.get_available_scenarios()

        # get the map files and their display names. display tutorials on top.
        self.maps_display = self._scenarios.keys()
        if not self.maps_display:
            return

        prefer_tutorial = lambda x: ('tutorial' not in x, x)
        self.maps_display.sort(key=prefer_tutorial)

        self._gui.distributeInitialData({'maplist': self.maps_display})
        self._gui.distributeData({'maplist': 0})

        # add all locales to lang list, select current locale as default and sort
        scenario_langs = list(
            set(l for s in self._scenarios.values() for l, filename in s))
        lang_list = self._gui.findChild(name="uni_langlist")
        lang_list.items = sorted([LANGUAGENAMES[l] for l in scenario_langs])

        cur_locale = horizons.globals.fife.get_locale()
        if LANGUAGENAMES[cur_locale] in lang_list.items:
            lang_list.selected = lang_list.items.index(
                LANGUAGENAMES[cur_locale])
        else:
            lang_list.selected = 0

        self._gui.mapEvents({
            'maplist/action': self._update_infos,
            'uni_langlist/action': self._update_infos,
        })
        self._update_infos()
Example #50
0
 def quicksave(self):
     """Called when user presses the quicksave hotkey"""
     self.log.debug("Session: quicksaving")
     # call saving through horizons.main and not directly through session, so that save errors are handled
     success = self.save(SavegameManager.create_quicksave_filename())
     if success:
         self.ingame_gui.message_widget.add(None, None, 'QUICKSAVE')
         SavegameManager.delete_dispensable_savegames(quicksaves=True)
     else:
         headline = _(u"Failed to quicksave.")
         descr = _(
             u"An error happened during quicksave. Your game has not been saved."
         )
         advice = _(u"If this error happens again, please contact the development team:") + \
                    u"unknown-horizons.org/support/"
         self.gui.show_error_popup(headline, descr, advice)
Example #51
0
def _load_map(savegame, ai_players, human_ai, force_player_id=None):
	"""Load a map specified by user.
	@param savegame: eiter the displayname of a savegame or a path to a savegame
	@return: bool, whether loading succeded"""
	# first check for partial or exact matches in the normal savegame list
	saves = SavegameManager.get_saves()
	map_file = None
	for i in xrange(0, len(saves[1])):
		# exact match
		if saves[1][i] == savegame:
			map_file = saves[0][i]
			break
		# check for partial match
		if saves[1][i].startswith(savegame):
			if map_file is not None:
				# multiple matches, collect all for output
				map_file += u'\n' + saves[0][i]
			else:
				map_file = saves[0][i]
	if map_file is None:
		# not a savegame, check for path to file or fail
		if os.path.exists(savegame):
			map_file = savegame
		else:
			#xgettext:python-format
			print u"Error: Cannot find savegame '{name}'.".format(name=savegame)
			return False
	if len(map_file.splitlines()) > 1:
		print "Error: Found multiple matches:"
		for match in map_file.splitlines():
			print os.path.basename(match)
		return False
	load_game(savegame=map_file, force_player_id=force_player_id)
	return True
Example #52
0
    def editor_load_map(self):
        """Show a dialog for the user to select a map to edit."""
        old_current = self._switch_current_widget('editor_select_map')
        self.current.show()

        map_files, map_file_display = SavegameManager.get_maps()
        self.current.distributeInitialData({'maplist': map_file_display})

        bind = {
            OkButton.DEFAULT_NAME: True,
            CancelButton.DEFAULT_NAME: False,
        }
        retval = self.show_dialog(self.current, bind)
        if not retval:
            # Dialog cancelled
            self.current = old_current
            return False

        selected_map_index = self.current.collectData('maplist')
        if selected_map_index == -1:
            # No map selected yet => select first available one
            self.current.distributeData({'maplist': 0})

        self.current = old_current
        self.show_loading_screen()
        horizons.main.edit_map(map_files[selected_map_index])
        return True
Example #53
0
def _start_dev_map(ai_players, human_ai, force_player_id):
	# start the development map
	for m in SavegameManager.get_maps()[0]:
		if 'development' in m:
			break
	load_game(ai_players, human_ai, m, force_player_id=force_player_id)
	return True
	def _update_map_infos(self):
		map_file = self._get_selected_map()

		number_of_players = SavegameManager.get_recommended_number_of_players(map_file)
		lbl = self._gui.findChild(name="recommended_number_of_players_lbl")
		lbl.text = _("Recommended number of players: {number}").format(number=number_of_players)

		self._update_map_preview(map_file)
 def _update_infos():
     mapindex = self.current.collectData('maplist')
     mapfile = self.current.files[mapindex]
     number_of_players = SavegameManager.get_recommended_number_of_players(
         mapfile)
     #xgettext:python-format
     self.current.findChild(name="recommended_number_of_players_lbl").text = \
       _("Recommended number of players: {number}").format(number=number_of_players)
	def _init_gui(self):
		self._gui = load_xml_translated("stringpreviewwidget.xml")
		self._gui.mapEvents({ 'load' : self.load })
		self.scenarios = SavegameManager.get_scenarios()
		self.listbox = self._gui.findChild(name="scenario_list")
		self.listbox.items = self.scenarios[1]

		self.logbook = LogBook()
Example #57
0
def _start_map(map_name, ai_players=0, is_scenario=False,
               pirate_enabled=True, trader_enabled=True, force_player_id=None, is_map=False):
	"""Start a map specified by user
	@param map_name: name of map or path to map
	@return: bool, whether loading succeeded"""
	if is_scenario:
		map_file = _find_scenario(map_name, SavegameManager.get_available_scenarios(locales=True))
	else:
		map_file = _find_map(map_name, SavegameManager.get_maps())

	if not map_file:
		return False

	options = StartGameOptions.create_start_singleplayer(map_file, is_scenario,
		ai_players, trader_enabled, pirate_enabled, force_player_id, is_map)
	start_singleplayer(options)
	return True
Example #58
0
def edit_map(map_name):
	"""
	Start editing the map file specified by the name.

	@param map_name: name of map or path to map
	@return: bool, whether loading succeeded
	"""
	return _edit_map(_find_map(map_name, SavegameManager.get_maps()))
 def __show_load_game(self):
     ret = self.show_select_savegame(mode='mp_load')
     if ret is None:  # user aborted
         return
     path, gamename, gamepassword = ret
     # get name from path
     paths, names = SavegameManager.get_multiplayersaves()
     mapname = names[paths.index(path)]
     self.__create_game(load=(mapname, gamename, gamepassword))