Exemple #1
0
def _InvokeOnUpdateWrapperEvent (changedSettings: typing.Set[str]) -> UpdateEventArguments:
	updateEventArguments = UpdateEventArguments(changedSettings)  # type: UpdateEventArguments

	for updateCallback in _onUpdateWrapper:  # type: typing.Callable[[types.ModuleType, Events.EventArguments], None]
		try:
			updateCallback(sys.modules[__name__], updateEventArguments)
		except:
			Debug.Log("Failed to run the 'OnUpdateWrapper' callback '" + Types.GetFullName(updateCallback) + "'.", This.Mod.Namespace, Debug.LogLevels.Exception, group = This.Mod.Namespace, owner = __name__)

	return updateEventArguments
Exemple #2
0
def _InvokeOnLoadWrapperEvent () -> Events.EventArguments:
	eventArguments = Events.EventArguments()  # type: Events.EventArguments

	for updateCallback in _onUpdateWrapper:  # type: typing.Callable[[types.ModuleType, Events.EventArguments], None]
		try:
			updateCallback(sys.modules[__name__], eventArguments)
		except:
			Debug.Log("Failed to run the 'OnLoadWrapper' callback '" + Types.GetFullName(updateCallback) + "'.", This.Mod.Namespace, Debug.LogLevels.Exception, group = This.Mod.Namespace, owner = __name__)

	return eventArguments
Exemple #3
0
	def DoBuffSelectionTesting (self) -> CycleEvents.MenstrualEffectBuffSelectionTestingArguments:
		eventArguments = CycleEvents.MenstrualEffectBuffSelectionTestingArguments(self.AffectingSystem.CurrentSeed, self.AffectingSystem.SimInfo)  # type: CycleEvents.MenstrualEffectBuffSelectionTestingArguments

		for buffSelectionTestingCallback in self.BuffSelectionTestingEvent:
			try:
				buffSelectionTestingCallback(self, eventArguments)
			except:
				Debug.Log("Failed to call buff selection testing callback '" + Types.GetFullName(buffSelectionTestingCallback) + "'.\n" + self.AffectingSystem.DebugInformation,
						  This.Mod.Namespace, Debug.LogLevels.Exception, group = This.Mod.Namespace, owner = __name__, lockIdentifier = __name__ + ":" + str(Python.GetLineNumber()), lockReference = buffSelectionTestingCallback)

		return eventArguments
Exemple #4
0
    def run(self) -> None:
        while True:
            if not self.isAlive(
            ) or self._parentTimer is None or not self._parentTimer.isAlive():
                break

            if self.daemon != self._parentTimer.daemon:
                self.daemon = self._parentTimer.daemon

            currentlyQueued = len(self._queuedCallbacks)  # type: int

            if currentlyQueued == 0:
                time.sleep(0.05)
            else:
                callback = self._queuedCallbacks[0][0]  # type: typing.Callable
                callbackArguments = self._queuedCallbacks[0][1]  # type: tuple
                callbackKeywordArguments = self._queuedCallbacks[0][
                    2]  # type: dict

                try:
                    callback(*callbackArguments, **callbackKeywordArguments)
                except Exception:
                    Debug.Log("Failed to call a timer callback. Callback '" +
                              Types.GetFullName(callback) + "'",
                              This.Mod.Namespace,
                              level=Debug.LogLevels.Warning,
                              group=This.Mod.Namespace,
                              owner=__name__)

                self._queuedCallbacks.pop(0)

                if currentlyQueued >= 10:
                    if not self._reportedBacklog:
                        Debug.Log(
                            "A timer's callback thread has developed a backlog. This might mean callbacks are being added faster than they can be dealt with. Last Callback: '"
                            + Types.GetFullName(callback) + "'",
                            This.Mod.Namespace,
                            level=Debug.LogLevels.Warning,
                            group=This.Mod.Namespace,
                            owner=__name__)
                        self._reportedBacklog = True
Exemple #5
0
def _ScanForAllSnippets() -> None:
    if services.snippet_manager is None:
        raise Exception("Cannot look for snippets, the manager is None.")

    if len(_scanningSnippets) == 0:
        return

    operationStartTime = time.time()  # type: float

    snippetsByType = dict(
    )  # type: typing.Dict[str, typing.List[snippets.SnippetInstanceMetaclass]]

    for snippetID, snippet in services.snippet_manager().types.items(
    ):  # type: typing.Any, snippets.SnippetInstanceMetaclass
        if isinstance(snippet, snippets.SnippetInstanceMetaclass):
            snippetList = snippetsByType.get(
                snippet.snippet_type,
                None)  # type: typing.List[snippets.SnippetInstanceMetaclass]

            if snippetList is None:
                snippetList = list()
                snippetsByType[snippet.snippet_type] = snippetList

            snippetList.append(snippet)

    for snippetType, snippetCallbacks in _scanningSnippets.items(
    ):  # type: str, typing.List[typing.Callable]
        snippetList = snippetsByType.get(snippetType, None)

        if snippetList is None:
            snippetList = list()

        for snippetCallback in snippetCallbacks:  # type: typing.Callable
            try:
                snippetCallback(snippetList)
            except:
                Debug.Log("Failed to trigger snippet scan callback at '%s'." %
                          Types.GetFullName(snippetCallback),
                          This.Mod.Namespace,
                          Debug.LogLevels.Exception,
                          group=This.Mod.Namespace,
                          owner=__name__)

    operationTime = time.time() - operationStartTime
    Debug.Log(
        "Finished scanning for %s types of snippet in %s seconds with %s snippets existing."
        % (len(_scanningSnippets), operationTime,
           len(services.snippet_manager().types)),
        This.Mod.Namespace,
        Debug.LogLevels.Info,
        group=This.Mod.Namespace,
        owner=__name__)
