rott/kf_sources/AcediaCore/Classes/SideEffect.uc
2026-07-14 20:27:09 +07:00

277 lines
11 KiB
Ucode

/**
* 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 <https://www.gnu.org/licenses/>.
*/
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 {
}