示例#1
0
	def _UpdateCompatibility (self, informationDictionary: dict) -> bool:
		informationKey = "Compatibility"  # type: str

		compatibilityLowestVersionKey = "LowestVersion"  # type: str
		compatibilityHighestVersionKey = "HighestVersion"  # type: str

		try:
			compatibility = informationDictionary.get(informationKey, dict())  # type: typing.Dict[str, dict]

			if not isinstance(compatibility, dict):
				raise Exceptions.IncorrectTypeException(compatibility, "Root[%s]" % informationKey, (dict,))

			for namespace, modDictionary in compatibility.items():  # type: str, typing.Dict[str, str]
				if not isinstance(namespace, str):
					raise Exceptions.IncorrectTypeException(namespace, "Root[%s]<Key>" % informationKey, (str,))

				if namespace == self.Mod.Namespace:
					raise Exception("A mod cannot have compatibility information for its self.")

				if not isinstance(modDictionary, dict):
					raise Exceptions.IncorrectTypeException(modDictionary, "Root[%s][%s]" % (informationKey, namespace), (dict,))

				if not compatibilityLowestVersionKey in modDictionary:
					lowestVersion = None
				else:
					lowestVersion = modDictionary[compatibilityLowestVersionKey]

				if not isinstance(lowestVersion, str) and lowestVersion is not None:
					raise Exceptions.IncorrectTypeException(lowestVersion, "Root[%s][%s][%s]" % (informationKey, namespace, compatibilityLowestVersionKey), (str, "None"))

				if not compatibilityHighestVersionKey in modDictionary:
					highestVersion = None
				else:
					highestVersion = modDictionary[compatibilityHighestVersionKey]

				if not isinstance(highestVersion, str) and highestVersion is not None:
					raise Exceptions.IncorrectTypeException(highestVersion, "Root[%s][%s][%s]" % (informationKey, namespace, compatibilityHighestVersionKey), (str, "None"))

				lowestVersionObject = Version.Version(versionString = lowestVersion) if lowestVersion is not None else None  # type: typing.Optional[Version.Version]
				highestVersionObject = Version.Version(versionString = highestVersion) if highestVersion is not None else None  # type: typing.Optional[Version.Version]

				self.Mod.Compatibility.append(Mods.Compatibility(namespace, lowestVersionObject, highestVersionObject))

			return True
		except Exception:
			Debug.Log("Failed to read mod information file value '%s' for '%s'." % (informationKey, self.Mod.Namespace), This.Mod.Namespace, Debug.LogLevels.Exception, group = This.Mod.Namespace, owner = __name__)
			return False
示例#2
0
    def LoadedLastVersion(self) -> typing.Optional[Version.Version]:
        """
		The last version the loaded data was loaded in.
		:return:
		"""

        if self._loadedLastVersion is None:
            return None

        return Version.Version(str(self._loadedLastVersion))
示例#3
0
def _ReadVersionFile(
    versionsFileURL: str
) -> typing.Dict[str, typing.Dict[str, Version.Version]]:
    with request.urlopen(
            versionsFileURL) as versionsFile:  # type: client.HTTPResponse
        versionsDictionaryString = versionsFile.read().decode(
            "utf-8")  # type: str

    if not versionsDictionaryString or versionsDictionaryString.isspace():
        raise Exception("Latest versions file at '" + versionsFileURL +
                        "' is empty or whitespace.")

    try:
        versionDictionary = json.JSONDecoder().decode(
            versionsDictionaryString
        )  # type: typing.Dict[str, typing.Dict[str, typing.Any]]

        if not isinstance(versionDictionary, dict):
            raise Exceptions.IncorrectTypeException(versionDictionary, "Root",
                                                    (dict, ))

        for mod, modLatest in versionDictionary.items(
        ):  # type: str, typing.Dict[str, typing.Any]
            if not isinstance(mod, str):
                raise Exceptions.IncorrectTypeException(
                    mod, "Root<Key>", (str, ))

            if not isinstance(modLatest, dict):
                raise Exceptions.IncorrectTypeException(
                    mod, "Root[%s]" % mod, (dict, ))

            if "Release" in modLatest:
                modLatest["Release"] = Version.Version(modLatest["Release"])

            if "Preview" in modLatest:
                modLatest["Preview"] = Version.Version(modLatest["Preview"])
    except Exception as e:
        raise Exception("Failed to decode latest version file at '" +
                        versionsFileURL + "'.") from e

    return versionDictionary