Exemple #6
0
	def _TriggerAnnouncement (self, announcementMethodName: str, preemptive: bool, *announcementArgs, **announcementKwargs) -> None:
		for announcer in Director.GetAllAnnouncers():  # type: typing.Type[Director.Announcer]
			readReportLockIdentifier = None  # type: typing.Optional[str]
			readReportLockReference = None  # type: typing.Any

			if self.LimitErrors:
				readReportLockIdentifier = __name__ + ":" + str(Python.GetLineNumber())  # type: str
				readReportLockReference = announcer

			try:
				if not announcer.Enabled:
					continue

				if not announcer.Host.IsLoaded() and not announcer.Reliable:
					continue

				if preemptive != announcer.Preemptive:
					continue

				announcementMethod = getattr(announcer, announcementMethodName)  # type: typing.Callable
			except Exception:
				from NeonOcean.S4.Main import Debug
				Debug.Log("Failed to read the announcer at '" + Types.GetFullName(announcer) + "' when triggering the announcement '" + announcementMethodName + "'.",
						  announcer.Host.Namespace, Debug.LogLevels.Exception, group = announcer.Host.Namespace, owner = __name__, lockIdentifier = readReportLockIdentifier, lockReference = readReportLockReference)

				return
			else:
				if readReportLockIdentifier is not None:
					from NeonOcean.S4.Main import Debug
					Debug.Unlock(readReportLockIdentifier, readReportLockReference)

			callReportLockIdentifier = None  # type: typing.Optional[str]
			callReportLockReference = None  # type: typing.Any

			if self.LimitErrors:
				callReportLockIdentifier = __name__ + ":" + str(Python.GetLineNumber())  # type: str
				callReportLockReference = announcer

			try:
				if self.AnnouncementCallWrapper is None:
					announcementMethod(*announcementArgs, **announcementKwargs)
				else:
					self.AnnouncementCallWrapper(announcementMethod, *announcementArgs, **announcementKwargs)
			except Exception:
				from NeonOcean.S4.Main import Debug
				Debug.Log("Failed to trigger the announcement '" + announcementMethodName + "' for '" + Types.GetFullName(announcer) + "'.", announcer.Host.Namespace, Debug.LogLevels.Exception, group = announcer.Host.Namespace, owner = __name__, lockIdentifier = callReportLockIdentifier, lockReference = callReportLockReference)
				return
			else:
				if callReportLockIdentifier is not None:
					from NeonOcean.S4.Main import Debug
					Debug.Unlock(callReportLockIdentifier, callReportLockReference)
Exemple #7
0
    def run(self) -> None:
        if self._repeat:
            lastInterval = self.Interval  # type: float
            sleepStartTime = time.time()  # type: float
            targetTime = sleepStartTime + lastInterval  # type: float
            sleepTime = lastInterval  # type: float

            while self.isAlive():
                time.sleep(sleepTime)

                if self.isAlive():
                    self._CallCallback()

                    sleepEndTime = time.time()  # type: float

                    sleepTimeOversleep = sleepEndTime - targetTime  # type: float

                    if self.Interval != lastInterval:
                        sleepTimeOversleep = max(
                            min(sleepTimeOversleep, self.Interval),
                            -self.Interval)

                    sleepTime = self.Interval - sleepTimeOversleep  # type: float

                    if sleepTime < 0:
                        if not self._reportedMissedTick:
                            actualSleepTime = sleepEndTime - sleepStartTime  # type: float

                            Debug.Log(
                                "A timer slept over an interval. This will be the only warning though there may be more missed ticks. Interval: '"
                                + str(self.Interval) + "' Actual Interval: '" +
                                str(actualSleepTime) + "' Callback: '" +
                                Types.GetFullName(self.Callback) + "'",
                                This.Mod.Namespace,
                                level=Debug.LogLevels.Warning,
                                group=This.Mod.Namespace,
                                owner=__name__)
                            self._reportedMissedTick = True

                        sleepTime = 0

                    lastInterval = self.Interval
                    sleepStartTime = time.time()  # type: float
                    targetTime += lastInterval
        else:
            if self.isAlive():
                time.sleep(self.Interval)

                if self.isAlive():
                    self._CallCallback()
    def _InvokeOnLoadEvent(self) -> Events.EventArguments:
        eventArguments = Events.EventArguments()  # type: Events.EventArguments

        for loadCallback in self.OnLoad:  # type: typing.Callable[[PersistentBranched, Events.EventArguments], None]
            try:
                loadCallback(self, eventArguments)
            except:
                Debug.Log("Failed to run the 'OnLoad' callback '" +
                          Types.GetFullName(loadCallback) + "'.",
                          This.Mod.Namespace,
                          Debug.LogLevels.Exception,
                          group=This.Mod.Namespace,
                          owner=__name__)

        return eventArguments
