def __init__(self, dbfile):
		self.upgrader = SavegameUpgrader(dbfile)
		super(SavegameAccessor, self).__init__(dbfile=self.upgrader.get_path())
		self._load_building()
		self._load_settlement()
		self._load_concrete_object()
		self._load_production()
		self._load_storage()
		self._load_storage_slot_limit()
		self._load_wildanimal()
		self._load_unit()
		self._load_building_collector()
		self._load_production_line()
		self._load_unit_path()
		self._load_component()
		self._load_storage_global_limit()
	def __init__(self, game_identifier, is_map, options=None):
		is_random_map = False
		if is_map:
			self.upgrader = None
			handle, self._temp_path = tempfile.mkstemp()
			os.close(handle)
			super(SavegameAccessor, self).__init__(dbfile=self._temp_path)
			with open('content/savegame_template.sql') as savegame_template:
				self.execute_script(savegame_template.read())

			if isinstance(game_identifier, list):
				is_random_map = True
				random_island_sequence = game_identifier
			else:
				self._map_path = game_identifier
		else:
			self.upgrader = SavegameUpgrader(game_identifier)
			self._temp_path = None
			game_identifier = self.upgrader.get_path()
			super(SavegameAccessor, self).__init__(dbfile=game_identifier)

			map_name_data = self('SELECT value FROM metadata WHERE name = ?', 'map_name')
			if not map_name_data:
				is_random_map = True
				random_island_sequence = self('SELECT value FROM metadata WHERE name = ?', 'random_island_sequence')[0][0].split(' ')
			else:
				map_name = map_name_data[0][0]
				if map_name.startswith('USER_MAPS_DIR:'):
					self._map_path = PATHS.USER_MAPS_DIR + map_name[len('USER_MAPS_DIR:'):]
				elif os.path.isabs(map_name):
					self._map_path = map_name
				else:
					self._map_path = SavegameManager.get_filename_from_map_name(map_name)

		if is_random_map:
			handle, self._temp_path2 = tempfile.mkstemp()
			os.close(handle)
			random_map_db = DbReader(self._temp_path2)
			with open('content/map-template.sql') as map_template:
				random_map_db.execute_script(map_template.read())
			for island_id, island_string in enumerate(random_island_sequence):
				create_random_island(random_map_db, island_id, island_string)
			random_map_db.close()
			self._map_path = self._temp_path2

			self('INSERT INTO metadata VALUES(?, ?)', 'random_island_sequence',
				' '.join(random_island_sequence))

		if options is not None:
			if options.map_padding is not None:
				self("INSERT INTO map_properties VALUES(?, ?)", 'padding', options.map_padding)

		self('ATTACH ? AS map_file', self._map_path)
		if is_random_map:
			self.map_name = random_island_sequence
		elif os.path.isabs(self._map_path):
			self.map_name = self._map_path
		else:
			self.map_name = SavegameManager.get_savegamename_from_filename(self._map_path)

		map_padding = self("SELECT value FROM map_properties WHERE name = 'padding'")
		self.map_padding = int(map_padding[0][0]) if map_padding else MAP.PADDING

		self._load_building()
		self._load_settlement()
		self._load_concrete_object()
		self._load_production()
		self._load_storage()
		self._load_wildanimal()
		self._load_unit()
		self._load_building_collector()
		self._load_production_line()
		self._load_unit_path()
		self._load_storage_global_limit()
		self._load_health()
		self._load_fish_data()
		self._hash = None
