/** * Author: dkanus * Home repo: https://www.insultplayers.ru/git/AcediaFramework/AcediaCore * License: GPL * Copyright 2022-2023 Anton Tarasenko *------------------------------------------------------------------------------ * This file is part of Acedia. * * Acedia is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, version 3 of the License, or * (at your option) any later version. * * Acedia is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Acedia. If not, see . */ class SideEffect extends AcediaObject; //! Defines the concept of "side effects" in the context of the Acedia and its derivative mods. //! //! Side effects are changes that are not part of the mod's main functionality, but rather something //! necessary to enable that functionality, while also possibly affecting how other mods work. //! Documenting these side effects helps developers and server admins understand changes performed //! by Acedia or mods based on it, and anticipate any potential conflicts or issues that may arise. //! //! It should be noted that what constitutes a side effect is loosely defined, and it is simply //! a tool to inform others that something unexpected has happened, possibly breaking other mods. //! AcediaCore aims to leave a minimal footprint, but still needs to make some changes //! (e.g., adding GameRules, patching code of some functions), and [`SideEffects`] can be used to //! document them. //! Similarly, [`SideEffect`]s can be used to document changes made by AcediaFixes, a package meant //! only for fixing bugs that inevitably needs to make many under-the-hood changes to achieve //! that goal. //! //! On the other hand gameplay mods like Futility or Ire can make a lot of changes, but they can all //! be just expected part of its direct functionality: we expect feature that shares dosh of leavers //! to alter players' dosh values, so this is not a side effect. //! Such mods are likely not going to have to specify any side effects whatsoever. var private Text name; var private Text description; var private Text package; var private Text source; var private Text status; var private bool initialized; protected function Finalizer() { _.memory.Free(name); _.memory.Free(description); _.memory.Free(package); _.memory.Free(source); _.memory.Free(status); name = none; description = none; package = none; source = none; status = none; initialized = false; } /// Checks whether caller [`SideEffect`] was initialized. /// /// Initialization must happen directly after creation and only initialized instances should /// ever be used. public final function bool IsInitialized() { return initialized; } /// This function is used to set the initial values of the [`SideEffect`] object properties when it /// is first created. /// /// All arguments must be not `none`. /// /// Returns `true` if the initialization was successful, `false` otherwise (including the case where /// the [`SideEffect`] object has already been initialized). public final function bool Initialize( BaseText sideEffectName, BaseText sideEffectDescription, BaseText sideEffectPackage, BaseText sideEffectSource, BaseText sideEffectStatus ) { if (initialized) return false; if (sideEffectName == none) return false; if (sideEffectDescription == none) return false; if (sideEffectPackage == none) return false; if (sideEffectSource == none) return false; if (sideEffectStatus == none) return false; name = sideEffectName.Copy(); description = sideEffectDescription.Copy(); package = sideEffectPackage.Copy(); source = sideEffectSource.Copy(); status = sideEffectStatus.Copy(); initialized = true; return true; } /// This function is used to set the initial values of the [`SideEffect`] object properties when it /// is first created. /// /// Returns `true` if the initialization was successful, `false` otherwise (including the case where /// the [`SideEffect`] object has already been initialized). public final function bool Initialize_S( string sideEffectName, string sideEffectDescription, string sideEffectPackage, string sideEffectSource, string sideEffectStatus ) { name = _.text.FromString(sideEffectName); description = _.text.FromString(sideEffectDescription); package = _.text.FromString(sideEffectPackage); source = _.text.FromString(sideEffectSource); status = _.text.FromString(sideEffectStatus); initialized = true; return true; } /// Returns a brief summary that conveys the purpose of the caller [SideEffect] to the user in /// a clear and concise manner. /// /// While there is no hard limit on the length of this value, it is recommended to keep it under 80 /// characters for readability. /// /// Returned value for initialized [`SideEffect`] is guaranteed to not be `none`, as it is /// a required property of the [`SideEffect`] object. public final function Text GetName() { if (initialized) { return name.Copy(); } return none; } /// Returns a brief summary that conveys the purpose of the caller [SideEffect] to the user in /// a clear and concise manner. /// /// While there is no hard limit on the length of this value, it is recommended to keep it under 80 /// characters for readability. public final function string GetName_S() { if (initialized && name != none) { return name.ToString(); } return ""; } /// Returns the detailed description of the caller [`SideEffect`], which describes what was done /// and why the relevant change was necessary. /// /// Returned value for initialized [`SideEffect`] is guaranteed to not be `none`, as it is /// a required property of the [`SideEffect`] object. public final function Text GetDescription() { if (initialized) { return description.Copy(); } return none; } /// Returns the detailed description of the caller [`SideEffect`], which describes what was done /// and why the relevant change was necessary. public final function string GetDescription_S() { if (initialized && description != none) { return description.ToString(); } return ""; } /// Returns the name of the package ("*.u" file) that introduced the changes /// represented by the caller `SideEffect`. /// /// It should be noted that even if a different package requested the functionality that led to /// the changes being made, the package responsible for the side effect is the one that performed /// the changes. /// /// Returned value for initialized [`SideEffect`] is guaranteed to not be `none`, as it is /// a required property of the [`SideEffect`] object. public final function Text GetPackage() { if (initialized) { return package.Copy(); } return none; } /// Returns the name of the package ("*.u" file) that introduced the changes /// represented by the caller `SideEffect`. /// /// It should be noted that even if a different package requested the functionality that led to /// the changes being made, the package responsible for the side effect is the one that performed /// the changes. public final function string GetPackage_S() { if (initialized && package != none) { return package.ToString(); } return ""; } /// The origin of this change within the package is specified, and for larger packages, additional /// details can be provided to clarify the cause of the change. /// /// Returned value for initialized [`SideEffect`] is guaranteed to not be `none`, as it is /// a required property of the [`SideEffect`] object. public final function Text GetSource() { if (initialized) { return source.Copy(); } return none; } /// The origin of this change within the package is specified, and for larger packages, additional /// details can be provided to clarify the cause of the change. public final function string GetSource_S() { if (initialized && source != none) { return source.ToString(); } return ""; } /// The status of the caller [`SideEffect`], that is used to differentiate between different ways /// that a side effect may have been introduced, allowing for better tracking and management of /// the effect. /// /// Returned value for initialized [`SideEffect`] is guaranteed to not be `none`, as it is /// a required property of the [`SideEffect`] object. public final function Text GetStatus() { if (initialized) { return status.Copy(); } return none; } /// The status of the caller [`SideEffect`], that is used to differentiate between different ways /// that a side effect may have been introduced, allowing for better tracking and management of /// the effect. public final function string GetStatus_S() { if (initialized && status != none) { return status.ToString(); } return ""; } public function bool IsEqual(Object other) { local SideEffect otherSideEffect; if (self == other) return true; otherSideEffect = SideEffect(other); if (otherSideEffect == none) return false; if (!otherSideEffect.initialized) return false; if (GetHashCode() != otherSideEffect.GetHashCode()) return false; if (!name.Compare(otherSideEffect.name,, SFORM_SENSITIVE)) return false; if (!package.Compare(otherSideEffect.package,, SFORM_SENSITIVE)) return false; if (!source.Compare(otherSideEffect.source,, SFORM_SENSITIVE)) return false; if (!status.Compare(otherSideEffect.status,, SFORM_SENSITIVE)) return false; if (!description.Compare(otherSideEffect.description,, SFORM_SENSITIVE)) return false; return true; } protected function int CalculateHashCode() { local int result; if (initialized) { result = name.GetHashCode(); result = CombineHash(result, description.GetHashCode()); result = CombineHash(result, package.GetHashCode()); result = CombineHash(result, source.GetHashCode()); result = CombineHash(result, status.GetHashCode()); return result; } } defaultproperties { }