Exemple #9
0
	def NotifyBuffRemoved (self, removedBuff: BuffsMenstrual.MenstrualBuffBase) -> None:
		"""
		Notify the effect that a new buff was just added.
		"""

		if not isinstance(removedBuff, BuffsMenstrual.MenstrualBuffBase):
			raise Exceptions.IncorrectTypeException(removedBuff, "removedBuff", (BuffsMenstrual.MenstrualBuffBase,))

		eventArguments = CycleEvents.MenstrualEffectBuffRemovedArguments(removedBuff)  # type: CycleEvents.MenstrualEffectBuffRemovedArguments

		for buffRemovedCallback in self.BuffRemovedEvent:
			try:
				buffRemovedCallback(self, eventArguments)
			except:
				Debug.Log("Failed to call buff removed callback '" + Types.GetFullName(buffRemovedCallback) + "'.\n" + self.AffectingSystem.DebugInformation,
						  This.Mod.Namespace, Debug.LogLevels.Exception, group = This.Mod.Namespace, owner = __name__, lockIdentifier = __name__ + ":" + str(Python.GetLineNumber()), lockReference = buffRemovedCallback)
Exemple #10
0
def InvokeUnregisteredReproductiveSystemEvent(
        reproductiveSystem: ReproductionShared.ReproductiveSystem) -> None:
    thisModule = sys.modules[__name__]
    registeredArguments = RegistrationChangedArguments(reproductiveSystem)

    for unregisteredEventCallback in UnregisteredReproductiveSystemEvent:
        try:
            unregisteredEventCallback(thisModule, registeredArguments)
        except:
            Debug.Log(
                "Failed to run unregistered reproductive system event callback "
                + Types.GetFullName(unregisteredEventCallback),
                This.Mod.Namespace,
                Debug.LogLevels.Exception,
                group=This.Mod.Namespace,
                owner=__name__)
Exemple #11
0
	def _TargetException (exception: BaseException) -> None:
		originalCallableFullName = Types.GetFullName(information.OriginalCallable)  # type: str
		if originalCallableFullName == Types.GetFullName(log.exception):
			Debug.Log("Failed to call target function '" + Types.GetFullName(information.TargetFunction) + "'. Original callable: '" + originalCallableFullName + "'.", This.Mod.Namespace, Debug.LogLevels.Exception, group = This.Mod.Namespace, owner = __name__, exception = exception, logToGame = False)
			information.OriginalCallable(This.Mod.Namespace, "Failed to call target function '" + Types.GetFullName(information.TargetFunction) + "'. Original callable: '" + originalCallableFullName + "'.", exc = exception)
		else:
			if originalCallableFullName == Types.GetFullName(log.Logger.exception):
				Debug.Log("Failed to call target function '" + Types.GetFullName(information.TargetFunction) + "'. Original callable: '" + originalCallableFullName + "'.", This.Mod.Namespace, Debug.LogLevels.Exception, group = This.Mod.Namespace, owner = __name__, exception = exception, logToGame = False)
				information.OriginalCallable(log.Logger(This.Mod.Namespace), "Failed to call target function '" + Types.GetFullName(information.TargetFunction) + "'. Original callable: '" + originalCallableFullName + "'.", exc = exception)
			else:
				Debug.Log("Failed to call target function '" + Types.GetFullName(information.TargetFunction) + "'. Original callable: '" + originalCallableFullName + "'.", This.Mod.Namespace, Debug.LogLevels.Exception, group = This.Mod.Namespace, owner = __name__, exception = exception)
Exemple #12
0
	def DoCycleAbortTesting (self) -> CycleEvents.CycleAbortTestingArguments:
		"""
		Test if the currently active cycle should abort.
		:return: Testing event arguments that carry information on whether or not the current cycle should abort.
		:rtype: EventsCycles.CycleAbortTestingArguments
		"""

		eventArguments = CycleEvents.CycleAbortTestingArguments()  # type: CycleEvents.CycleAbortTestingArguments

		for cycleAbortTestingCallback in self.CycleAbortTestingEvent:
			try:
				cycleAbortTestingCallback(self, eventArguments)
			except:
				Debug.Log("Failed to call cycle abort testing callback '" + Types.GetFullName(cycleAbortTestingCallback) + "'.\n" + self.TrackingSystem.DebugInformation,
						  This.Mod.Namespace, Debug.LogLevels.Exception, group = This.Mod.Namespace, owner = __name__, lockIdentifier = __name__ + ":" + str(Python.GetLineNumber()), lockReference = cycleAbortTestingCallback)

		return eventArguments
Exemple #13
0
	def _AddMissingEffects (self) -> None:
		activeTypeIdentifiers = set(effect.TypeIdentifier for effect in self.ActiveEffects)  # type: typing.Set[str]
		allTypeIdentifiers = EffectsTypes.GetAllEffectTypeIdentifiers()  # type: typing.Set[str]

		for typeIdentifier in allTypeIdentifiers:  # type: str
			if not typeIdentifier in activeTypeIdentifiers:
				addingEffectType = EffectsTypes.GetEffectType(typeIdentifier)

				try:
					addingEffect = addingEffectType(self.TrackingSystem)  # type: EffectsBase.EffectBase
				except:
					Debug.Log("Failed to create instance of the effect type '" + Types.GetFullName(addingEffectType) + "'.\n" + self.TrackingSystem.DebugInformation,
							  This.Mod.Namespace, Debug.LogLevels.Exception, group = This.Mod.Namespace, owner = __name__, lockIdentifier = __name__ + ":CreatingEffect", lockReference = addingEffectType)

					continue

				self._AddEffect(addingEffect)
