def end(self, keep_map=False, remove_savegame=True):
		"""
		Clean up temporary files.
		"""
		super(SPTestSession, self).end()

		# remove the saved game
		savegame_db = SavegameAccessor(self.savegame, self.started_from_map)
		savegame_db.close()
		if remove_savegame and not self.started_from_map:
			os.remove(self.savegame)
Beispiel #2
0
    def end(self, keep_map=False, remove_savegame=True):
        """
		Clean up temporary files.
		"""
        super(SPTestSession, self).end()

        # remove the saved game
        savegame_db = SavegameAccessor(self.savegame, self.started_from_map)
        savegame_db.close()
        if remove_savegame and not self.started_from_map:
            os.remove(self.savegame)
Beispiel #3
0
	def end(self, keep_map=False, remove_savegame=True):
		"""
		Clean up temporary files.
		"""
		super(SPTestSession, self).end()

		# Find all islands in the map first
		savegame_db = SavegameAccessor(self.savegame)
		if not keep_map:
			for (island_file, ) in savegame_db('SELECT file FROM island'):
				if not island_file.startswith('random:'): # random islands don't exist as files
					os.remove(island_file)

		# Finally remove savegame
		savegame_db.close()
		if remove_savegame:
			os.remove(self.savegame)
Beispiel #4
0
def edit_game_map(saved_game_name):
	"""
	Start editing the specified map.

	@param map_name: name of map or path to map
	@return: bool, whether loading succeeded
	"""
	saved_games = SavegameManager.get_saves()
	saved_game_path = _find_map(saved_game_name, saved_games)
	if not saved_game_path:
		return False

	accessor = SavegameAccessor(saved_game_path, False)
	map_name = accessor.map_name
	accessor.close()
	if isinstance(map_name, list):
		# a random map represented by a list of island strings
		return _edit_map(map_name)
	return edit_map(map_name)
Beispiel #5
0
def edit_game_map(saved_game_name):
	"""
	Start editing the specified map.

	@param map_name: name of map or path to map
	@return: bool, whether loading succeeded
	"""
	saved_games = SavegameManager.get_saves()
	saved_game_path = _find_matching_map(saved_game_name, saved_games)
	if not saved_game_path:
		return False

	accessor = SavegameAccessor(saved_game_path, False)
	map_name = accessor.map_name
	accessor.close()
	if isinstance(map_name, list):
		# a random map represented by a list of island strings
		return _edit_map(map_name)
	return edit_map(map_name)
    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, gamepassword = load
            path = SavegameManager.get_multiplayersave_map(mapname)
            maxplayers = SavegameAccessor.get_players_num(path)
            password = gamepassword
            maphash = 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')
            password = self.current.collectData('password')
            maphash = ""

        password = hashlib.sha1(password).hexdigest() if password != "" else ""
        game = NetworkInterface().creategame(mapname, maxplayers, gamename,
                                             maphash, password)
        if game is None:
            return

        self.__show_gamelobby()
	def __update_game_details(self, game=None):
		"""Set map name and other misc data in a widget. Only possible in certain states"""
		if game is None:
			game = self.__get_selected_game()
			if game is None:
				return
		#xgettext:python-format
		self.current.findChild(name="game_map").text = _("Map: {map_name}").format(map_name=game.get_map_name())
		self.current.findChild(name="game_name").text = _("Name: {game_name}").format(game_name=game.get_name())
		self.current.findChild(name="game_creator").text = _("Creator: {game_creator}").format(game_creator=game.get_creator())
		#xgettext:python-format
		self.current.findChild(name="game_playersnum").text = _("Players: {player_amount}/{player_limit}").format(
		                           player_amount=game.get_player_count(),
		                           player_limit=game.get_player_limit())
		vbox_inner = self.current.findChild(name="game_info")
		if game.is_savegame(): # work around limitations of current systems via messages
			path = SavegameManager.get_multiplayersave_map(game.mapname)
			btn_name = "save_missing_help_button"
			btn = vbox_inner.findChild(name=btn_name)
			if SavegameAccessor.get_hash(path) != game.get_map_hash():
				text = ""
				if btn is None:
					btn = Button(name=btn_name)
					btn.text = _("This savegame is missing (click here)")
					last_elem = vbox_inner.findChild(name="game_info_last")
					if last_elem is None: # no last elem -> we are last
						vbox_inner.addChild( btn )
					else:
						vbox_inner.insertChildBefore( btn, last_elem )
				btn_text = _(u"For multiplayer load, it is necessary for you to have the correct savegame file.") + u"\n"
				btn_text += _(u"The file will be downloaded when the game starts.")
				btn.btn_text = btn_text
				def show():
					self.show_popup(_("Help"), btn_text, size=1)
				btn.capture(show)

			else:
				text = _(u"This is a savegame.")
				if btn is not None:
					btn.hide()

			if text:
				self.current.findChild(name="game_isloaded").text = text

		self.__update_players_box(game)

		vbox_inner.adaptLayout() # inner vbox always exists
		vbox = self.current.findChild(name="gamedetailsbox")
		if vbox is not None:
			vbox.adaptLayout()
	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, gamepassword = load
			path = SavegameManager.get_multiplayersave_map(mapname)
			maxplayers = SavegameAccessor.get_players_num(path)
			password = gamepassword
			maphash = 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')
			password = self.current.collectData('password')
			maphash = ""


		password = hashlib.sha1(password).hexdigest() if password != "" else ""
		game = NetworkInterface().creategame(mapname, maxplayers, gamename, maphash, password)
		if game is None:
			return

		self.__show_gamelobby()
