def Save(self) -> bool:
        """
		Saves the currently stored persistent data to the file path specified when initiating this object.
		If the directory the save file is in doesn't exist one will be created.

		:return: True if this completed without incident, False if not.
		:rtype: bool
		"""

        operationSuccess = True  # type: bool

        saveSuccessful, persistentDataContainerString = super().Save(
        )  # type: bool, str

        try:
            if not os.path.exists(os.path.dirname(self.FilePath)):
                os.makedirs(os.path.dirname(self.FilePath))

            with open(self.FilePath, mode="w+") as persistentFile:
                persistentFile.write(persistentDataContainerString)
        except Exception:
            Debug.Log("Failed to write to '" +
                      Paths.StripUserDataPath(self.FilePath) + "'.",
                      self.HostNamespace,
                      Debug.LogLevels.Error,
                      group=self.HostNamespace,
                      owner=__name__)
            operationSuccess = False

        if not saveSuccessful:
            return False

        return operationSuccess
    def Load(self, *args) -> bool:
        """
		Load persistent data from the file path specified when initiating this object, if it exists.

		:return: True if this completed without incident, False if not.
		:rtype: bool
		"""

        operationSuccess = True  # type: bool

        persistentDataContainerString = "{}"  # type: str

        if os.path.exists(self.FilePath):
            try:
                with open(self.FilePath) as persistentFile:
                    persistentDataContainerString = persistentFile.read()
            except Exception:
                Debug.Log("Failed to read from '" +
                          Paths.StripUserDataPath(self.FilePath) + "'.",
                          self.HostNamespace,
                          Debug.LogLevels.Error,
                          group=self.HostNamespace,
                          owner=__name__)
                operationSuccess = False

        loadSuccessful = super().Load(
            persistentDataContainerString)  # type: bool

        if not loadSuccessful:
            return False

        return operationSuccess
Exemple #3
0
def Commit (sourceDirectoryPath: str, commitSlotID: int) -> None:
	"""
	Copy the active directory in this slot to its actual save directory and backup old save directories. If the active directory doesn't exist nothing will happen.
	:param sourceDirectoryPath: The path of the mod save folder that will be copied to the slot.
	:type sourceDirectoryPath: str
	:param commitSlotID: The save slot id suppose to be committed. This must be greater than or equal to 0.
	:type commitSlotID: int
	"""

	global _loadedSlotID, _loadedDirectoryPath

	if not isinstance(sourceDirectoryPath, str):
		raise Exceptions.IncorrectTypeException(sourceDirectoryPath, "sourceDirectoryPath", (str,))

	if not isinstance(commitSlotID, int):
		raise Exceptions.IncorrectTypeException(commitSlotID, "commitSlotID", (int,))

	if commitSlotID < 0:
		raise Exception("commitSlotID values must be greater than or equal to 0.")

	Debug.Log("Committing the directory '%s' to the slot %s." % (Paths.StripUserDataPath(sourceDirectoryPath), commitSlotID), This.Mod.Namespace, Debug.LogLevels.Info, group = This.Mod.Namespace, owner = __name__)

	committingDirectoryPath = GetModSaveDirectoryPath(commitSlotID)  # type: str
	currentTimestamp = datetime.datetime.now().timestamp()  # type: float

	try:
		_ShiftBackupDirectories(commitSlotID)

		if os.path.exists(sourceDirectoryPath):
			shutil.copytree(sourceDirectoryPath, committingDirectoryPath)
			os.utime(committingDirectoryPath, (currentTimestamp, currentTimestamp))
		else:
			Debug.Log("The commit source directory at '%s' does not exist." % Paths.StripUserDataPath(sourceDirectoryPath), This.Mod.Namespace, Debug.LogLevels.Warning, group = This.Mod.Namespace, owner = __name__)
	except:
		Debug.Log("Failed to commit to save slot '" + str(commitSlotID) + "'.", This.Mod.Namespace, Debug.LogLevels.Exception, group = This.Mod.Namespace, owner = __name__)
		_ShowCommitFailureDialog()
		return

	_loadedSlotID = commitSlotID
	_loadedDirectoryPath = committingDirectoryPath

	Debug.Log("Finished committing to save slot %s." % commitSlotID, This.Mod.Namespace, Debug.LogLevels.Info, group = This.Mod.Namespace, owner = __name__)