Exemple #14
0
	def DoCycleReleaseOvumTesting (self, ovumRelease: CycleOvumRelease.OvumRelease) -> CycleEvents.CycleReleaseOvumTestingArguments:
		"""
		Test if the a cycle should release an ovum.
		:param ovumRelease: The object that has indicated to the cycle that an ovum should release.
		:type ovumRelease: CycleOvumRelease.OvumRelease
		:return: Testing event arguments that carry information on whether or not a cycle should release an ovum.
		:rtype: EventsCycles.CycleReleaseOvumTestingArguments
		"""

		eventArguments = CycleEvents.CycleReleaseOvumTestingArguments(ovumRelease)  # type: CycleEvents.CycleReleaseOvumTestingArguments

		for cycleReleaseOvumTestingCallback in self.CycleReleaseOvumTestingEvent:
			try:
				cycleReleaseOvumTestingCallback(self, eventArguments)
			except:
				Debug.Log("Failed to call cycle release ovum testing callback '" + Types.GetFullName(cycleReleaseOvumTestingCallback) + "'.\n" + self.TrackingSystem.DebugInformation,
						  This.Mod.Namespace, Debug.LogLevels.Exception, group = This.Mod.Namespace, owner = __name__, lockIdentifier = __name__ + ":" + str(Python.GetLineNumber()), lockReference = cycleReleaseOvumTestingCallback)

		return eventArguments
Exemple #15
0
    def _NotifyHandlerRemoved(
            self, removedHandler: HandlersBase.HandlerBase) -> None:
        eventArguments = CycleEvents.HandlerRemovedArguments(
            removedHandler)  # type: CycleEvents.HandlerRemovedArguments

        for handlerRemovedCallback in self.HandlerRemovedEvent:
            try:
                handlerRemovedCallback(self, eventArguments)
            except:
                Debug.Log("Failed to call handler removed callback '" +
                          Types.GetFullName(handlerRemovedCallback) + "'.\n" +
                          self.TrackingSystem.DebugInformation,
                          This.Mod.Namespace,
                          Debug.LogLevels.Exception,
                          group=This.Mod.Namespace,
                          owner=__name__,
                          lockIdentifier=__name__ + ":" +
                          str(Python.GetLineNumber()),
                          lockReference=handlerRemovedCallback)
Exemple #16
0
def GetDoesNotInheritExceptionText (valueName: str, correctParents: typing.Tuple[typing.Union[type, str], ...], *additional) -> str:
	if not isinstance(valueName, str):
		raise IncorrectTypeException(valueName, "valueName", (str,))

	if not isinstance(correctParents, tuple):
		raise IncorrectTypeException(correctParents, "correctParents", (tuple,))

	if len(correctParents) == 0:
		raise Exception("This exception must receive at least one correct type")

	for correctParentIndex in range(len(correctParents)):  # type: int
		if isinstance(correctParents[correctParentIndex], type):
			continue

		if isinstance(correctParents[correctParentIndex], str):
			continue

		if correctParents[correctParentIndex] is None:
			continue

		raise IncorrectTypeException(correctParents[correctParentIndex], "correctParents[%d]" % correctParentIndex, (type, str, None))

	correctString = "'{}'" + (", '{}'" * (len(correctParents) - 2) if len(correctParents) > 2 else "") + (" or '{}'" if len(correctParents) > 1 else "")

	formatList = list()

	formatList.append(valueName)

	for correctParentIndex in range(0, len(correctParents)):
		if isinstance(correctParents[correctParentIndex], type) or correctParents[correctParentIndex] is None:
			formatList.append(Types.GetFullName(correctParents[correctParentIndex]))
		elif isinstance(correctParents[correctParentIndex], str):
			formatList.append(correctParents[correctParentIndex])
		else:
			formatList.append("")

	exceptionString = ("Expected '{}' to inherit " + correctString + "").format(*formatList)

	for additionalObject in additional:  # type: typing.Any
		exceptionString += "\n" + str(additionalObject)

	return exceptionString
Exemple #17
0
	def _CurrentCycleCompletedCallback (self, completionReason: CycleShared.CompletionReasons) -> None:
		eventArguments = CycleEvents.CycleCompletedArguments(completionReason)  # type: CycleEvents.CycleCompletedArguments

		for cycleCompletedCallback in self.CycleCompletedEvent:
			try:
				cycleCompletedCallback(self, eventArguments)
			except:
				Debug.Log("Failed to call cycle completed callback '" + Types.GetFullName(cycleCompletedCallback) + "'.\n" + self.TrackingSystem.DebugInformation,
						  This.Mod.Namespace, Debug.LogLevels.Exception, group = This.Mod.Namespace, owner = __name__, lockIdentifier = __name__ + ":" + str(Python.GetLineNumber()), lockReference = cycleCompletedCallback)

		self.CurrentCycle = None

		self.CompletedInitialCycle = True
		self.CompletedFirstCycle = True

		self.TimeSinceLastCycle = None
		self.LastCycleCompletionReason = completionReason

		if completionReason == CycleShared.CompletionReasons.Finished:
			self.TimeSinceLastCycle = 0  # TODO this should be set only if the sim experiences any symptoms instead.