def test_save_trivial(session, _):
	"""
	Let 2 AI players play for a while, then attempt to save the game.

	Be aware, this is a pretty simple test and it doesn't actually check what is
	being saved.
	"""
	session.run(seconds=4*60)

	fd, filename = tempfile.mkstemp()
	os.close(fd)

	assert session.save(savegamename=filename)

	SavegameAccessor(filename, False)

	os.unlink(filename)
	def __actual_join(self, game=None, password=""):
		"""Does the actual joining to the game.

		 This method is called after everything is OK for joining."""
		if game is None:
			return False

		self.__apply_new_nickname()
		self.__apply_new_color()

		fetch = False
		if game.is_savegame() and SavegameAccessor.get_hash(SavegameManager.get_multiplayersave_map(game.mapname)) != game.get_map_hash():
			fetch = True

		if not NetworkInterface().joingame(game.get_uuid(), password, fetch):
			return False
		self.__show_gamelobby()
		return True
    def __actual_join(self, game=None, password=""):
        """Does the actual joining to the game.

		 This method is called after everything is OK for joining."""
        if game is None:
            return False

        self.__apply_new_nickname()
        self.__apply_new_color()

        fetch = False
        if game.is_savegame() and SavegameAccessor.get_hash(
                SavegameManager.get_multiplayersave_map(
                    game.mapname)) != game.get_map_hash():
            fetch = True

        if not NetworkInterface().joingame(game.get_uuid(), password, fetch):
            return False
        self.__show_gamelobby()
        return True
Beispiel #12
0
def load_raw_world(map_file):
    WorldObject.reset()
    world = World(session=None)
    world.inited = True
    world.load_raw_map(SavegameAccessor(map_file, True), preview=True)
    return world