示例#4
0
	def _UpdateBuildGameVersion (self, informationDictionary: dict) -> bool:
		informationKey = "BuildGameVersion"  # type: str

		try:
			buildGameVersion = informationDictionary.get(informationKey, None)

			if buildGameVersion is None:
				return True

			if not isinstance(buildGameVersion, str):
				raise Exceptions.IncorrectTypeException(buildGameVersion, "Root[%s]" % informationKey, (str,))

			self.Mod.BuildGameVersion = Version.Version(buildGameVersion, translate = True)
			return True
		except Exception:
			Debug.Log("Failed to read mod information file value '%s' for '%s'." % (informationKey, self.Mod.Namespace), This.Mod.Namespace, Debug.LogLevels.Exception, group = This.Mod.Namespace, owner = __name__)
			return False
示例#5
0
	def _UpdateVersion (self, informationDictionary: dict) -> bool:
		informationKey = "Version"  # type: str

		try:
			if not "Version" in informationDictionary:
				raise Exception("Missing dictionary entry '%s' in 'Root'." % informationKey)

			version = informationDictionary["Version"]  # type: str

			if not isinstance(version, str):
				raise Exceptions.IncorrectTypeException(version, "Root[%s]" % informationKey, (str,))

			self.Mod.Version = Version.Version(version)
			return True
		except Exception:
			Debug.Log("Failed to read mod information file value '%s' for '%s'." % (informationKey, self.Mod.Namespace), This.Mod.Namespace, Debug.LogLevels.Exception, group = This.Mod.Namespace, owner = __name__)
			return False
示例#6
0
	def _ResetInformation (self) -> None:
		self.Mod.Author = ""
		self.Mod.Version = Version.Version()
		self.Mod.VersionDisplay = "0.0.0"
		self.Mod.Distribution = Mods.Distribution(None, None, None, None)
		self.Mod.Rating = Mods.Rating.Normal

		self.Mod.ScriptPaths = list()
		self.Mod.Modules = list()

		self.Mod.RequiredMods = set()
		self.Mod.IncompatibleMods = set()
		self.Mod.LoadAfter = set()
		self.Mod.LoadBefore = set()
		self.Mod.Compatibility = list()

		self.Mod.BuildDate = None
		self.Mod.BuildGameVersion = None

		self.Mod.Additional = dict()
示例#7
0
    def __init__(self, namespace: str, name: str, loadController: str,
                 informationFilePath: str):
        """
		A container for mod information.

		:param namespace: The namespace of the mod, it should be the root of all the mod's modules.
		:type namespace: str
		:param name: The actual name of the mod.
		:type name: str
		:param loadController: The namespace of the mod that can load this mod.
		:type loadController: typing.Optional[str]
		:param informationFilePath: The file path of the mod information file.
		:type informationFilePath: str
		"""

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

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

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

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

        self.InformationFilePath = informationFilePath  # type: str
        self.InformationFileDirectoryPath = os.path.dirname(
            self.InformationFilePath)  # type: str

        self._namespace = namespace  # type: str

        self.Name = name  # type: str
        self.LoadController = loadController  # type: typing.Optional[str]

        self.Path = os.path.join(Paths.ModsPath, self.Namespace)  # type: str
        self.PersistentPath = os.path.join(Paths.PersistentPath,
                                           self.Namespace)  # type: str

        self.Author = ""  # type: str
        self.Version = Version.Version()  # type: Version.Version
        self.VersionDisplay = "0.0.0"  # type: str
        self.Distribution = Distribution(None, None, None,
                                         None)  # type: Distribution
        self.Rating = Rating.Normal  # type: Rating

        self.ScriptPaths = list()  # type: typing.List[str]
        self.Modules = list()  # type: typing.List[str]

        self.RequiredMods = set()  # type: typing.Set[str]
        self.IncompatibleMods = set()  # type: typing.Set[str]
        self.LoadAfter = set()  # type: typing.Set[str]
        self.LoadBefore = set()  # type: typing.Set[str]
        self.Compatibility = list()  # type: typing.List[Compatibility]

        self.BuildDate = None  # type: typing.Optional[datetime.datetime]
        self.BuildGameVersion = None  # type: typing.Optional[Version.Version]

        self.Additional = dict()  # type: dict

        self.Blocked = False  # type: bool
        self.Loading = False  # type: bool

        self.ReadInformation = False  # type: bool
        self.Imported = False  # type: bool
        self.Initiated = False  # type: bool
        self.Started = False  # type: bool

        self.LoadTime = None  # type: typing.Optional[float]