Exemple #18
0
	def DoCycleStartTesting (self) -> CycleEvents.CycleStartTestingArguments:
		"""
		Test for when the next cycle is to start and of what type it will be.
		:return: Testing event arguments that carry information on whether or not a cycle should start.
		:rtype: EventsCycles.CycleStartTestingArguments
		"""

		if self.CycleStartTestingSeed is None:
			self.CycleStartTestingSeed = self.TrackingSystem.CurrentSeed

		eventArguments = CycleEvents.CycleStartTestingArguments(self.CycleStartTestingSeed, self.TimeSinceLastCycle)  # type: CycleEvents.CycleStartTestingArguments
		self.CycleStartTestingEvent.Invoke(self, eventArguments)

		for cycleStartTestingCallback in self.CycleStartTestingEvent:
			try:
				cycleStartTestingCallback(self, eventArguments)
			except:
				Debug.Log("Failed to call cycle start testing callback '" + Types.GetFullName(cycleStartTestingCallback) + "'.\n" + self.TrackingSystem.DebugInformation,
						  This.Mod.Namespace, Debug.LogLevels.Exception, group = This.Mod.Namespace, owner = __name__, lockIdentifier = __name__ + ":" + str(Python.GetLineNumber()), lockReference = cycleStartTestingCallback)

		return eventArguments
Exemple #19
0
def InvokeModLoadedEvent(mod: Mods.Mod) -> ModLoadedEventArguments:
    """
	Invokes the mod loaded event. Should be triggered every time a mod is loaded.

	:param mod: A reference the mod in question.
	:type mod: Mods.Mod
	:rtype: None
	"""

    eventArguments = ModLoadedEventArguments(
        mod)  # type: ModLoadedEventArguments

    for modLoadedCallback in ModLoadedEvent:
        try:
            modLoadedCallback(sys.modules[__name__], eventArguments)
        except:
            Debug.Log("Failed to invoke a mod loaded callback at '" +
                      Types.GetFullName(modLoadedCallback) + "'.",
                      This.Mod.Namespace,
                      Debug.LogLevels.Exception,
                      group=This.Mod.Namespace,
                      owner=__name__)

    return eventArguments
Exemple #20
0
    def _ActivateResetCallbacks(self) -> bool:
        operationInformation = "Save Identifier: %s | Section Identifier: %s" % (
            self.SavingObject.Identifier,
            self.Identifier,
        )
        operationSuccessful = True  # type: bool

        for resetCallback in self._resetCallbacks:  # type: typing.Callable[[Saving.SectionBase], bool]
            try:
                callbackSuccess = resetCallback(self)  # type: bool

                if not callbackSuccess:
                    operationSuccessful = False
            except:
                Debug.Log("Failed to activate reset callback at '" +
                          Types.GetFullName(resetCallback) + "'.\n" +
                          operationInformation,
                          self.SavingObject.Host.Namespace,
                          Debug.LogLevels.Exception,
                          group=self.SavingObject.Host.Namespace,
                          owner=__name__)
                operationSuccessful = False

        return operationSuccessful
    def Save(self) -> typing.Tuple[bool, str]:
        """
		Encodes the persistent data container to a json string. This method can handle cases in which any persistent data's key or value cannot be encoded.

		:return: The first value indicates if this method completed without incident. The second is the save data.
		:rtype: typing.Tuple[bool, dict]
		"""

        operationSuccess = True  # type: bool

        saveSuccess, persistentDataContainer = super().Save(
        )  # type: bool, dict

        persistentDataBranches = persistentDataContainer[
            self.
            _branchesKey]  # type: typing.Dict[str, typing.Dict[str, typing.Any]]
        persistentDataBranchesValuesString = ""  # type: str

        for branchKey, branchValue in persistentDataBranches.items(
        ):  # type: str, dict
            branchInformation = "Branch: " + branchKey
            persistentDataValuesString = ""

            for persistentKey, persistentValue in branchValue.items(
            ):  # type: str, typing.Any
                keyInformation = "Key: " + persistentKey  # type: str

                try:
                    assert isinstance(persistentKey, str)
                    persistentKeyString = json.JSONEncoder(indent="\t").encode(
                        persistentKey)  # type: str
                    assert "\n" not in persistentKeyString and "\r" not in persistentKeyString
                except Exception:
                    Debug.Log(
                        "Failed to encode a persistence key to a json string.\n"
                        + branchInformation + "\n" + keyInformation,
                        self.HostNamespace,
                        Debug.LogLevels.Exception,
                        group=self.HostNamespace,
                        owner=__name__)
                    operationSuccess = False
                    continue

                valueInformation = "Value Type: " + Types.GetFullName(
                    persistentKey
                ) + "\nValue Value: " + persistentKey  # type: str

                try:
                    persistentValueString = json.JSONEncoder(
                        indent="\t").encode(persistentValue)  # type: str
                except Exception:
                    Debug.Log(
                        "Failed to encode a persistence value to a json string.\n"
                        + branchInformation + "\n" + keyInformation + "\n" +
                        valueInformation,
                        self.HostNamespace,
                        Debug.LogLevels.Exception,
                        group=self.HostNamespace,
                        owner=__name__)
                    operationSuccess = False
                    continue

                persistentValueString = persistentValueString.replace(
                    "\n", "\n\t\t\t")

                if persistentDataValuesString != "":
                    persistentDataValuesString += ",\n"

                persistentDataValuesString += "\t\t\t" + persistentKeyString + ": " + persistentValueString

            if persistentDataBranchesValuesString != "":
                persistentDataBranchesValuesString += ",\n"

            persistentDataBranchesValuesString += "\t\t\"" + branchKey + "\": {"

            if persistentDataBranchesValuesString != "":
                persistentDataBranchesValuesString += "\n" + persistentDataValuesString + "\n\t\t}"
            else:
                persistentDataBranchesValuesString += "}"

        persistentDataBranchesString = "\t\"" + self._branchesKey + "\": {"  # type: str

        if persistentDataBranchesString != "":
            persistentDataBranchesString += "\n" + persistentDataBranchesValuesString + "\n\t}"
        else:
            persistentDataBranchesString += "}"

        lastVersion = persistentDataContainer[
            self._lastVersionKey]  # type: str

        try:
            lastVersionString = json.JSONEncoder(indent="\t").encode(
                lastVersion)  # type: str
        except Exception as e:
            raise Exception(
                "Failed to encode a persistence last version to a json string."
            ) from e

        lastVersionString = "\t\"" + self._lastVersionKey + "\": " + lastVersionString  # type: str

        persistentDataContainerString = "{\n" + persistentDataBranchesString + ",\n" + lastVersionString + "\n}"  # type: str

        if not saveSuccess:
            return False, persistentDataContainerString

        return operationSuccess, persistentDataContainerString