Exemple #4
0
    def Save(self, saveFilePath: str) -> bool:
        """
		Write the loaded data to the active save file.

		This saving object must have save data loaded or this method will raise an exception.

		:param saveFilePath: The path to save the data to.
		:type saveFilePath: str
		:return: This method will return False if an error in saving any section occurred. Otherwise this method will return True if it behaved as expected.
		:rtype: bool
		"""

        if not isinstance(saveFilePath, str):
            raise Exceptions.IncorrectTypeException(saveFilePath,
                                                    "saveFilePath", (str, ))

        operationInformation = "Save Identifier: %s" % (self.Identifier, )
        operationStartTime = time.time()  # type: float

        Debug.Log(
            "Save operation starting in a saving object.\nTarget File: %s\n" %
            Paths.StripUserDataPath(saveFilePath) + operationInformation,
            self.Host.Namespace,
            Debug.LogLevels.Info,
            group=self.Host.Namespace,
            owner=__name__)

        if not self.Enabled:
            Debug.Log(
                "Triggered save operation in a disabled saving object.\n" +
                operationInformation,
                self.Host.Namespace,
                Debug.LogLevels.Warning,
                group=self.Host.Namespace,
                owner=__name__)

        try:
            saveSuccessful = self._SaveInternal(saveFilePath)
            self._currentFilePath = saveFilePath
        except:
            self._currentFilePath = saveFilePath
            operationTime = time.time() - operationStartTime  # type: float
            Debug.Log(
                "Save operation in a saving object aborted. (Operation took " +
                str(operationTime) + " seconds)\n" + operationInformation,
                self.Host.Namespace,
                Debug.LogLevels.Warning,
                group=self.Host.Namespace,
                owner=__name__)
            return False

        operationTime = time.time() - operationStartTime  # type: float

        if saveSuccessful:
            Debug.Log(
                "Save operation in a saving object finished without issue. (Operation took "
                + str(operationTime) + " seconds)\n" + operationInformation,
                self.Host.Namespace,
                Debug.LogLevels.Info,
                group=self.Host.Namespace,
                owner=__name__)
        else:
            Debug.Log(
                "Save operation in a saving object at least partially failed. (Operation took "
                + str(operationTime) + " seconds)\n" + operationInformation,
                self.Host.Namespace,
                Debug.LogLevels.Warning,
                group=self.Host.Namespace,
                owner=__name__)

        return saveSuccessful