示例#8
0
    def Load(self, persistentDataContainer: dict) -> bool:
        """
		Load persistent data from a persistent data container.
		:param persistentDataContainer: The persistent data container dictionary.
		:type persistentDataContainer: dict
		:rtype: None
		"""

        operationSuccess = True  # type: bool

        persistenceInformation = self.PersistenceInformation  # type: str

        if not isinstance(persistentDataContainer, dict):
            raise Exceptions.IncorrectTypeException(persistentDataContainer,
                                                    "persistentDataContainer",
                                                    (dict, ))

        persistentData = persistentDataContainer.get(
            self._valuesKey, dict())  # type: typing.Dict[str, typing.Any]

        if not isinstance(persistentData, dict):
            Debug.Log("Invalid type in persistent data container.\n" +
                      Exceptions.GetIncorrectTypeExceptionText(
                          persistentData,
                          "PersistentDataContainer[%s]" % self._valuesKey,
                          (dict, )) + "\n" + persistenceInformation,
                      self.HostNamespace,
                      Debug.LogLevels.Warning,
                      group=self.HostNamespace,
                      owner=__name__)
            persistentData = dict()
            operationSuccess = False

        lastVersionString = persistentDataContainer.get(
            self._lastVersionKey)  # type:

        if lastVersionString is None:
            lastVersion = None
        else:
            if not isinstance(lastVersionString, str):
                Debug.Log(
                    "Invalid type in persistent data container.\n" +
                    Exceptions.GetIncorrectTypeExceptionText(
                        lastVersionString,
                        "PersistentDataContainer[%s]" % self._lastVersionKey,
                        (dict, )) + "\n" + persistenceInformation,
                    self.HostNamespace,
                    Debug.LogLevels.Warning,
                    group=self.HostNamespace,
                    owner=__name__)
                lastVersion = None
                operationSuccess = False
            else:
                try:
                    lastVersion = Version.Version(lastVersionString)
                except Exception:
                    Debug.Log(
                        "Cannot convert persistent data's last version value '"
                        + lastVersionString +
                        "' to a version number object.\n" +
                        persistenceInformation,
                        self.HostNamespace,
                        Debug.LogLevels.Warning,
                        group=self.HostNamespace,
                        owner=__name__)
                    lastVersion = None
                    operationSuccess = False

        self.Reset(autoSave=False, autoUpdate=False)
        setDataSuccess = self._LoadSetData(
            persistentData, lastVersion=lastVersion)  # type: bool

        self._InvokeOnLoadEvent()

        if not setDataSuccess:
            return False

        return operationSuccess