Exemple #22
0
def Patch (originalObject: typing.Any, originalCallableName: str, targetFunction: typing.Callable, patchType: PatchTypes = PatchTypes.After, permanent: bool = False) -> None:
	"""
	Combine a function with another function or method, the original callable located in the original object will then be replaced by the patch automatically.
	:param originalObject: The object the original callable resides in.
	:type originalObject: typing.Any
	:param originalCallableName: The name of the callable to be combined, Can be a reference to a function, built in function, or method.
	:type originalCallableName: str
	:param targetFunction: The function object that will be combined with the original. This can only be a function or a built in function.
	:type targetFunction: typing.Callable
	:param patchType: Controls when the original callable is called. A value of PatchTypes.Custom requires that the target function take an extra argument
					  in the first argument position. The extra argument will be a reference to the original callable.
	:type patchType: PatchTypes
	:param permanent: Whether or not the patch will be disabled if the module the patching function resides in is unloaded.
	:type permanent: bool
	"""

	if originalObject is None:
		raise TypeError("originalObject cannot be none.")

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

	originalCallable = getattr(originalObject, originalCallableName)  # type: typing.Callable

	if originalCallable is None:
		raise Exception("Cannot find attribute named '" + originalCallableName + "' in '" + Types.GetFullName(originalObject) + "'.")

	patchedFunction = PatchDirectly(originalCallable, targetFunction, patchType = patchType, permanent = permanent)
	setattr(originalObject, originalCallableName, patchedFunction)
Exemple #23
0
	def Compare (cls, leftVersion, rightVersion) -> int:
		"""
		Compare two version objects together.
		:return: Less than zero, if the left version is less than the right version. Zero, If the left and right version are equal. Greater than zero, If the
		left version is greater than the right version.
		:rtype: int
		"""

		if not isinstance(leftVersion, Version) or not isinstance(rightVersion, Version):
			raise TypeError("Version compare operations are not supported between instances of '%s' and '%s'" % (Types.GetFullName(leftVersion), Types.GetFullName(rightVersion)))

		if leftVersion.Major != rightVersion.Major:
			if leftVersion.Major < rightVersion.Major:
				return -1
			else:
				return 1

		if leftVersion.Minor != rightVersion.Minor:
			if leftVersion.Minor < rightVersion.Minor:
				return -1
			else:
				return 1

		leftPatch = leftVersion.Patch if leftVersion.Patch >= 0 else 0  # type: int
		rightPatch = rightVersion.Patch if rightVersion.Patch >= 0 else 0  # type: int
		if leftPatch != rightPatch:
			if leftPatch < rightPatch:
				return -1
			else:
				return 1

		if len(leftVersion.PreRelease) != 0 and len(rightVersion.PreRelease) == 0:
			return -1
		elif len(leftVersion.PreRelease) == 0 and len(rightVersion.PreRelease) != 0:
			return 1

		for preReleaseIndex in range(len(leftVersion.PreRelease)):  # type: int
			if len(rightVersion.PreRelease) - 1 < preReleaseIndex:
				break

			leftPreReleaseIdentifier = leftVersion.PreRelease[preReleaseIndex]  # type: typing.Union[str, int]
			rightPreReleaseIdentifier = rightVersion.PreRelease[preReleaseIndex]  # type: typing.Union[str, int]

			if leftPreReleaseIdentifier == rightPreReleaseIdentifier:
				continue

			if isinstance(leftPreReleaseIdentifier, int) and isinstance(rightPreReleaseIdentifier, str):
				return -1
			elif isinstance(leftPreReleaseIdentifier, str) and isinstance(rightPreReleaseIdentifier, int):
				return 1

			assert isinstance(leftPreReleaseIdentifier, int) and isinstance(rightPreReleaseIdentifier, int) or \
				   isinstance(leftPreReleaseIdentifier, str) and isinstance(rightPreReleaseIdentifier, str)

			if leftPreReleaseIdentifier < rightPreReleaseIdentifier:
				return -1
			else:
				return 1

		if len(leftVersion.PreRelease) < len(rightVersion.PreRelease):
			return -1
		elif len(leftVersion.PreRelease) > len(rightVersion.PreRelease):
			return 1

		return 0