Exemple #5
0
    def Load(self, saveFilePath: str) -> bool:
        """
		Load a save file. If any data is already loaded it will be unloaded first.

		:param saveFilePath: The path of the save file to be loaded. If this doesn't exist the method 'LoadDefault' will be used instead.
		:type saveFilePath: str
		:return: This method will return False if an error occurred. Otherwise this method will return True if it behaved as expected.
		:rtype: bool
		"""

        if not isinstance(saveFilePath, str):
            raise Exceptions.IncorrectTypeException(saveFilePath,
                                                    "saveFilePath", (str, ))

        operationInformation = "Save Identifier: %s" % (self.Identifier, )
        operationStartTime = time.time()  # type: float

        Debug.Log(
            "Load operation starting in a saving object.\nTarget File: %s\n" %
            Paths.StripUserDataPath(saveFilePath) + operationInformation,
            self.Host.Namespace,
            Debug.LogLevels.Info,
            group=self.Host.Namespace,
            owner=__name__)

        if not self.Enabled:
            Debug.Log(
                "Triggered load operation in a disabled saving object.\n" +
                operationInformation,
                self.Host.Namespace,
                Debug.LogLevels.Warning,
                group=self.Host.Namespace,
                owner=__name__)

        if self.Loaded:
            self.Unload()

        if not os.path.exists(saveFilePath):
            self.LoadDefault()
            loadSuccessful = True

            self._loadedFileExisted = False
            self._currentFilePath = saveFilePath
        else:
            try:
                loadSuccessful = self._LoadInternal(saveFilePath)

                self._loadedFileExisted = True
                self._currentFilePath = saveFilePath
            except Exception:
                operationTime = time.time() - operationStartTime  # type: float
                Debug.Log(
                    "Load operation in a saving object aborted, falling back to the default. (Operation took "
                    + str(operationTime) + " seconds)\n" +
                    operationInformation,
                    self.Host.Namespace,
                    Debug.LogLevels.Warning,
                    group=self.Host.Namespace,
                    owner=__name__)
                self.LoadDefault()

                self._loadedFileExisted = True
                self._currentFilePath = saveFilePath

                return False

        operationTime = time.time() - operationStartTime  # type: float

        if loadSuccessful:
            Debug.Log(
                "Load operation in a saving object finished without issue. (Operation took "
                + str(operationTime) + " seconds)\n" + operationInformation,
                self.Host.Namespace,
                Debug.LogLevels.Info,
                group=self.Host.Namespace,
                owner=__name__)
        else:
            Debug.Log(
                "Load operation in a saving object at least partially failed. (Operation took "
                + str(operationTime) + " seconds)\n" + operationInformation,
                self.Host.Namespace,
                Debug.LogLevels.Warning,
                group=self.Host.Namespace,
                owner=__name__)

        return loadSuccessful