示例#9
0
def _CheckUpdates() -> None:
    previewAvailableMods = list(
    )  # type: typing.List[typing.Tuple[Mods.Mod, Version.Version]]
    releaseAvailableMods = list(
    )  # type: typing.List[typing.Tuple[Mods.Mod, Version.Version]]

    distributeUpdates = Settings.CheckForUpdates.Get()  # type: bool
    distributePreviewUpdates = Settings.CheckForPreviewUpdates.Get(
    )  # type: bool

    if not distributeUpdates:
        return

    latestURL = _distributionURL + "/mods/latest.json"  # type: str

    try:
        latestDictionary = _ReadVersionFile(
            latestURL
        )  # type: typing.Dict[str, typing.Dict[str, Version.Version]]
    except Exception:
        Debug.Log("Failed to get mod versions.",
                  This.Mod.Namespace,
                  Debug.LogLevels.Warning,
                  group=This.Mod.Namespace,
                  owner=__name__)
        return

    for mod in Mods.GetAllMods():  # type: Mods.Mod
        if not mod.ReadInformation:
            continue

        if mod.Distribution.UpdatesController is None:
            continue

        if mod.Distribution.UpdatesController != Information.RootNamespace:
            continue

        modShownReleaseVersions = _shownReleaseVersions.get(mod)  # type: list

        if modShownReleaseVersions is None:
            modShownReleaseVersions = list()
            _shownReleaseVersions[mod] = modShownReleaseVersions

        modShownPreviewVersions = _shownPreviewVersions.get(mod)  # type: list

        if modShownPreviewVersions is None:
            modShownPreviewVersions = list()
            _shownPreviewVersions[mod] = modShownPreviewVersions

        try:
            modVersions = latestDictionary.get(mod.Namespace)  # type: Version

            if modVersions is None:
                Debug.Log("Missing version data for '" + mod.Namespace + "'.",
                          This.Mod.Namespace,
                          Debug.LogLevels.Warning,
                          group=This.Mod.Namespace,
                          owner=__name__)
                continue

            releaseVersion = modVersions.get(
                "Release")  # type: Version.Version

            if releaseVersion is None:
                Debug.Log("Missing release version for '" + mod.Namespace +
                          "'.",
                          This.Mod.Namespace,
                          Debug.LogLevels.Warning,
                          group=This.Mod.Namespace,
                          owner=__name__)
                releaseVersion = Version.Version()

            if distributePreviewUpdates:
                previewVersion = modVersions.get(
                    "Preview")  # type: Version.Version

                if previewVersion is None:
                    Debug.Log("Missing preview version for '" + mod.Namespace +
                              "'.",
                              This.Mod.Namespace,
                              Debug.LogLevels.Warning,
                              group=This.Mod.Namespace,
                              owner=__name__)
                    previewVersion = Version.Version()

                if previewVersion <= releaseVersion:
                    if not releaseVersion in modShownReleaseVersions:
                        if mod.Version < releaseVersion:
                            releaseAvailableMods.append((mod, releaseVersion))
                            continue
                else:
                    if not previewVersion in modShownPreviewVersions:
                        if mod.Version < previewVersion:
                            previewAvailableMods.append((mod, previewVersion))
                            continue
            else:
                if not releaseVersion in modShownReleaseVersions:
                    if mod.Version < releaseVersion:
                        releaseAvailableMods.append((mod, releaseVersion))
                        continue

        except Exception:
            Debug.Log("Failed to get update information for '" +
                      mod.Namespace + "'.",
                      This.Mod.Namespace,
                      Debug.LogLevels.Warning,
                      group=This.Mod.Namespace,
                      owner=__name__)

    for releaseTuple in releaseAvailableMods:  # type: typing.Tuple[Mods.Mod, Version.Version]
        try:
            _ShowReleaseUpdateNotification(releaseTuple[0], releaseTuple[1])
        except Exception:
            Debug.Log("Failed to show release update notification for '" +
                      releaseTuple[0].Namespace + "'.",
                      This.Mod.Namespace,
                      Debug.LogLevels.Warning,
                      group=This.Mod.Namespace,
                      owner=__name__)

    for previewTuple in previewAvailableMods:  # type: typing.Tuple[Mods.Mod, Version.Version]
        try:
            _ShowPreviewUpdateNotification(previewTuple[0], previewTuple[1])
        except Exception:
            Debug.Log("Failed to show release update notification for '" +
                      previewTuple[0].Namespace + "'.",
                      This.Mod.Namespace,
                      Debug.LogLevels.Warning,
                      group=This.Mod.Namespace,
                      owner=__name__)