class SavegameAccessor(DbReader):
	"""
	SavegameAccessor is the class used for loading saved games.

	Frequent select queries are preloaded for faster access.
	"""

	def __init__(self, game_identifier, is_map, options=None):
		is_random_map = False
		if is_map:
			self.upgrader = None
			handle, self._temp_path = tempfile.mkstemp()
			os.close(handle)
			super(SavegameAccessor, self).__init__(dbfile=self._temp_path)
			with open('content/savegame_template.sql') as savegame_template:
				self.execute_script(savegame_template.read())

			if isinstance(game_identifier, list):
				is_random_map = True
				random_island_sequence = game_identifier
			else:
				self._map_path = game_identifier
		else:
			self.upgrader = SavegameUpgrader(game_identifier)
			self._temp_path = None
			game_identifier = self.upgrader.get_path()
			super(SavegameAccessor, self).__init__(dbfile=game_identifier)

			map_name_data = self('SELECT value FROM metadata WHERE name = ?', 'map_name')
			if not map_name_data:
				is_random_map = True
				random_island_sequence = self('SELECT value FROM metadata WHERE name = ?', 'random_island_sequence')[0][0].split(' ')
			else:
				map_name = map_name_data[0][0]
				if map_name.startswith('USER_MAPS_DIR:'):
					self._map_path = PATHS.USER_MAPS_DIR + map_name[len('USER_MAPS_DIR:'):]
				elif os.path.isabs(map_name):
					self._map_path = map_name
				else:
					self._map_path = SavegameManager.get_filename_from_map_name(map_name)

		if is_random_map:
			handle, self._temp_path2 = tempfile.mkstemp()
			os.close(handle)
			random_map_db = DbReader(self._temp_path2)
			with open('content/map-template.sql') as map_template:
				random_map_db.execute_script(map_template.read())
			for island_id, island_string in enumerate(random_island_sequence):
				create_random_island(random_map_db, island_id, island_string)
			random_map_db.close()
			self._map_path = self._temp_path2

			self('INSERT INTO metadata VALUES(?, ?)', 'random_island_sequence',
				' '.join(random_island_sequence))

		if options is not None:
			if options.map_padding is not None:
				self("INSERT INTO map_properties VALUES(?, ?)", 'padding', options.map_padding)

		self('ATTACH ? AS map_file', self._map_path)
		if is_random_map:
			self.map_name = random_island_sequence
		elif os.path.isabs(self._map_path):
			self.map_name = self._map_path
		else:
			self.map_name = SavegameManager.get_savegamename_from_filename(self._map_path)

		map_padding = self("SELECT value FROM map_properties WHERE name = 'padding'")
		self.map_padding = int(map_padding[0][0]) if map_padding else MAP.PADDING

		self._load_building()
		self._load_settlement()
		self._load_concrete_object()
		self._load_production()
		self._load_storage()
		self._load_wildanimal()
		self._load_unit()
		self._load_building_collector()
		self._load_production_line()
		self._load_unit_path()
		self._load_storage_global_limit()
		self._load_health()
		self._load_fish_data()
		self._hash = None

	def close(self):
		super(SavegameAccessor, self).close()
		if self.upgrader is not None:
			self.upgrader.close()
		if self._temp_path is not None:
			os.unlink(self._temp_path)
		if hasattr(self, '_temp_path2'):
			os.unlink(self._temp_path2)

	def _load_building(self):
		self._building = {}
		for row in self("SELECT rowid, x, y, location, rotation, level FROM building"):
			self._building[int(row[0])] = row[1:]

	def get_building_row(self, worldid):
		"""Returns (x, y, location, rotation, level)"""
		return self._building[int(worldid)]

	def get_building_location(self, worldid):
		return self._building[int(worldid)][2]


	def _load_settlement(self):
		self._settlement = {}
		for row in self("SELECT rowid, owner, island FROM settlement"):
			self._settlement[int(row[0])] = row[1:]

	def get_settlement_owner(self, worldid):
		"""Returns the id of the owner of the settlement or None otherwise"""
		return self._settlement.get(int(worldid), [None])[0]

	def get_settlement_island(self, worldid):
		return self._settlement[int(worldid)][1]


	def _load_concrete_object(self):
		self._concrete_object = {}
		for row in self("SELECT id, action_runtime, action_set_id FROM concrete_object"):
			self._concrete_object[int(row[0])] = int(row[1]), row[2]

	def get_concrete_object_data(self, worldid):
		return self._concrete_object[int(worldid)]


	def _load_production(self):
		self._productions_by_worldid = {}
		self._production_lines_by_owner = {}
		self._productions_by_id_and_owner = {}
		db_data = self("SELECT rowid, state, owner, prod_line_id, remaining_ticks, _pause_old_state, creation_tick FROM production")
		for row in db_data:
			rowid = int(row[0])
			data = row[1:]
			self._productions_by_worldid[rowid] = data
			owner = int(row[2])
			line = int(row[3])
			if not line in self._productions_by_id_and_owner:
				self._productions_by_id_and_owner[line] = {}
			# in the line dict, the owners are unique
			self._productions_by_id_and_owner[line][owner] = data

			if owner not in self._production_lines_by_owner:
				self._production_lines_by_owner[owner] = [line]
			else:
				self._production_lines_by_owner[owner].append(line)

			self._production_lines_by_owner[owner].append

		self._production_state_history = defaultdict(lambda: deque())
		for object_id, production_id, tick, state in self("SELECT object_id, production, tick, state FROM production_state_history ORDER BY object_id, production, tick"):
			self._production_state_history[int(object_id), int(production_id)].append((tick, state))

	def get_production_by_id_and_owner(self, id, ownerid):
		# owner means worldid of entity
		return self._productions_by_id_and_owner[id][ownerid]

	def get_production_line_id(self, production_worldid):
		"""Returns the prod_line_id of the given production"""
		return self._productions_by_worldid[int(production_worldid)][2]

	def get_production_lines_by_owner(self, owner):
		"""Returns the prod_line_id of the given production"""
		return self._production_lines_by_owner.get(owner, [])

	def get_production_state_history(self, worldid, prod_id):
		return self._production_state_history[int(worldid), int(prod_id)]


	def _load_storage(self):
		self._storage = {}
		for row in self("SELECT object, resource, amount FROM storage"):
			ownerid = int(row[0])
			if ownerid in self._storage:
				self._storage[ownerid].append(row[1:])
			else:
				self._storage[ownerid] = [row[1:]]

	def get_storage_rowids_by_ownerid(self, ownerid):
		"""Returns potentially empty list of worldids referencing storages"""
		return self._storage.get(int(ownerid), [])


	def _load_wildanimal(self):
		self._wildanimal = {}
		for row in self("SELECT rowid, health, can_reproduce FROM wildanimal"):
			self._wildanimal[int(row[0])] = row[1:]

	def get_wildanimal_row(self, worldid):
		"""Returns (health, can_reproduce)"""
		return self._wildanimal[int(worldid)]


	def _load_unit(self):
		self._unit = {}
		for row in self("SELECT rowid, owner FROM unit"):
			self._unit[int(row[0])] = int(row[1])

	def get_unit_owner(self, worldid):
		return self._unit[int(worldid)]


	def _load_building_collector(self):
		self._building_collector = {}
		for row in self("SELECT rowid, home_building, creation_tick FROM building_collector"):
			self._building_collector[int(row[0])] = (int(row[1]) if row[1] is not None else None, row[2])

		self._building_collector_job_history = defaultdict(lambda: deque())
		for collector_id, tick, utilization in self("SELECT collector, tick, utilisation FROM building_collector_job_history ORDER BY collector, tick"):
			self._building_collector_job_history[int(collector_id)].append((tick, utilization))

	def get_building_collectors_data(self, worldid):
		"""Returns (id of the building collector's home or None otherwise, creation_tick)"""
		return self._building_collector.get(int(worldid))

	def get_building_collector_job_history(self, worldid):
		return self._building_collector_job_history[int(worldid)]


	def _load_production_line(self):
		self._production_line = {}
		for row in self("SELECT for_worldid, type, res, amount FROM production_line"):
			id = int(row[0])
			if id not in self._production_line:
				self._production_line[id] = []
			self._production_line[id].append(row[1:])

	def get_production_line_row(self, for_worldid):
		return self._production_line[int(for_worldid)]


	def _load_unit_path(self):
		self._unit_path = {}
		for row in self("SELECT unit, x, y FROM unit_path ORDER BY 'index'"):
			id = int(row[0])
			if id not in self._unit_path:
				self._unit_path[id] = []
			self._unit_path[id].append(row[1:])

	def get_unit_path(self, worldid):
		return self._unit_path.get(int(worldid))


	def _load_storage_global_limit(self):
		self._storage_global_limit = {}
		for row in self("SELECT object, value FROM storage_global_limit"):
			self._storage_global_limit[(int(row[0]))] = int(row[1])

	def get_storage_global_limit(self, worldid):
		return self._storage_global_limit[int(worldid)]


	def _load_health(self):
		self._health = dict( self("SELECT owner_id, health FROM unit_health") )

	def get_health(self, owner):
		return self._health[owner]


	def _load_fish_data(self):
		self._fish_data = {}
		for row in self("SELECT rowid, last_usage_tick FROM fish_data"):
			self._fish_data[int(row[0])] = int(row[1])

	def get_last_fish_usage_tick(self, worldid):
		return self._fish_data[worldid]

	# Random savegamefile related utility that i didn't know where to put

	@classmethod
	def get_players_num(cls, savegamefile):
		"""Return number of regular human and ai players"""
		return DbReader(savegamefile)("SELECT count(rowid) FROM player WHERE is_trader = 0 AND is_pirate = 0")[0][0]

	@classmethod
	def get_hash(cls, savegamefile):
		if not os.path.exists(savegamefile):
			return False
		fd = open(savegamefile, "rb")
		h = hashlib.sha1()
		h.update(fd.read())
		filehash = h.hexdigest()
		fd.close()
		return filehash
    def __init__(self, game_identifier, is_map, options=None):
        is_random_map = False
        if is_map:
            self.upgrader = None
            handle, self._temp_path = tempfile.mkstemp()
            os.close(handle)
            super().__init__(dbfile=self._temp_path)
            with open('content/savegame_template.sql') as savegame_template:
                self.execute_script(savegame_template.read())

            if isinstance(game_identifier, list):
                is_random_map = True
                random_island_sequence = game_identifier
            else:
                self._map_path = game_identifier
        else:
            self.upgrader = SavegameUpgrader(game_identifier)
            self._temp_path = None
            game_identifier = self.upgrader.get_path()
            super().__init__(dbfile=game_identifier)

            map_name_data = self('SELECT value FROM metadata WHERE name = ?',
                                 'map_name')
            if not map_name_data:
                is_random_map = True
                random_island_sequence = self(
                    'SELECT value FROM metadata WHERE name = ?',
                    'random_island_sequence')[0][0].split(' ')
            else:
                map_name = map_name_data[0][0]
                if map_name.startswith('USER_MAPS_DIR:'):
                    self._map_path = PATHS.USER_MAPS_DIR + map_name[
                        len('USER_MAPS_DIR:'):]
                elif os.path.isabs(map_name):
                    self._map_path = map_name
                else:
                    self._map_path = SavegameManager.get_filename_from_map_name(
                        map_name)

        if is_random_map:
            handle, self._temp_path2 = tempfile.mkstemp()
            os.close(handle)
            random_map_db = DbReader(self._temp_path2)
            with open('content/map-template.sql') as map_template:
                random_map_db.execute_script(map_template.read())
            for island_id, island_string in enumerate(random_island_sequence):
                create_random_island(random_map_db, island_id, island_string)
            random_map_db.close()
            self._map_path = self._temp_path2

            self('INSERT INTO metadata VALUES(?, ?)', 'random_island_sequence',
                 ' '.join(random_island_sequence))

        if options is not None:
            if options.map_padding is not None:
                self("INSERT INTO map_properties VALUES(?, ?)", 'padding',
                     options.map_padding)

        if not os.path.exists(self._map_path):
            raise MapFileNotFound("Map file " + str(self._map_path) +
                                  " not found!")

        self('ATTACH ? AS map_file', self._map_path)
        if is_random_map:
            self.map_name = random_island_sequence
        elif os.path.isabs(self._map_path):
            self.map_name = self._map_path
        else:
            self.map_name = SavegameManager.get_savegamename_from_filename(
                self._map_path)

        map_padding = self(
            "SELECT value FROM map_properties WHERE name = 'padding'")
        self.map_padding = int(
            map_padding[0][0]) if map_padding else MAP.PADDING

        self._load_building()
        self._load_settlement()
        self._load_concrete_object()
        self._load_production()
        self._load_storage()
        self._load_wildanimal()
        self._load_unit()
        self._load_building_collector()
        self._load_production_line()
        self._load_unit_path()
        self._load_storage_global_limit()
        self._load_health()
        self._load_fish_data()
        self._hash = None