Beispiel #13
0
	def load(self, savegame, players, trader_enabled, pirate_enabled,
	         natural_resource_multiplier, is_scenario=False, campaign=None,
	         force_player_id=None, disasters_enabled=True, is_multiplayer=False):
		"""Loads a map. Key method for starting a game.
		@param savegame: path to the savegame database.
		@param players: iterable of dictionaries containing id, name, color, local, ai, and difficulty
		@param is_scenario: Bool whether the loaded map is a scenario or not
		@param force_player_id: the worldid of the selected human player or default if None (debug option)
		"""
		"""
		TUTORIAL: Here you see how the vital game elements (and some random things that are also required)
		are initialised.
		"""
		if is_scenario:
			# savegame is a yaml file, that contains reference to actual map file
			self.scenario_eventhandler = ScenarioEventHandler(self, savegame)
			# scenario maps can be normal maps or scenario maps:
			map_filename = self.scenario_eventhandler.get_map_file()
			savegame = os.path.join(SavegameManager.scenario_maps_dir, map_filename)
			if not os.path.exists(savegame):
				savegame = os.path.join(SavegameManager.maps_dir, map_filename)
		self.campaign = {} if not campaign else campaign

		self.log.debug("Session: Loading from %s", savegame)
		savegame_db = SavegameAccessor(savegame) # Initialize new dbreader
		savegame_data = SavegameManager.get_metadata(savegame)

		# 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, force_player_id, disasters_enabled=disasters_enabled)
		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, lambda p1, p2: cmp(p1['id'], p2['id'])):
				self.world.setup_player(i['id'], i['name'], i['color'], i['clientid'] if is_multiplayer else None, i['local'], i['ai'], i['difficulty'])
			self.world.set_forced_player(force_player_id)
			center = self.world.init_new_world(trader_enabled, pirate_enabled, natural_resource_multiplier)
			self.view.center(center[0], center[1])
		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'
		"""
Beispiel #14
0
    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 __update_game_details(self, game=None):
        """Set map name and other misc data in a widget. Only possible in certain states"""
        if game is None:
            game = self.__get_selected_game()
            if game is None:
                return
        #xgettext:python-format
        self.current.findChild(
            name="game_map").text = _("Map: {map_name}").format(
                map_name=game.get_map_name())
        self.current.findChild(
            name="game_name").text = _("Name: {game_name}").format(
                game_name=game.get_name())
        self.current.findChild(
            name="game_creator").text = _("Creator: {game_creator}").format(
                game_creator=game.get_creator())
        #xgettext:python-format
        self.current.findChild(name="game_playersnum").text = _(
            "Players: {player_amount}/{player_limit}").format(
                player_amount=game.get_player_count(),
                player_limit=game.get_player_limit())
        vbox_inner = self.current.findChild(name="game_info")
        if game.is_savegame(
        ):  # work around limitations of current systems via messages
            path = SavegameManager.get_multiplayersave_map(game.mapname)
            btn_name = "save_missing_help_button"
            btn = vbox_inner.findChild(name=btn_name)
            if SavegameAccessor.get_hash(path) != game.get_map_hash():
                text = ""
                if btn is None:
                    btn = Button(name=btn_name)
                    btn.text = _("This savegame is missing (click here)")
                    last_elem = vbox_inner.findChild(name="game_info_last")
                    if last_elem is None:  # no last elem -> we are last
                        vbox_inner.addChild(btn)
                    else:
                        vbox_inner.insertChildBefore(btn, last_elem)
                btn_text = _(
                    u"For multiplayer load, it is necessary for you to have the correct savegame file."
                ) + u"\n"
                btn_text += _(
                    u"The file will be downloaded when the game starts.")
                btn.btn_text = btn_text

                def show():
                    self.show_popup(_("Help"), btn_text, size=1)

                btn.capture(show)

            else:
                text = _(u"This is a savegame.")
                if btn is not None:
                    btn.hide()

            if text:
                self.current.findChild(name="game_isloaded").text = text

        self.__update_players_box(game)

        vbox_inner.adaptLayout()  # inner vbox always exists
        vbox = self.current.findChild(name="gamedetailsbox")
        if vbox is not None:
            vbox.adaptLayout()
	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 initialized.
		"""
		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, options) # 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)

		LoadingProgress.broadcast(self, 'session_create_world')
		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, self.world) # 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 be old scheduled ticks).
		LoadingProgress.broadcast(self, "session_index_fish")
		self.world.init_fish_indexer() # now the fish should exist

		# load the old gui positions and stuff
		# Do this before loading selections, they need the minimap setup
		LoadingProgress.broadcast(self, "session_load_gui")
		self.ingame_gui = self._ingame_gui_class(self)
		self.ingame_gui.load(savegame_db)

		Scheduler().before_ticking()
		savegame_db.close()

		assert hasattr(self.world, "player"), 'Error: there is no human player'
		LoadingProgress.broadcast(self, "session_finish")
		"""
Beispiel #17
0
    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 initialized.
		"""
        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,
                                       options)  # 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)

        LoadingProgress.broadcast(self, 'session_create_world')
        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, self.world)  # 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 be old scheduled ticks).
        LoadingProgress.broadcast(self, "session_index_fish")
        self.world.init_fish_indexer()  # now the fish should exist

        # load the old gui positions and stuff
        # Do this before loading selections, they need the minimap setup
        LoadingProgress.broadcast(self, "session_load_gui")
        self.ingame_gui = self._ingame_gui_class(self)
        self.ingame_gui.load(savegame_db)

        Scheduler().before_ticking()
        savegame_db.close()

        assert hasattr(self.world, "player"), 'Error: there is no human player'
        LoadingProgress.broadcast(self, "session_finish")
        """
Beispiel #18
0
	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'
		"""