Exemple #6
0
def Load (loadSlotID: int, loadingDirectoryPath: typing.Optional[str] = None, changingSave: bool = False) -> None:
	"""
	Load the specified slot in every registered and enabled saving object.
	:param loadSlotID: The save slot id of the game's loaded save file. This must be greater than or equal to 0.
	:type loadSlotID: int
	:param loadingDirectoryPath: This parameter allows you to load a specific directory. If this is not None, we will copy this directory into the slot's active path to load it.
	Anything already existing at the activated path will be lost unless the path is pointing to the activated path.
	activated instead.
	:type loadingDirectoryPath: str | None
	:param changingSave: Whether or not we are switching to another save.
	:type changingSave: bool
	"""

	global _loadedSlotID, _loadedDirectoryPath

	if not isinstance(loadSlotID, int):
		raise Exceptions.IncorrectTypeException(loadSlotID, "loadSlotID", (int,))

	if loadSlotID < 0:
		raise Exception("loadSlotID values must be greater than or equal to 0.")

	if not isinstance(loadingDirectoryPath, str) and loadingDirectoryPath is not None:
		raise Exceptions.IncorrectTypeException(loadingDirectoryPath, "loadingDirectoryPath", (str, None))

	if not isinstance(changingSave, bool):
		raise Exceptions.IncorrectTypeException(changingSave, "changingSave", (bool,))

	if loadingDirectoryPath is not None:
		Debug.Log("Loading the directory '" + Paths.StripUserDataPath(loadingDirectoryPath) + "' in save slot %s for %s saving object(s)." % (loadSlotID, len(_registeredSavingObjects)), This.Mod.Namespace, Debug.LogLevels.Info, group = This.Mod.Namespace, owner = __name__)
	else:
		Debug.Log("Loading save slot %s for %s saving object(s)." % (loadSlotID, len(_registeredSavingObjects)), This.Mod.Namespace, Debug.LogLevels.Info, group = This.Mod.Namespace, owner = __name__)

	loadingFailure = False  # type: bool

	failedSavingIdentifiers = list()  # type: typing.List[str]
	mismatchGUIDSavingIdentifiers = list()  # type: typing.List[str]
	mismatchGameTickSavingIdentifiers = list()  # type: typing.List[str]

	if _loadedSlotID is None or _loadedDirectoryPath is None:
		changingSave = True

	if loadingDirectoryPath is not None:
		changingSave = True

		try:
			ActivateDirectoryToSlot(loadingDirectoryPath, loadSlotID)
		except:
			Debug.Log("Failed to activate the directory at %s in save slot %s" % (Paths.StripUserDataPath(loadingDirectoryPath), loadSlotID), This.Mod.Namespace, Debug.LogLevels.Exception, group = This.Mod.Namespace, owner = __name__)
			loadingFailure = True
	else:
		loadingDirectoryPath = GetModSaveDirectoryPath(loadSlotID)  # type: str

		if _activeSlotID != loadSlotID:
			try:
				ActivateDirectoryToSlot(loadingDirectoryPath, loadSlotID)
			except:
				Debug.Log("Failed to activate save slot %s" % (loadSlotID,), This.Mod.Namespace, Debug.LogLevels.Exception, group = This.Mod.Namespace, owner = __name__)
				loadingFailure = True

	loadingActiveDirectoryPath = GetModSaveActiveDirectoryPath(loadSlotID)  # type: str

	modSaveMetaDataFileName = GetModSaveMetaDataFileName()  # type: str

	for savingObject in _registeredSavingObjects:  # type: Saving.SaveBase
		try:
			if not savingObject.Enabled:
				continue

			savingObjectFileName = savingObject.GetSaveFileName()  # type: str

			if savingObjectFileName == modSaveMetaDataFileName:
				Debug.Log("Had to skip a saving object with the identifier '" + savingObject.Identifier + "' because its file name was '" + modSaveMetaDataFileName + "' which conflicts with an important file.", This.Mod.Namespace, Debug.LogLevels.Error, group = This.Mod.Namespace, owner = __name__)
				continue

			loadingFilePath = os.path.abspath(os.path.join(loadingActiveDirectoryPath, savingObject.GetSaveFileName()))  # type: str

			modLoadSuccessful = savingObject.Load(loadingFilePath)  # type: bool
		except Exception:
			Debug.Log("Encountered an unhandled exception upon loading a saving object with the identifier '" + savingObject.Identifier + "'.", This.Mod.Namespace, Debug.LogLevels.Exception, group = This.Mod.Namespace, owner = __name__)
			modLoadSuccessful = False

		if not modLoadSuccessful:
			failedSavingIdentifiers.append(savingObject.Identifier)

		if modLoadSuccessful:
			savingObjectGUID = savingObject.DataGUID  # type: typing.Optional[int]

			if savingObjectGUID is not None:
				gameSaveGUID = services.get_persistence_service().get_save_slot_proto_guid()  # type: int

				if savingObjectGUID != gameSaveGUID:
					mismatchGUIDSavingIdentifiers.append(savingObject.Identifier)
					continue

			savingObjectGameTick = savingObject.DataGameTick  # type: typing.Optional[int]

			if savingObjectGameTick is not None:
				gameplaySaveSlotData = services.get_persistence_service().get_save_slot_proto_buff().gameplay_data

				if savingObjectGameTick != gameplaySaveSlotData.world_game_time:
					mismatchGameTickSavingIdentifiers.append(savingObject.Identifier)
					continue

	if changingSave:
		_loadedSlotID = loadSlotID
		_loadedDirectoryPath = loadingDirectoryPath

	if loadingFailure:
		_ShowLoadFailureDialog()

	if len(failedSavingIdentifiers) != 0:
		_ShowModLoadFailureDialog(failedSavingIdentifiers)

	if len(mismatchGUIDSavingIdentifiers) != 0:
		_ShowMismatchGUIDWarningDialog(mismatchGUIDSavingIdentifiers)

	if len(mismatchGameTickSavingIdentifiers) != 0:
		_ShowMismatchGameTickWarningDialog(mismatchGameTickSavingIdentifiers)

	Debug.Log("Finished loading %s saving object(s) with %s failing." % (len(_registeredSavingObjects), str(len(failedSavingIdentifiers))), This.Mod.Namespace, Debug.LogLevels.Info, group = This.Mod.Namespace, owner = __name__)
Exemple #7
0
 def PersistenceInformation(self) -> str:
     return "%s | File %s" % (self.__class__.__name__,
                              Paths.StripUserDataPath(self.FilePath))