class SavegameAccessor(DbReader):
    """
	SavegameAccessor is the class used for loading saved games.

	Frequent select queries are preloaded for faster access.
	"""
    def __init__(self, game_identifier, is_map, options=None):
        is_random_map = False
        if is_map:
            self.upgrader = None
            handle, self._temp_path = tempfile.mkstemp()
            os.close(handle)
            super().__init__(dbfile=self._temp_path)
            with open('content/savegame_template.sql') as savegame_template:
                self.execute_script(savegame_template.read())

            if isinstance(game_identifier, list):
                is_random_map = True
                random_island_sequence = game_identifier
            else:
                self._map_path = game_identifier
        else:
            self.upgrader = SavegameUpgrader(game_identifier)
            self._temp_path = None
            game_identifier = self.upgrader.get_path()
            super().__init__(dbfile=game_identifier)

            map_name_data = self('SELECT value FROM metadata WHERE name = ?',
                                 'map_name')
            if not map_name_data:
                is_random_map = True
                random_island_sequence = self(
                    'SELECT value FROM metadata WHERE name = ?',
                    'random_island_sequence')[0][0].split(' ')
            else:
                map_name = map_name_data[0][0]
                if map_name.startswith('USER_MAPS_DIR:'):
                    self._map_path = PATHS.USER_MAPS_DIR + map_name[
                        len('USER_MAPS_DIR:'):]
                elif os.path.isabs(map_name):
                    self._map_path = map_name
                else:
                    self._map_path = SavegameManager.get_filename_from_map_name(
                        map_name)

        if is_random_map:
            handle, self._temp_path2 = tempfile.mkstemp()
            os.close(handle)
            random_map_db = DbReader(self._temp_path2)
            with open('content/map-template.sql') as map_template:
                random_map_db.execute_script(map_template.read())
            for island_id, island_string in enumerate(random_island_sequence):
                create_random_island(random_map_db, island_id, island_string)
            random_map_db.close()
            self._map_path = self._temp_path2

            self('INSERT INTO metadata VALUES(?, ?)', 'random_island_sequence',
                 ' '.join(random_island_sequence))

        if options is not None:
            if options.map_padding is not None:
                self("INSERT INTO map_properties VALUES(?, ?)", 'padding',
                     options.map_padding)

        if not os.path.exists(self._map_path):
            raise MapFileNotFound("Map file " + str(self._map_path) +
                                  " not found!")

        self('ATTACH ? AS map_file', self._map_path)
        if is_random_map:
            self.map_name = random_island_sequence
        elif os.path.isabs(self._map_path):
            self.map_name = self._map_path
        else:
            self.map_name = SavegameManager.get_savegamename_from_filename(
                self._map_path)

        map_padding = self(
            "SELECT value FROM map_properties WHERE name = 'padding'")
        self.map_padding = int(
            map_padding[0][0]) if map_padding else MAP.PADDING

        self._load_building()
        self._load_settlement()
        self._load_concrete_object()
        self._load_production()
        self._load_storage()
        self._load_wildanimal()
        self._load_unit()
        self._load_building_collector()
        self._load_production_line()
        self._load_unit_path()
        self._load_storage_global_limit()
        self._load_health()
        self._load_fish_data()
        self._hash = None

    def close(self):
        super().close()
        if self.upgrader is not None:
            self.upgrader.close()
        if self._temp_path is not None:
            os.unlink(self._temp_path)
        if hasattr(self, '_temp_path2'):
            os.unlink(self._temp_path2)

    def _load_building(self):
        self._building = {}
        for row in self(
                "SELECT rowid, x, y, location, rotation, level FROM building"):
            self._building[int(row[0])] = row[1:]

    def get_building_row(self, worldid):
        """Returns (x, y, location, rotation, level)"""
        return self._building[int(worldid)]

    def get_building_location(self, worldid):
        return self._building[int(worldid)][2]

    def _load_settlement(self):
        self._settlement = {}
        for row in self("SELECT rowid, owner, island FROM settlement"):
            self._settlement[int(row[0])] = row[1:]

    def get_settlement_owner(self, worldid):
        """Returns the id of the owner of the settlement or None otherwise"""
        return self._settlement.get(int(worldid), [None])[0]

    def get_settlement_island(self, worldid):
        return self._settlement[int(worldid)][1]

    def _load_concrete_object(self):
        self._concrete_object = {}
        for row in self(
                "SELECT id, action_runtime, action_set_id FROM concrete_object"
        ):
            self._concrete_object[int(row[0])] = int(row[1]), row[2]

    def get_concrete_object_data(self, worldid):
        return self._concrete_object[int(worldid)]

    def _load_production(self):
        self._productions_by_worldid = {}
        self._production_lines_by_owner = {}
        self._productions_by_id_and_owner = {}
        db_data = self(
            "SELECT rowid, state, owner, prod_line_id, remaining_ticks, _pause_old_state, creation_tick FROM production"
        )
        for row in db_data:
            rowid = int(row[0])
            data = row[1:]
            self._productions_by_worldid[rowid] = data
            owner = int(row[2])
            line = int(row[3])
            if line not in self._productions_by_id_and_owner:
                self._productions_by_id_and_owner[line] = {}
            # in the line dict, the owners are unique
            self._productions_by_id_and_owner[line][owner] = data

            if owner not in self._production_lines_by_owner:
                self._production_lines_by_owner[owner] = [line]
            else:
                self._production_lines_by_owner[owner].append(line)

            self._production_lines_by_owner[owner].append

        self._production_state_history = defaultdict(deque)
        for object_id, production_id, tick, state in self(
                "SELECT object_id, production, tick, state FROM production_state_history ORDER BY object_id, production, tick"
        ):
            self._production_state_history[int(object_id),
                                           int(production_id)].append(
                                               (tick, state))

    def get_production_by_id_and_owner(self, id, ownerid):
        # owner means worldid of entity
        return self._productions_by_id_and_owner[id][ownerid]

    def get_production_line_id(self, production_worldid):
        """Returns the prod_line_id of the given production"""
        return self._productions_by_worldid[int(production_worldid)][2]

    def get_production_lines_by_owner(self, owner):
        """Returns the prod_line_id of the given production"""
        return self._production_lines_by_owner.get(owner, [])

    def get_production_state_history(self, worldid, prod_id):
        return self._production_state_history[int(worldid), int(prod_id)]

    def _load_storage(self):
        self._storage = {}
        for row in self("SELECT object, resource, amount FROM storage"):
            ownerid = int(row[0])
            if ownerid in self._storage:
                self._storage[ownerid].append(row[1:])
            else:
                self._storage[ownerid] = [row[1:]]

    def get_storage_rowids_by_ownerid(self, ownerid):
        """Returns potentially empty list of worldids referencing storages"""
        return self._storage.get(int(ownerid), [])

    def _load_wildanimal(self):
        self._wildanimal = {}
        for row in self("SELECT rowid, health, can_reproduce FROM wildanimal"):
            self._wildanimal[int(row[0])] = row[1:]

    def get_wildanimal_row(self, worldid):
        """Returns (health, can_reproduce)"""
        return self._wildanimal[int(worldid)]

    def _load_unit(self):
        self._unit = {}
        for row in self("SELECT rowid, owner FROM unit"):
            self._unit[int(row[0])] = int(row[1])

    def get_unit_owner(self, worldid):
        return self._unit[int(worldid)]

    def _load_building_collector(self):
        self._building_collector = {}
        for row in self(
                "SELECT rowid, home_building, creation_tick FROM building_collector"
        ):
            self._building_collector[int(
                row[0])] = (int(row[1]) if row[1] is not None else None,
                            row[2])

        self._building_collector_job_history = defaultdict(deque)
        for collector_id, tick, utilization in self(
                "SELECT collector, tick, utilisation FROM building_collector_job_history ORDER BY collector, tick"
        ):
            self._building_collector_job_history[int(collector_id)].append(
                (tick, utilization))

    def get_building_collectors_data(self, worldid):
        """Returns (id of the building collector's home or None otherwise, creation_tick)"""
        return self._building_collector.get(int(worldid))

    def get_building_collector_job_history(self, worldid):
        return self._building_collector_job_history[int(worldid)]

    def _load_production_line(self):
        self._production_line = {}
        for row in self(
                "SELECT for_worldid, type, res, amount FROM production_line"):
            id = int(row[0])
            if id not in self._production_line:
                self._production_line[id] = []
            self._production_line[id].append(row[1:])

    def get_production_line_row(self, for_worldid):
        return self._production_line[int(for_worldid)]

    def _load_unit_path(self):
        self._unit_path = {}
        for row in self("SELECT unit, x, y FROM unit_path ORDER BY 'index'"):
            id = int(row[0])
            if id not in self._unit_path:
                self._unit_path[id] = []
            self._unit_path[id].append(row[1:])

    def get_unit_path(self, worldid):
        return self._unit_path.get(int(worldid))

    def _load_storage_global_limit(self):
        self._storage_global_limit = {}
        for row in self("SELECT object, value FROM storage_global_limit"):
            self._storage_global_limit[(int(row[0]))] = int(row[1])

    def get_storage_global_limit(self, worldid):
        return self._storage_global_limit[int(worldid)]

    def _load_health(self):
        self._health = dict(self("SELECT owner_id, health FROM unit_health"))

    def get_health(self, owner):
        return self._health[owner]

    def _load_fish_data(self):
        self._fish_data = {}
        for row in self("SELECT rowid, last_usage_tick FROM fish_data"):
            self._fish_data[int(row[0])] = int(row[1])

    def get_last_fish_usage_tick(self, worldid):
        return self._fish_data[worldid]

    # Random savegamefile related utility that i didn't know where to put

    @classmethod
    def get_players_num(cls, savegamefile):
        """Return number of regular human and ai players"""
        return DbReader(
            savegamefile
        )("SELECT count(rowid) FROM player WHERE is_trader = 0 AND is_pirate = 0"
          )[0][0]

    @classmethod
    def get_hash(cls, savegamefile):
        if not os.path.exists(savegamefile):
            return False
        with open(savegamefile, "rb") as f:
            h = hashlib.sha1()
            h.update(f.read())
            filehash = h.hexdigest()
        return filehash
		def tmp_show_details():
			"""Fetches details of selected savegame and displays it"""
			gui.findChild(name="screenshot").image = None
			map_file = None
			map_file_index = gui.collectData(savegamelist)

			savegame_details_box = gui.findChild(name="savegame_details")
			savegame_details_parent = savegame_details_box.parent
			if map_file_index == -1:
				if savegame_details_box not in savegame_details_parent.hidden_children:
					savegame_details_parent.hideChild(savegame_details_box)
				return
			else:
				savegame_details_parent.showChild(savegame_details_box)
			try:
				map_file = map_files[map_file_index]
			except IndexError:
				# this was a click in the savegame list, but not on an element
				# it happens when the savegame list is empty
				return
			savegame_info = SavegameManager.get_metadata(map_file)

			if savegame_info.get('screenshot'):
				# try to find a writable location, that is accessible via relative paths
				# (required by fife)
				fd, filename = tempfile.mkstemp()
				try:
					path_rel = os.path.relpath(filename)
				except ValueError: # the relative path sometimes doesn't exist on win
					os.close(fd)
					os.unlink(filename)
					# try again in the current dir, it's often writable
					fd, filename = tempfile.mkstemp(dir=os.curdir)
					try:
						path_rel = os.path.relpath(filename)
					except ValueError:
						fd, filename = None, None

				if fd:
					with os.fdopen(fd, "w") as f:
						f.write(savegame_info['screenshot'])
					# fife only supports relative paths
					gui.findChild(name="screenshot").image = path_rel
					os.unlink(filename)

			# savegamedetails
			details_label = gui.findChild(name="savegamedetails_lbl")
			details_label.text = u""
			if savegame_info['timestamp'] == -1:
				details_label.text += _("Unknown savedate")
			else:
				savetime = time.strftime("%c", time.localtime(savegame_info['timestamp']))
				#xgettext:python-format
				details_label.text += _("Saved at {time}").format(time=savetime.decode('utf-8'))
			details_label.text += u'\n'
			counter = savegame_info['savecounter']
			# N_ takes care of plural forms for different languages
			#xgettext:python-format
			details_label.text += N_("Saved {amount} time",
			                         "Saved {amount} times",
			                         counter).format(amount=counter)
			details_label.text += u'\n'

			from horizons.constants import VERSION
			try:
				#xgettext:python-format
				details_label.text += _("Savegame version {version}").format(
				                         version=savegame_info['savegamerev'])
				if savegame_info['savegamerev'] != VERSION.SAVEGAMEREVISION:
					if not SavegameUpgrader.can_upgrade(savegame_info['savegamerev']):
						details_label.text += u" " + _("(probably incompatible)")
			except KeyError:
				# this should only happen for very old savegames, so having this unfriendly
				# error is ok (savegame is quite certainly fully unusable).
				details_label.text += u" " + _("Incompatible version")

			gui.adaptLayout()
        def tmp_show_details():
            """Fetches details of selected savegame and displays it"""
            gui.findChild(name="screenshot").image = None
            map_file = None
            map_file_index = gui.collectData(savegamelist)

            savegame_details_box = gui.findChild(name="savegame_details")
            savegame_details_parent = savegame_details_box.parent
            if map_file_index == -1:
                if (Fife.getVersion() >= (0, 4, 0)):
                    savegame_details_parent.hideChild(savegame_details_box)
                else:
                    if savegame_details_box not in savegame_details_parent.hidden_children:
                        savegame_details_parent.hideChild(savegame_details_box)
                return
            else:
                savegame_details_parent.showChild(savegame_details_box)
            try:
                map_file = map_files[map_file_index]
            except IndexError:
                # this was a click in the savegame list, but not on an element
                # it happens when the savegame list is empty
                return
            savegame_info = SavegameManager.get_metadata(map_file)

            if savegame_info.get('screenshot'):
                # try to find a writable location, that is accessible via relative paths
                # (required by fife)
                fd, filename = tempfile.mkstemp()
                try:
                    path_rel = os.path.relpath(filename)
                except ValueError:  # the relative path sometimes doesn't exist on win
                    os.close(fd)
                    os.unlink(filename)
                    # try again in the current dir, it's often writable
                    fd, filename = tempfile.mkstemp(dir=os.curdir)
                    try:
                        path_rel = os.path.relpath(filename)
                    except ValueError:
                        fd, filename = None, None

                if fd:
                    with os.fdopen(fd, "w") as f:
                        f.write(savegame_info['screenshot'])
                    # fife only supports relative paths
                    gui.findChild(name="screenshot").image = path_rel
                    os.unlink(filename)

            # savegamedetails
            details_label = gui.findChild(name="savegamedetails_lbl")
            details_label.text = u""
            if savegame_info['timestamp'] == -1:
                details_label.text += T("Unknown savedate")
            else:
                savetime = time.strftime(
                    "%c", time.localtime(savegame_info['timestamp']))
                details_label.text += T("Saved at {time}").format(
                    time=savetime.decode('utf-8'))
            details_label.text += u'\n'
            counter = savegame_info['savecounter']
            # NT takes care of plural forms for different languages
            details_label.text += NT("Saved {amount} time",
                                     "Saved {amount} times",
                                     counter).format(amount=counter)
            details_label.text += u'\n'

            from horizons.constants import VERSION
            try:
                details_label.text += T("Savegame version {version}").format(
                    version=savegame_info['savegamerev'])
                if savegame_info['savegamerev'] != VERSION.SAVEGAMEREVISION:
                    if not SavegameUpgrader.can_upgrade(
                            savegame_info['savegamerev']):
                        details_label.text += u" " + T(
                            "(probably incompatible)")
            except KeyError:
                # this should only happen for very old savegames, so having this unfriendly
                # error is ok (savegame is quite certainly fully unusable).
                details_label.text += u" " + T("Incompatible version")

            gui.adaptLayout()