Exemple #24
0
	def __str__ (self):
		if self.TargetFunction is not None:
			return "Failed to invoke the function at '" + Types.GetFullName(self.TargetFunction) + "' as it was already active in another thread."
		else:
			return "Failed to invoke a function as it was already active in another thread."
Exemple #25
0
def FindGuideGroup (simInfo: sim_info.SimInfo) -> typing.Optional[GuideGroup]:
	"""
	Return the first guide group found that is appropriate for the specified sim. This will return None if no appropriate one is found.
	"""

	if not isinstance(simInfo, sim_info.SimInfo):
		raise Exceptions.IncorrectTypeException(simInfo, "simInfo", (sim_info.SimInfo,))

	for guideGroup in _guideGroups:  # type: GuideGroup
		try:
			if guideGroup.Matches(simInfo):
				return guideGroup
		except Exception as e:
			Debug.Log("Encountered an unhandled exception when checking if a guide group matches a sim. Matcher: " + Types.GetFullName(guideGroup.Matcher), This.Mod.Namespace, Debug.LogLevels.Exception, group = This.Mod.Namespace, owner = __name__, exception = e)

	return None
Exemple #26
0
def _ResolveRegularTags (text: str, tokens: typing.Sequence, languageHandler: typing.Type[LanguageHandlers.LanguageHandlerBase]) -> typing.Optional[str]:
	# This doesn't completely replace the game's stbl formatting system.

	correctedText = ""  # type: str
	uncorrectedTextStartPosition = None  # type: typing.Optional[int]

	def doSpecialAdjustments (adjustingText: str, specialAdjustmentIdentifiers: typing.List[str]) -> str:
		adjustedText = adjustingText  # type: str

		for specialAdjustmentIdentifier in specialAdjustmentIdentifiers:  # type: str
			specialAdjustmentIdentifierLower = specialAdjustmentIdentifier.lower()  # type: str

			# noinspection SpellCheckingInspection
			if specialAdjustmentIdentifierLower == "xxupper":
				adjustedText = adjustedText.upper()
			elif specialAdjustmentIdentifierLower == "xxlower":  # I didn't actually test if this is actually possible in the base game.
				adjustedText = adjustedText.lower()

		for specialAdjustmentIdentifier in specialAdjustmentIdentifiers:  # type: str
			specialAdjustmentIdentifierLower = specialAdjustmentIdentifier.lower()  # type: str

			# noinspection SpellCheckingInspection
			if specialAdjustmentIdentifierLower == "enan":
				if adjustingText.startswith(("a", "e", "i", "o", "u")):
					adjustedText = "an " + adjustedText
				else:
					adjustedText = "a " + adjustedText
			elif specialAdjustmentIdentifierLower == "enhouseholdnameplural":
				adjustedText = adjustedText + " household"

		return adjustedText

	def addText (addingText: str) -> None:
		nonlocal correctedText

		if len(tagTextSpecialParts) != 0:
			addingText = doSpecialAdjustments(addingText, tagTextSpecialParts)

		correctedText += text[uncorrectedTextStartPosition: tagStartPosition] + addingText

	def addTokenText (addingLocalizationToken) -> None:
		nonlocal correctedText

		tokenTypeHandler = tokenTypeHandlers.get(addingLocalizationToken.type, None)

		if tokenTypeHandler is not None:
			tokenTypeHandler(addingLocalizationToken)

	def addSimTokenText (addingLocalizationToken) -> None:
		if tagText == "SimFirstName":
			addText(addingLocalizationToken.first_name)
		elif tagText == "SimLastName":
			addText(addingLocalizationToken.last_name)
		elif tagText == "SimName":
			simName = None  # type: typing.Optional[str]

			if addingLocalizationToken.full_name_key != 0:
				simName = GetLocalizationStringText(addingLocalizationToken.full_name_key)  # type: typing.Optional[str]

			if simName is None:
				simName = languageHandler.GetSimFullNameString(addingLocalizationToken.first_name, addingLocalizationToken.last_name)

			addText(simName)

	def addStringTokenText (addingLocalizationToken) -> None:
		if tagText == "String":
			resolvedStringToken = ResolveSTBLText(addingLocalizationToken.text_string, addingLocalizationToken.text_string.tokens)  # type: typing.Optional[str]

			if resolvedStringToken is not None:
				addText(resolvedStringToken)
		else:
			raise _UnsupportedLocalizationStringException("The tag '%s' is an unknown tag for a localization string token." % tagText)

	def addRawTextTokenText (addingLocalizationToken) -> None:
		if tagText == "String":
			addText(addingLocalizationToken.raw_text)
		else:
			raise _UnsupportedLocalizationStringException("The tag '%s' is an unknown tag for a raw text token." % tagText)

	def addNumberTokenText (addingLocalizationToken) -> None:
		if tagText == "Number":
			addText(str(addingLocalizationToken.number))
		elif tagText == "Money":
			addText(languageHandler.GetMoneyString(tagToken))
		else:
			raise _UnsupportedLocalizationStringException("The tag '%s' is an unknown tag for a number token." % tagText)

	def addObjectTokenText (addingLocalizationToken) -> None:
		if tagText == "ObjectName":
			if addingLocalizationToken.custom_name != "":
				addingText = addingLocalizationToken.custom_name
			else:
				addingText = GetLocalizationStringText(addingLocalizationToken.catalog_name_key)
		elif tagText == "ObjectDescription":
			if addingLocalizationToken.custom_description != "":
				addingText = addingLocalizationToken.custom_description
			else:
				addingText = GetLocalizationStringText(addingLocalizationToken.catalog_description_key)
		elif tagText == "ObjectCatalogName":
			addingText = GetLocalizationStringText(addingLocalizationToken.catalog_name_key)
		elif tagText == "ObjectCatalogDescription":
			addingText = GetLocalizationStringText(addingLocalizationToken.catalog_description_key)
		else:
			raise _UnsupportedLocalizationStringException("The tag '%s' is an unknown tag for an object token." % tagText)

		if addingText is not None:
			if len(tagTextSpecialParts) != 0:
				doSpecialAdjustments(addingText, tagTextSpecialParts)

			addText(addingText)

	# noinspection PyUnresolvedReferences
	tokenTypeHandlers = {
		Localization_pb2.LocalizedStringToken.SIM: addSimTokenText,
		Localization_pb2.LocalizedStringToken.STRING: addStringTokenText,
		Localization_pb2.LocalizedStringToken.RAW_TEXT: addRawTextTokenText,
		Localization_pb2.LocalizedStringToken.NUMBER: addNumberTokenText,
		Localization_pb2.LocalizedStringToken.OBJECT: addObjectTokenText
	}

	for regularTagMatch in re.finditer(SingleTagRegularPattern, text):
		tag, tagTokenIndexString, tagText = regularTagMatch.groups()  # type: str

		tagTextParts = tagText.split("|")  # type: typing.List[str]
		tagText = tagTextParts[0]  # type: str
		tagTextSpecialParts = tagTextParts[1:]  # type: typing.List[str]

		tagTokenIndex = int(tagTokenIndexString)  # type: int

		tagStartPosition = regularTagMatch.start()  # type: int
		tagEndPosition = regularTagMatch.end()  # type: int
		nextUnfixedTextStartPosition = tagEndPosition  # type: int

		try:
			tagToken = tokens[tagTokenIndex]
		except IndexError:
			pass
		else:
			if hasattr(tagToken, "populate_localization_token"):
				temporaryLocalizationToken = Localization_pb2.LocalizedStringToken()
				# noinspection PyUnresolvedReferences
				temporaryLocalizationToken.type = Localization_pb2.LocalizedStringToken.INVALID
				tagToken.populate_localization_token(temporaryLocalizationToken)

				# noinspection PyTypeChecker
				addTokenText(temporaryLocalizationToken)
			elif isinstance(tagToken, numbers.Number):
				if tagText == "Number":  # Tags like these are case sensitive in the base game so they are here as well.
					addText(str(tagToken))
				elif tagText == "Money":
					addText(languageHandler.GetMoneyString(tagToken))
				else:
					raise _UnsupportedLocalizationStringException("The tag '%s' is an unknown tag for a number token." % tagText)
			elif isinstance(tagToken, str):
				if tagText == "String":
					addText(tagToken)
				else:
					raise _UnsupportedLocalizationStringException("The tag '%s' is an unknown tag for a raw text token." % tagText)
			elif isinstance(tagToken, Localization_pb2.LocalizedString):
				if tagText == "String":
					# noinspection PyUnresolvedReferences
					tagTokenText = GetLocalizationStringText(tagToken.hash)  # type: typing.Optional[str]

					if tagTokenText is not None:
						# noinspection PyUnresolvedReferences
						correctedTagTokenText = ResolveSTBLText(tagTokenText, tuple(tagToken.tokens))  # Any gendered language tags would have already been resolved, it's fine that gendered tokens aren't handled.

						if correctedTagTokenText is not None:
							addText(correctedTagTokenText)
				else:
					raise _UnsupportedLocalizationStringException("The tag '%s' is an unknown tag for a localization string token." % tagText)
			elif isinstance(tagToken, Localization_pb2.LocalizedStringToken):
				# noinspection PyTypeChecker
				addTokenText(tagToken)
			else:
				raise _UnsupportedLocalizationStringException("Unsupported token type '%s'." % Types.GetFullName(tagToken))

		uncorrectedTextStartPosition = nextUnfixedTextStartPosition

	correctedText += text[uncorrectedTextStartPosition:]

	return correctedText