class SavegameAccessor(DbReader):
	"""
	SavegameAccessor is the class used for loading saved games.

	Frequent select queries are preloaded for faster access.
	"""

	def __init__(self, dbfile):
		self.upgrader = SavegameUpgrader(dbfile)
		dbfile = self.upgrader.get_path()
		super(SavegameAccessor, self).__init__(dbfile=dbfile)
		self._load_building()
		self._load_settlement()
		self._load_concrete_object()
		self._load_production()
		self._load_storage()
		self._load_wildanimal()
		self._load_unit()
		self._load_building_collector()
		self._load_production_line()
		self._load_unit_path()
		self._load_storage_global_limit()
		self._load_health()
		self._hash = None

	def close(self):
		super(SavegameAccessor, self).close()
		self.upgrader.close()


	def _load_building(self):
		self._building = {}
		for row in self("SELECT rowid, x, y, location, rotation, level FROM building"):
			self._building[int(row[0])] = row[1:]

	def get_building_row(self, worldid):
		"""Returns (x, y, location, rotation, level)"""
		return self._building[int(worldid)]

	def get_building_location(self, worldid):
		return self._building[int(worldid)][2]


	def _load_settlement(self):
		self._settlement = {}
		for row in self("SELECT rowid, owner, island FROM settlement"):
			self._settlement[int(row[0])] = row[1:]

	def get_settlement_owner(self, worldid):
		"""Returns the id of the owner of the settlement or None otherwise"""
		return self._settlement.get(int(worldid), [None])[0]

	def get_settlement_island(self, worldid):
		return self._settlement[int(worldid)][1]


	def _load_concrete_object(self):
		self._concrete_object = {}
		for row in self("SELECT id, action_runtime, action_set_id FROM concrete_object"):
			self._concrete_object[int(row[0])] = int(row[1]), row[2]

	def get_concrete_object_data(self, worldid):
		return self._concrete_object[int(worldid)]


	def _load_production(self):
		self._productions_by_worldid = {}
		self._production_lines_by_owner = {}
		self._productions_by_id_and_owner = {}
		db_data = self("SELECT rowid, state, owner, prod_line_id, remaining_ticks, _pause_old_state, creation_tick FROM production")
		for row in db_data:
			rowid = int(row[0])
			data = row[1:]
			self._productions_by_worldid[rowid] = data
			owner = int(row[2])
			line = int(row[3])
			if not line in self._productions_by_id_and_owner:
				self._productions_by_id_and_owner[line] = {}
			# in the line dict, the owners are unique
			self._productions_by_id_and_owner[line][owner] = data

			if owner not in self._production_lines_by_owner:
				self._production_lines_by_owner[owner] = [line]
			else:
				self._production_lines_by_owner[owner].append(line)

			self._production_lines_by_owner[owner].append

		self._production_state_history = defaultdict(lambda: deque())
		for object_id, production_id, tick, state in self("SELECT object_id, production, tick, state FROM production_state_history ORDER BY object_id, production, tick"):
			self._production_state_history[int(object_id), int(production_id)].append((tick, state))

	def get_production_by_id_and_owner(self, id, ownerid):
		# owner means worldid of entity
		return self._productions_by_id_and_owner[id][ownerid]

	def get_production_line_id(self, production_worldid):
		"""Returns the prod_line_id of the given production"""
		return self._productions_by_worldid[int(production_worldid)][2]

	def get_production_lines_by_owner(self, owner):
		"""Returns the prod_line_id of the given production"""
		return self._production_lines_by_owner.get(owner, [])

	def get_production_state_history(self, worldid, prod_id):
		return self._production_state_history[int(worldid), int(prod_id)]


	def _load_storage(self):
		self._storage = {}
		for row in self("SELECT object, resource, amount FROM storage"):
			ownerid = int(row[0])
			if ownerid in self._storage:
				self._storage[ownerid].append(row[1:])
			else:
				self._storage[ownerid] = [row[1:]]

	def get_storage_rowids_by_ownerid(self, ownerid):
		"""Returns potentially empty list of worldids referencing storages"""
		return self._storage.get(int(ownerid), [])


	def _load_wildanimal(self):
		self._wildanimal = {}
		for row in self("SELECT rowid, health, can_reproduce FROM wildanimal"):
			self._wildanimal[int(row[0])] = row[1:]

	def get_wildanimal_row(self, worldid):
		"""Returns (health, can_reproduce)"""
		return self._wildanimal[int(worldid)]


	def _load_unit(self):
		self._unit = {}
		for row in self("SELECT rowid, owner FROM unit"):
			self._unit[int(row[0])] = int(row[1])

	def get_unit_owner(self, worldid):
		return self._unit[int(worldid)]


	def _load_building_collector(self):
		self._building_collector = {}
		for row in self("SELECT rowid, home_building, creation_tick FROM building_collector"):
			self._building_collector[int(row[0])] = (int(row[1]) if row[1] is not None else None, row[2])

		self._building_collector_job_history = defaultdict(lambda: deque())
		for collector_id, tick, utilisation in self("SELECT collector, tick, utilisation FROM building_collector_job_history ORDER BY collector, tick"):
			self._building_collector_job_history[int(collector_id)].append((tick, utilisation))

	def get_building_collectors_data(self, worldid):
		"""Returns (id of the building collector's home or None otherwise, creation_tick)"""
		return self._building_collector.get(int(worldid))

	def get_building_collector_job_history(self, worldid):
		return self._building_collector_job_history[int(worldid)]


	def _load_production_line(self):
		self._production_line = {}
		for row in self("SELECT for_worldid, type, res, amount FROM production_line"):
			id = int(row[0])
			if id not in self._production_line:
				self._production_line[id] = []
			self._production_line[id].append(row[1:])

	def get_production_line_row(self, for_worldid):
		return self._production_line[int(for_worldid)]


	def _load_unit_path(self):
		self._unit_path = {}
		for row in self("SELECT unit, x, y FROM unit_path ORDER BY 'index'"):
			id = int(row[0])
			if id not in self._unit_path:
				self._unit_path[id] = []
			self._unit_path[id].append(row[1:])

	def get_unit_path(self, worldid):
		return self._unit_path.get(int(worldid))


	def _load_storage_global_limit(self):
		self._storage_global_limit = {}
		for row in self("SELECT object, value FROM storage_global_limit"):
			self._storage_global_limit[(int(row[0]))] = int(row[1])

	def get_storage_global_limit(self, worldid):
		return self._storage_global_limit[int(worldid)]


	def _load_health(self):
		self._health = dict( self("SELECT owner_id, health FROM unit_health") )

	def get_health(self, owner):
		return self._health[owner]

	# Random savegamefile related utility that i didn't know where to put

	@classmethod
	def get_players_num(cls, savegamefile):
		"""Return number of regular human and ai players"""
		return DbReader(savegamefile)("SELECT count(rowid) FROM player WHERE is_trader = 0 AND is_pirate = 0")[0][0]

	@classmethod
	def get_hash(cls, savegamefile):
		if not os.path.exists(savegamefile):
			return False
		fd = open(savegamefile, "rb")
		h = hashlib.sha1()
		h.update(fd.read())
		filehash = h.hexdigest()
		fd.close()
		return filehash
class SavegameAccessor(DbReader):
	"""
	SavegameAccessor is the class used for loading saved games.

	Frequent select queries are preloaded for faster access.
	"""

	def __init__(self, dbfile):
		self.upgrader = SavegameUpgrader(dbfile)
		super(SavegameAccessor, self).__init__(dbfile=self.upgrader.get_path())
		self._load_building()
		self._load_settlement()
		self._load_concrete_object()
		self._load_production()
		self._load_storage()
		self._load_storage_slot_limit()
		self._load_wildanimal()
		self._load_unit()
		self._load_building_collector()
		self._load_production_line()
		self._load_unit_path()
		self._load_component()
		self._load_storage_global_limit()

	def close(self):
		super(SavegameAccessor, self).close()
		self.upgrader.close()


	def _load_building(self):
		self._building = {}
		for row in self("SELECT rowid, x, y, location, rotation, level FROM building"):
			self._building[int(row[0])] = row[1:]

	def get_building_row(self, worldid):
		"""Returns (x, y, location, rotation, level)"""
		return self._building[int(worldid)]

	def get_building_location(self, worldid):
		return self._building[int(worldid)][2]


	def _load_settlement(self):
		self._settlement = {}
		for row in self("SELECT rowid, owner, island FROM settlement"):
			self._settlement[int(row[0])] = row[1:]

	def get_settlement_owner(self, worldid):
		"""Returns the id of the owner of the settlement or None otherwise"""
		worldid = int(worldid)
		return None if worldid not in self._settlement else self._settlement[worldid][0]

	def get_settlement_island(self, worldid):
		return self._settlement[int(worldid)][1]


	def _load_concrete_object(self):
		self._concrete_object = {}
		for row in self("SELECT id, action_runtime FROM concrete_object"):
			self._concrete_object[int(row[0])] = int(row[1])

	def get_concrete_object_action_runtime(self, worldid):
		return self._concrete_object[int(worldid)]


	def _load_production(self):
		self._production = {}
		self._productions_by_id_and_owner = {}
		db_data = self("SELECT rowid, state, owner, prod_line_id, remaining_ticks, _pause_old_state, creation_tick FROM production")
		for row in db_data:
			rowid = int(row[0])
			data = row[1:]
			self._production[rowid] = data
			owner = int(row[2])
			line = int(row[3])
			if not line in self._productions_by_id_and_owner:
				self._productions_by_id_and_owner[line] = {}
			# in the line dict, the owners are unique
			self._productions_by_id_and_owner[line][owner] = data

		self._production_state_history = defaultdict(lambda: deque())
		for production_id, tick, state in self("SELECT production, tick, state FROM production_state_history ORDER BY production, tick"):
			self._production_state_history[int(production_id)].append((tick, state))

	def get_production_by_id_and_owner(self, id, ownerid):
		# owner means worldid of entity
		return self._productions_by_id_and_owner[id][ownerid]

	def get_production_line_id(self, production_worldid):
		"""Returns the prod_line_id of the given production"""
		return self._production[int(production_worldid)][2]

	def get_production_state_history(self, worldid):
		return self._production_state_history[int(worldid)]


	def _load_storage(self):
		self._storage = {}
		for row in self("SELECT object, resource, amount FROM storage"):
			ownerid = int(row[0])
			if ownerid in self._storage:
				self._storage[ownerid].append(row[1:])
			else:
				self._storage[ownerid] = [row[1:]]

	def get_storage_rowids_by_ownerid(self, ownerid):
		"""Returns potentially empty list of worldids referencing storages"""
		ownerid = int(ownerid)
		return [] if ownerid not in self._storage else self._storage[ownerid]


	def _load_storage_slot_limit(self):
		self._storage_slot_limit = {}
		for row in self("SELECT object, slot, value FROM storage_slot_limit"):
			key = (int(row[0]), int(row[1]))
			self._storage_slot_limit[key] = int(row[2])

	def get_storage_slot_limit(self, ownerid, slot):
		return self._storage_slot_limit[(int(ownerid), int(slot))]


	def _load_wildanimal(self):
		self._wildanimal = {}
		for row in self("SELECT rowid, health, can_reproduce FROM wildanimal"):
			self._wildanimal[int(row[0])] = row[1:]

	def get_wildanimal_row(self, worldid):
		"""Returns (health, can_reproduce)"""
		return self._wildanimal[int(worldid)]


	def _load_unit(self):
		self._unit = {}
		for row in self("SELECT rowid, owner FROM unit"):
			self._unit[int(row[0])] = int(row[1])

	def get_unit_owner(self, worldid):
		return self._unit[int(worldid)]


	def _load_building_collector(self):
		self._building_collector = {}
		for row in self("SELECT rowid, home_building, creation_tick FROM building_collector"):
			self._building_collector[int(row[0])] = (int(row[1]) if row[1] is not None else None, row[2])

		self._building_collector_job_history = defaultdict(lambda: deque())
		for collector_id, tick, utilisation in self("SELECT collector, tick, utilisation FROM building_collector_job_history ORDER BY collector, tick"):
			self._building_collector_job_history[int(collector_id)].append((tick, utilisation))

	def get_building_collectors_data(self, worldid):
		"""Returns (id of the building collector's home or None otherwise, creation_tick)"""
		worldid = int(worldid)
		return None if worldid not in self._building_collector else self._building_collector[worldid]

	def get_building_collector_job_history(self, worldid):
		return self._building_collector_job_history[int(worldid)]


	def _load_production_line(self):
		self._production_line = {}
		for row in self("SELECT for_worldid, type, res, amount FROM production_line"):
			id = int(row[0])
			if id not in self._production_line:
				self._production_line[id] = []
			self._production_line[id].append(row[1:])

	def get_production_line_row(self, for_worldid):
		return self._production_line[int(for_worldid)]


	def _load_unit_path(self):
		self._unit_path = {}
		for row in self("SELECT unit, x, y FROM unit_path ORDER BY 'index'"):
			id = int(row[0])
			if id not in self._unit_path:
				self._unit_path[id] = []
			self._unit_path[id].append(row[1:])

	def get_unit_path(self, worldid):
		worldid = int(worldid)
		return self._unit_path[worldid] if worldid in self._unit_path else None


	def _load_component(self):
		self._component = {}
		for row in self("SELECT worldid, name, module, class FROM component"):
			id = int(row[0])
			if id not in self._component:
				self._component[id] = []
			self._component[id].append(row[1:])

	def get_component_row(self, worldid):
		worldid = int(worldid)
		return self._component[worldid] if worldid in self._component else []


	def _load_storage_global_limit(self):
		self._storage_global_limit = {}
		for row in self("SELECT object, value FROM storage_global_limit"):
			self._storage_global_limit[(int(row[0]))] = int(row[1])

	def get_storage_global_limit(self, worldid):
		return self._storage_global_limit[int(worldid)]
    def __init__(self, game_identifier, is_map):
        is_random_map = False
        if is_map:
            self.upgrader = None
            handle, self._temp_path = tempfile.mkstemp()
            os.close(handle)
            super(SavegameAccessor, self).__init__(dbfile=self._temp_path)
            with open("content/savegame_template.sql") as savegame_template:
                self.execute_script(savegame_template.read())

            if isinstance(game_identifier, list):
                is_random_map = True
                random_island_sequence = game_identifier
            else:
                self._map_path = game_identifier
        else:
            self.upgrader = SavegameUpgrader(game_identifier)
            self._temp_path = None
            game_identifier = self.upgrader.get_path()
            super(SavegameAccessor, self).__init__(dbfile=game_identifier)

            map_name_data = self("SELECT value FROM metadata WHERE name = ?", "map_name")
            if not map_name_data:
                is_random_map = True
                random_island_sequence = self("SELECT value FROM metadata WHERE name = ?", "random_island_sequence")[0][
                    0
                ].split(" ")
            else:
                map_name = map_name_data[0][0]
                if os.path.isabs(map_name):
                    self._map_path = map_name
                else:
                    self._map_path = SavegameManager.get_filename_from_map_name(map_name)

        if is_random_map:
            handle, self._temp_path2 = tempfile.mkstemp()
            os.close(handle)
            random_map_db = DbReader(self._temp_path2)
            with open("content/map-template.sql") as map_template:
                random_map_db.execute_script(map_template.read())
            for island_id, island_string in enumerate(random_island_sequence):
                create_random_island(random_map_db, island_id, island_string)
            random_map_db.close()
            self._map_path = self._temp_path2

            self("INSERT INTO metadata VALUES(?, ?)", "random_island_sequence", " ".join(random_island_sequence))

        self("ATTACH ? AS map_file", self._map_path)
        if is_random_map:
            self.map_name = random_island_sequence
        elif os.path.isabs(self._map_path):
            self.map_name = self._map_path
        else:
            self.map_name = SavegameManager.get_savegamename_from_filename(self._map_path)

        self._load_building()
        self._load_settlement()
        self._load_concrete_object()
        self._load_production()
        self._load_storage()
        self._load_wildanimal()
        self._load_unit()
        self._load_building_collector()
        self._load_production_line()
        self._load_unit_path()
        self._load_storage_global_limit()
        self._load_health()
        self._load_fish_data()
        self._hash = None
    def __init__(self, game_identifier, is_map):
        is_random_map = False
        if is_map:
            self.upgrader = None
            handle, self._temp_path = tempfile.mkstemp()
            os.close(handle)
            super(SavegameAccessor, self).__init__(dbfile=self._temp_path)
            with open('content/savegame_template.sql') as savegame_template:
                self.execute_script(savegame_template.read())

            if isinstance(game_identifier, list):
                is_random_map = True
                random_island_sequence = game_identifier
            else:
                self._map_path = game_identifier
        else:
            self.upgrader = SavegameUpgrader(game_identifier)
            self._temp_path = None
            game_identifier = self.upgrader.get_path()
            super(SavegameAccessor, self).__init__(dbfile=game_identifier)

            map_name_data = self('SELECT value FROM metadata WHERE name = ?',
                                 'map_name')
            if not map_name_data:
                is_random_map = True
                random_island_sequence = self(
                    'SELECT value FROM metadata WHERE name = ?',
                    'random_island_sequence')[0][0].split(' ')
            else:
                map_name = map_name_data[0][0]
                if os.path.isabs(map_name):
                    self._map_path = map_name
                else:
                    self._map_path = SavegameManager.get_filename_from_map_name(
                        map_name)

        if is_random_map:
            handle, self._temp_path2 = tempfile.mkstemp()
            os.close(handle)
            random_map_db = DbReader(self._temp_path2)
            with open('content/map-template.sql') as map_template:
                random_map_db.execute_script(map_template.read())
            for island_id, island_string in enumerate(random_island_sequence):
                create_random_island(random_map_db, island_id, island_string)
            random_map_db.close()
            self._map_path = self._temp_path2

            self('INSERT INTO metadata VALUES(?, ?)', 'random_island_sequence',
                 ' '.join(random_island_sequence))

        self('ATTACH ? AS map_file', self._map_path)
        if is_random_map:
            self.map_name = random_island_sequence
        elif os.path.isabs(self._map_path):
            self.map_name = self._map_path
        else:
            self.map_name = SavegameManager.get_savegamename_from_filename(
                self._map_path)

        self._load_building()
        self._load_settlement()
        self._load_concrete_object()
        self._load_production()
        self._load_storage()
        self._load_wildanimal()
        self._load_unit()
        self._load_building_collector()
        self._load_production_line()
        self._load_unit_path()
        self._load_storage_global_limit()
        self._load_health()
        self._load_fish_data()
        self._hash = None