Browse Source
Aliases were initially using `Actor`-base objects to manage themselves, but that became a legacy approachin AcediaCore and they had to be reimplemented without any `Actor`s (based on `Feature` instead), allowing them mto be usable even when no `LevelCore` is provided.pull/8/head
Anton Tarasenko
2 years ago
25 changed files with 1391 additions and 802 deletions
@ -1,117 +1,18 @@ |
|||||||
[AcediaCore.FeatureAliasSource] |
; NOTE: You most likely do not want to modify this file, unless you are really |
||||||
[AcediaCore:Commands_Feature FeatureAliases] |
; sure what you're doing or was told exactly what to do by someone. |
||||||
Alias="commands" |
[default Aliases] |
||||||
Alias="command" |
; This feature allows you to configure what alias sources are used for resolving |
||||||
Alias="comands" |
; what alias types. Like all Acedia's features, it supports multiple named |
||||||
Alias="comand" |
; configs, allowing you to, say, replacve `weaponAliasSoruce` with a different |
||||||
Alias="cmds" |
; one when running a mod that replaces stock weapons. |
||||||
Alias="cmd" |
autoEnable=true |
||||||
|
weaponAliasSource=Class'AcediaCore.WeaponAliasSource' |
||||||
[AcediaCore:Avarice_Feature FeatureAliases] |
colorAliasSource=Class'AcediaCore.ColorAliasSource' |
||||||
Alias="Avarice" |
featureAliasSource=Class'AcediaCore.FeatureAliasSource' |
||||||
|
entityAliasSource=Class'AcediaCore.EntityAliasSource' |
||||||
[AcediaFixes:FixAmmoSelling_Feature FeatureAliases] |
; `customSource` records allow you to add custom alias sources into Acedia, |
||||||
Alias="FixAmmoSelling" |
; that is sources that do not fit either of the standard groups. These sources |
||||||
Alias="FixSelling" |
; can then be used by mods to resolve custom aliases using specified `name`. |
||||||
Alias="FixAmmo" |
; Their names, unlike aliases, are case-sensitive. |
||||||
Alias="AmmoSellingFix" |
;customSource=(name="custom",source=Class'BlaBla.CustomSource') |
||||||
Alias="SellingFix" |
customSource=(name="mock",source=Class'AcediaCore.MockAliasSource') |
||||||
Alias="AmmoFix" |
|
||||||
Alias="FixAmmoSell" |
|
||||||
Alias="FixSell" |
|
||||||
Alias="AmmoSellFix" |
|
||||||
Alias="SellFix" |
|
||||||
Alias="FixAmmoPrinting" |
|
||||||
Alias="FixPrinting" |
|
||||||
Alias="AmmoPrintingFix" |
|
||||||
Alias="PrintingFix" |
|
||||||
Alias="FixAmmoPrint" |
|
||||||
Alias="FixPrint" |
|
||||||
Alias="AmmoPrintFix" |
|
||||||
Alias="PrintFix" |
|
||||||
|
|
||||||
[AcediaFixes:FixDoshSpam_Feature FeatureAliases] |
|
||||||
Alias="DoshSpamFix" |
|
||||||
Alias="DoshFix" |
|
||||||
Alias="CashSpamFix" |
|
||||||
Alias="CashFix" |
|
||||||
Alias="FixDoshSpamF" |
|
||||||
Alias="FixDosh" |
|
||||||
Alias="FixCashSpam" |
|
||||||
Alias="FixCash" |
|
||||||
|
|
||||||
[AcediaFixes:FixDualiesCost_Feature FeatureAliases] |
|
||||||
Alias="FixDualiesCost" |
|
||||||
Alias="FixDualies" |
|
||||||
Alias="DualiesCostFix" |
|
||||||
Alias="DualiesFix" |
|
||||||
|
|
||||||
[AcediaFixes:FixFFHack_Feature FeatureAliases] |
|
||||||
Alias="FixFFHack" |
|
||||||
Alias="FixFriendlyFireHack" |
|
||||||
Alias="FixFriendFireHack" |
|
||||||
Alias="FFHackFix" |
|
||||||
Alias="FriendlyFireHackFix" |
|
||||||
Alias="FriendFireHackFix" |
|
||||||
|
|
||||||
[AcediaFixes:FixInfiniteNades_Feature FeatureAliases] |
|
||||||
Alias="FixInfiniteNades" |
|
||||||
Alias="FixInfiniteNade" |
|
||||||
Alias="FixInfNades" |
|
||||||
Alias="FixInfNade" |
|
||||||
Alias="FixNades" |
|
||||||
Alias="FixNade" |
|
||||||
Alias="InfiniteNadesFix" |
|
||||||
Alias="InfiniteNadeFix" |
|
||||||
Alias="InfNadesFix" |
|
||||||
Alias="InfNadeFix" |
|
||||||
Alias="NadesFix" |
|
||||||
Alias="NadeFix" |
|
||||||
|
|
||||||
[AcediaFixes:FixInventoryAbuse_Feature FeatureAliases] |
|
||||||
Alias="FixInventoryAbuse" |
|
||||||
Alias="FixInventory" |
|
||||||
Alias="InventoryAbuseFix" |
|
||||||
Alias="InventoryFix" |
|
||||||
|
|
||||||
[AcediaFixes:FixLogSpam_Feature FeatureAliases] |
|
||||||
Alias="FixLogSpam" |
|
||||||
Alias="FixLog" |
|
||||||
Alias="LogSpamFix" |
|
||||||
Alias="LogFix" |
|
||||||
|
|
||||||
[AcediaFixes:FixPipes_Feature FeatureAliases] |
|
||||||
Alias="FixPipes" |
|
||||||
Alias="FixPipe" |
|
||||||
Alias="PipesFix" |
|
||||||
Alias="PipeFix" |
|
||||||
|
|
||||||
[AcediaFixes:FixProjectileFF_Feature FeatureAliases] |
|
||||||
Alias="FixProjectileFriendlyFire" |
|
||||||
Alias="FixProjectileFF" |
|
||||||
Alias="FixProjFriendlyFire" |
|
||||||
Alias="FixProjFF" |
|
||||||
Alias="FixFriendlyFire" |
|
||||||
Alias="FixFF" |
|
||||||
Alias="ProjectileFriendlyFireFix" |
|
||||||
Alias="ProjectileFFFix" |
|
||||||
Alias="ProjFriendlyFireFix" |
|
||||||
Alias="ProjFFFix" |
|
||||||
Alias="FriendlyFireFix" |
|
||||||
Alias="FFFix" |
|
||||||
|
|
||||||
[AcediaFixes:FixSpectatorCrash_Feature FeatureAliases] |
|
||||||
Alias="FixSpectatorCrash" |
|
||||||
Alias="FixSpecCrash" |
|
||||||
Alias="SpectatorCrashFix" |
|
||||||
Alias="SpecCrashFix" |
|
||||||
|
|
||||||
[AcediaFixes:FixZedTimeLags_Feature FeatureAliases] |
|
||||||
Alias="FixZedTimeLags" |
|
||||||
Alias="FixZedTime" |
|
||||||
Alias="FixZTLags" |
|
||||||
Alias="FixZT" |
|
||||||
Alias="ZedTimeLagsFix" |
|
||||||
Alias="ZedTimeFix" |
|
||||||
Alias="ZTLagsFix" |
|
||||||
Alias="ZTFix" |
|
@ -0,0 +1,119 @@ |
|||||||
|
; This config file allows you to configure feature aliases. |
||||||
|
; Remember that aliases are case-insensitive. |
||||||
|
[AcediaCore.FeatureAliasSource] |
||||||
|
[AcediaCore:Commands_Feature FeatureAliases] |
||||||
|
Alias="commands" |
||||||
|
Alias="command" |
||||||
|
Alias="comands" |
||||||
|
Alias="comand" |
||||||
|
Alias="cmds" |
||||||
|
Alias="cmd" |
||||||
|
|
||||||
|
[AcediaCore:Avarice_Feature FeatureAliases] |
||||||
|
Alias="Avarice" |
||||||
|
|
||||||
|
[AcediaFixes:FixAmmoSelling_Feature FeatureAliases] |
||||||
|
Alias="FixAmmoSelling" |
||||||
|
Alias="FixSelling" |
||||||
|
Alias="FixAmmo" |
||||||
|
Alias="AmmoSellingFix" |
||||||
|
Alias="SellingFix" |
||||||
|
Alias="AmmoFix" |
||||||
|
Alias="FixAmmoSell" |
||||||
|
Alias="FixSell" |
||||||
|
Alias="AmmoSellFix" |
||||||
|
Alias="SellFix" |
||||||
|
Alias="FixAmmoPrinting" |
||||||
|
Alias="FixPrinting" |
||||||
|
Alias="AmmoPrintingFix" |
||||||
|
Alias="PrintingFix" |
||||||
|
Alias="FixAmmoPrint" |
||||||
|
Alias="FixPrint" |
||||||
|
Alias="AmmoPrintFix" |
||||||
|
Alias="PrintFix" |
||||||
|
|
||||||
|
[AcediaFixes:FixDoshSpam_Feature FeatureAliases] |
||||||
|
Alias="DoshSpamFix" |
||||||
|
Alias="DoshFix" |
||||||
|
Alias="CashSpamFix" |
||||||
|
Alias="CashFix" |
||||||
|
Alias="FixDoshSpamF" |
||||||
|
Alias="FixDosh" |
||||||
|
Alias="FixCashSpam" |
||||||
|
Alias="FixCash" |
||||||
|
|
||||||
|
[AcediaFixes:FixDualiesCost_Feature FeatureAliases] |
||||||
|
Alias="FixDualiesCost" |
||||||
|
Alias="FixDualies" |
||||||
|
Alias="DualiesCostFix" |
||||||
|
Alias="DualiesFix" |
||||||
|
|
||||||
|
[AcediaFixes:FixFFHack_Feature FeatureAliases] |
||||||
|
Alias="FixFFHack" |
||||||
|
Alias="FixFriendlyFireHack" |
||||||
|
Alias="FixFriendFireHack" |
||||||
|
Alias="FFHackFix" |
||||||
|
Alias="FriendlyFireHackFix" |
||||||
|
Alias="FriendFireHackFix" |
||||||
|
|
||||||
|
[AcediaFixes:FixInfiniteNades_Feature FeatureAliases] |
||||||
|
Alias="FixInfiniteNades" |
||||||
|
Alias="FixInfiniteNade" |
||||||
|
Alias="FixInfNades" |
||||||
|
Alias="FixInfNade" |
||||||
|
Alias="FixNades" |
||||||
|
Alias="FixNade" |
||||||
|
Alias="InfiniteNadesFix" |
||||||
|
Alias="InfiniteNadeFix" |
||||||
|
Alias="InfNadesFix" |
||||||
|
Alias="InfNadeFix" |
||||||
|
Alias="NadesFix" |
||||||
|
Alias="NadeFix" |
||||||
|
|
||||||
|
[AcediaFixes:FixInventoryAbuse_Feature FeatureAliases] |
||||||
|
Alias="FixInventoryAbuse" |
||||||
|
Alias="FixInventory" |
||||||
|
Alias="InventoryAbuseFix" |
||||||
|
Alias="InventoryFix" |
||||||
|
|
||||||
|
[AcediaFixes:FixLogSpam_Feature FeatureAliases] |
||||||
|
Alias="FixLogSpam" |
||||||
|
Alias="FixLog" |
||||||
|
Alias="LogSpamFix" |
||||||
|
Alias="LogFix" |
||||||
|
|
||||||
|
[AcediaFixes:FixPipes_Feature FeatureAliases] |
||||||
|
Alias="FixPipes" |
||||||
|
Alias="FixPipe" |
||||||
|
Alias="PipesFix" |
||||||
|
Alias="PipeFix" |
||||||
|
|
||||||
|
[AcediaFixes:FixProjectileFF_Feature FeatureAliases] |
||||||
|
Alias="FixProjectileFriendlyFire" |
||||||
|
Alias="FixProjectileFF" |
||||||
|
Alias="FixProjFriendlyFire" |
||||||
|
Alias="FixProjFF" |
||||||
|
Alias="FixFriendlyFire" |
||||||
|
Alias="FixFF" |
||||||
|
Alias="ProjectileFriendlyFireFix" |
||||||
|
Alias="ProjectileFFFix" |
||||||
|
Alias="ProjFriendlyFireFix" |
||||||
|
Alias="ProjFFFix" |
||||||
|
Alias="FriendlyFireFix" |
||||||
|
Alias="FFFix" |
||||||
|
|
||||||
|
[AcediaFixes:FixSpectatorCrash_Feature FeatureAliases] |
||||||
|
Alias="FixSpectatorCrash" |
||||||
|
Alias="FixSpecCrash" |
||||||
|
Alias="SpectatorCrashFix" |
||||||
|
Alias="SpecCrashFix" |
||||||
|
|
||||||
|
[AcediaFixes:FixZedTimeLags_Feature FeatureAliases] |
||||||
|
Alias="FixZedTimeLags" |
||||||
|
Alias="FixZedTime" |
||||||
|
Alias="FixZTLags" |
||||||
|
Alias="FixZT" |
||||||
|
Alias="ZedTimeLagsFix" |
||||||
|
Alias="ZedTimeFix" |
||||||
|
Alias="ZTLagsFix" |
||||||
|
Alias="ZTFix" |
@ -1,139 +0,0 @@ |
|||||||
/** |
|
||||||
* Service that handles pending saving of aliases data into configs. |
|
||||||
* Adding aliases into `AliasSource`s causes corresponding configs to update. |
|
||||||
* This service allows to delay and spread config rewrites over time, |
|
||||||
* which should help in case someone dynamically adds a lot of |
|
||||||
* different aliases. |
|
||||||
* Copyright 2020 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 AliasService extends Service |
|
||||||
config(AcediaSystem); |
|
||||||
|
|
||||||
// Objects for which we are yet to write configs |
|
||||||
var private array<AliasSource> sourcesPendingToSave; |
|
||||||
var private array<Aliases> aliasesPendingToSave; |
|
||||||
// How often should we do it. |
|
||||||
// Negative or zero values would be reset to `0.05`. |
|
||||||
var public config const float saveInterval; |
|
||||||
|
|
||||||
// To avoid creating yet another object for aliases system we will |
|
||||||
// keep config variable pointing to weapon, color, etc. `AliasSource` |
|
||||||
// subclasses here. It's not the best regarding separation of responsibility, |
|
||||||
// but should make config files less fragmented. |
|
||||||
// Changing these allows you to change in what sources `AliasesAPI` |
|
||||||
// looks for weapon and color aliases. |
|
||||||
var public config const class<AliasSource> weaponAliasesSource; |
|
||||||
var public config const class<AliasSource> colorAliasesSource; |
|
||||||
var public config const class<AliasSource> featureAliasesSource; |
|
||||||
var public config const class<AliasSource> entityAliasesSource; |
|
||||||
|
|
||||||
protected simulated function OnLaunch() |
|
||||||
{ |
|
||||||
local float actualInterval; |
|
||||||
actualInterval = saveInterval; |
|
||||||
if (actualInterval <= 0) |
|
||||||
{ |
|
||||||
actualInterval = 0.05; |
|
||||||
} |
|
||||||
SetTimer(actualInterval, true); |
|
||||||
} |
|
||||||
|
|
||||||
protected simulated function OnShutdown() |
|
||||||
{ |
|
||||||
SaveAllPendingObjects(); |
|
||||||
} |
|
||||||
|
|
||||||
public simulated final function PendingSaveSource(AliasSource sourceToSave) |
|
||||||
{ |
|
||||||
local int i; |
|
||||||
if (sourceToSave == none) return; |
|
||||||
// Starting searching from the end of an array will make situations when |
|
||||||
// we add several aliases to a single source in a row more efficient. |
|
||||||
for (i = sourcesPendingToSave.length - 1;i >= 0; i -= 1) { |
|
||||||
if (sourcesPendingToSave[i] == sourceToSave) return; |
|
||||||
} |
|
||||||
sourcesPendingToSave[sourcesPendingToSave.length] = sourceToSave; |
|
||||||
} |
|
||||||
|
|
||||||
public simulated final function PendingSaveObject(Aliases objectToSave) |
|
||||||
{ |
|
||||||
local int i; |
|
||||||
if (objectToSave == none) return; |
|
||||||
// Starting searching from the end of an array will make situations when |
|
||||||
// we add several aliases to a single `Aliases` object in a row |
|
||||||
// more efficient. |
|
||||||
for (i = aliasesPendingToSave.length - 1;i >= 0; i -= 1) { |
|
||||||
if (aliasesPendingToSave[i] == objectToSave) return; |
|
||||||
} |
|
||||||
aliasesPendingToSave[aliasesPendingToSave.length] = objectToSave; |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Forces saving of the next object (either `AliasSource` or `Aliases`) |
|
||||||
* in queue to the config file. |
|
||||||
* |
|
||||||
* Does not reset the timer until next saving. |
|
||||||
*/ |
|
||||||
private simulated final function DoSaveNextPendingObject() |
|
||||||
{ |
|
||||||
if (sourcesPendingToSave.length > 0) |
|
||||||
{ |
|
||||||
if (sourcesPendingToSave[0] != none) { |
|
||||||
sourcesPendingToSave[0].SaveConfig(); |
|
||||||
} |
|
||||||
sourcesPendingToSave.Remove(0, 1); |
|
||||||
return; |
|
||||||
} |
|
||||||
if (aliasesPendingToSave.length > 0) |
|
||||||
{ |
|
||||||
aliasesPendingToSave[0].SaveOrClear(); |
|
||||||
aliasesPendingToSave.Remove(0, 1); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Forces saving of all objects (both `AliasSource`s or `Aliases`s) in queue |
|
||||||
* to their config files. |
|
||||||
*/ |
|
||||||
private simulated final function SaveAllPendingObjects() |
|
||||||
{ |
|
||||||
local int i; |
|
||||||
for (i = 0; i < sourcesPendingToSave.length; i += 1) { |
|
||||||
if (sourcesPendingToSave[i] == none) continue; |
|
||||||
sourcesPendingToSave[i].SaveConfig(); |
|
||||||
} |
|
||||||
for (i = 0; i < aliasesPendingToSave.length; i += 1) { |
|
||||||
aliasesPendingToSave[i].SaveOrClear(); |
|
||||||
} |
|
||||||
sourcesPendingToSave.length = 0; |
|
||||||
aliasesPendingToSave.length = 0; |
|
||||||
} |
|
||||||
|
|
||||||
public simulated function Timer() |
|
||||||
{ |
|
||||||
DoSaveNextPendingObject(); |
|
||||||
} |
|
||||||
|
|
||||||
defaultproperties |
|
||||||
{ |
|
||||||
saveInterval = 0.05 |
|
||||||
weaponAliasesSource = class'WeaponAliasSource' |
|
||||||
colorAliasesSource = class'ColorAliasSource' |
|
||||||
featureAliasesSource = class'FeatureAliasSource' |
|
||||||
entityAliasesSource = class'EntityAliasSource' |
|
||||||
} |
|
@ -0,0 +1,205 @@ |
|||||||
|
/** |
||||||
|
* This is a simple helper object for `AliasSource` that can store |
||||||
|
* an array of aliases in config files in a per-object-config manner. |
||||||
|
* One `AliasesStorage` object can store several aliases for a single |
||||||
|
* value. |
||||||
|
* It is recommended that you do not try to access these objects directly. |
||||||
|
* `AliasesStorage` is abstract, so it can never be created, for any |
||||||
|
* actual use create a child class. Suggested name scheme is |
||||||
|
* "<something>Aliases", like "ColorAliases" or "WeaponAliases". |
||||||
|
* It's only interesting function is storing '.'s as ':' in it's config, |
||||||
|
* which is necessary to allow storing aliases for class names via |
||||||
|
* these objects (since UnrealScript's cannot handle '.'s in object's names |
||||||
|
* in it's configs). |
||||||
|
* [INTERNAL] This is an internal object and should not be directly modified, |
||||||
|
* its only allowed use is documented way to create new alias sources. |
||||||
|
* Copyright 2019-2022 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 AliasesStorage extends AcediaObject |
||||||
|
perObjectConfig |
||||||
|
config(AcediaAliases) |
||||||
|
abstract; |
||||||
|
|
||||||
|
// Aliases, recorded by this `AliasesStorage` object that all refer to |
||||||
|
// the same value, defined by this object's name `string(self.name)` |
||||||
|
var protected config array<string> alias; |
||||||
|
|
||||||
|
// Name of the configurational file (without extension) where |
||||||
|
// this `AliasSource`'s data will be stored |
||||||
|
var protected const string configName; |
||||||
|
|
||||||
|
// Link to the `AliasSource` that uses `AliasesStorage` objects of this class. |
||||||
|
// To ensure that any `AliasesStorage` sub-class only belongs to one |
||||||
|
// `AliasSource`. |
||||||
|
var public const class<AliasSource> sourceClass; |
||||||
|
|
||||||
|
// `true` means that this `AliasesStorage` object is awaiting saving into its |
||||||
|
// config |
||||||
|
var private bool pendingSaveToConfig; |
||||||
|
|
||||||
|
// Since: |
||||||
|
// 1. '.'s in values are converted into ':' for storage purposes; |
||||||
|
// 2. We have to store values in `string` to make use of config files. |
||||||
|
// we need methods to convert between "storage" (`string`) |
||||||
|
// and "actual" (`Text`) value version. |
||||||
|
// `ToStorageVersion()` and `ToActualVersion()` do that. |
||||||
|
private final static function string ToStorageVersion(BaseText actualValue) |
||||||
|
{ |
||||||
|
return Repl(actualValue.ToString(), ".", ":"); |
||||||
|
} |
||||||
|
|
||||||
|
// See comment to `ToStorageVersion()` |
||||||
|
private final static function Text ToActualVersion(string storageValue) |
||||||
|
{ |
||||||
|
return __().text.FromString(Repl(storageValue, ":", ".")); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Loads all `AliasesStorage` objects from their config file |
||||||
|
* (defined in paired `AliasSource` class). |
||||||
|
* |
||||||
|
* This is an internal method and returned `AliasesStorage` objects require |
||||||
|
* a special treatment: they aren't meant to be used with Acedia's reference |
||||||
|
* counting - never release their references. |
||||||
|
* |
||||||
|
* @return Array of all `Aliases` objects, loaded from their config file. |
||||||
|
*/ |
||||||
|
public static final function array<AliasesStorage> LoadAllObjects() |
||||||
|
{ |
||||||
|
local int i; |
||||||
|
local array<string> objectNames; |
||||||
|
local array<AliasesStorage> loadedAliasObjects; |
||||||
|
|
||||||
|
objectNames = GetPerObjectNames(default.configName, |
||||||
|
string(default.class.name), MaxInt); |
||||||
|
for (i = 0; i < objectNames.length; i += 1) { |
||||||
|
loadedAliasObjects[i] = LoadObjectByName(objectNames[i]); |
||||||
|
} |
||||||
|
return loadedAliasObjects; |
||||||
|
} |
||||||
|
|
||||||
|
// Loads a new `AliasesStorage` object by it's given name (`objectName`). |
||||||
|
private static final function AliasesStorage LoadObjectByName( |
||||||
|
string objectName) |
||||||
|
{ |
||||||
|
local AliasesStorage result; |
||||||
|
|
||||||
|
// Since `MemoryAPI` for now does not support specifying names |
||||||
|
// to created objects - do some manual dark magic and |
||||||
|
// initialize this shit ourselves. Don't repeat this at home, kids. |
||||||
|
result = new(none, objectName) default.class; |
||||||
|
result._constructor(); |
||||||
|
return result; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Loads a new `AliasesStorage` object based on the value (`aliasesValue`) |
||||||
|
* of it's aliases. |
||||||
|
* |
||||||
|
* @param aliasesValue Value that aliases in this `Aliases` object will |
||||||
|
* correspond to. |
||||||
|
* @return Instance of `AliasesStorage` object with a given name. |
||||||
|
*/ |
||||||
|
public static final function AliasesStorage LoadObject(BaseText aliasesValue) |
||||||
|
{ |
||||||
|
if (aliasesValue != none) { |
||||||
|
return LoadObjectByName(ToStorageVersion(aliasesValue)); |
||||||
|
} |
||||||
|
return none; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Returns value that caller's `Aliases` object's aliases point to. |
||||||
|
* |
||||||
|
* @return Value, stored by this object. |
||||||
|
*/ |
||||||
|
public final function Text GetValue() |
||||||
|
{ |
||||||
|
return ToActualVersion(string(self.name)); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Returns array of aliases that caller `AliasesStorage` tells us point to |
||||||
|
* it's value. |
||||||
|
* |
||||||
|
* @return Array of all aliases, stored by caller `AliasesStorage` object. |
||||||
|
*/ |
||||||
|
public final function array<Text> GetAliases() |
||||||
|
{ |
||||||
|
local int i; |
||||||
|
local array<Text> textAliases; |
||||||
|
|
||||||
|
for (i = 0; i < alias.length; i += 1) { |
||||||
|
textAliases[i] = _.text.FromString(alias[i]); |
||||||
|
} |
||||||
|
return textAliases; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* [For inner use by `AliasSource`] Removes alias from this object. |
||||||
|
* |
||||||
|
* Does not update relevant `AliasHash`. |
||||||
|
* |
||||||
|
* Will prevent adding duplicate records inside it's own storage. |
||||||
|
* |
||||||
|
* @param aliasToRemove Alias to remove from caller `AliasesStorage` object. |
||||||
|
* Expected to be in lower case. |
||||||
|
*/ |
||||||
|
public final function RemoveAlias_S(string aliasToRemove) |
||||||
|
{ |
||||||
|
local int i; |
||||||
|
local bool removedAlias; |
||||||
|
|
||||||
|
while (i < alias.length) |
||||||
|
{ |
||||||
|
if (aliasToRemove ~= alias[i]) |
||||||
|
{ |
||||||
|
alias.Remove(i, 1); |
||||||
|
removedAlias = true; |
||||||
|
} |
||||||
|
else { |
||||||
|
i += 1; |
||||||
|
} |
||||||
|
} |
||||||
|
if (!pendingSaveToConfig) |
||||||
|
{ |
||||||
|
pendingSaveToConfig = true; |
||||||
|
_.scheduler.RequestDiskAccess(self).connect = SaveOrClear; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* If this object still has any alias records, - forces a rewrite of it's data |
||||||
|
* into the config file, otherwise - removes it's record entirely. |
||||||
|
*/ |
||||||
|
private final function SaveOrClear() |
||||||
|
{ |
||||||
|
if (alias.length <= 0) { |
||||||
|
ClearConfig(); |
||||||
|
} |
||||||
|
else { |
||||||
|
SaveConfig(); |
||||||
|
} |
||||||
|
pendingSaveToConfig = false; |
||||||
|
} |
||||||
|
|
||||||
|
defaultproperties |
||||||
|
{ |
||||||
|
sourceClass = class'AliasSource' |
||||||
|
configName = "AcediaAliases" |
||||||
|
} |
@ -0,0 +1,249 @@ |
|||||||
|
/** |
||||||
|
* This feature provides a mechanism to define commands that automatically |
||||||
|
* parse their arguments into standard Acedia collection. It also allows to |
||||||
|
* manage them (and specify limitation on how they can be called) in a |
||||||
|
* centralized manner. |
||||||
|
* Copyright 2022 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 Aliases_Feature extends Feature |
||||||
|
dependson(Aliases); |
||||||
|
|
||||||
|
struct ClassSourcePair |
||||||
|
{ |
||||||
|
var class<AliasSource> class; |
||||||
|
var AliasSource source; |
||||||
|
}; |
||||||
|
// We don't want to reload `AliasSource`s several times when this feature is |
||||||
|
// disabled and re-enabled or its config is swapped, so we keep all loaded |
||||||
|
// sources here at all times and look them up from here |
||||||
|
var private array<ClassSourcePair> loadedSources; |
||||||
|
|
||||||
|
// Loaded `AliasSource`s |
||||||
|
var private AliasSource weaponAliasSource; |
||||||
|
var private AliasSource colorAliasSource; |
||||||
|
var private AliasSource featureAliasSource; |
||||||
|
var private AliasSource entityAliasSource; |
||||||
|
// Everything else |
||||||
|
var private HashTable customSources; |
||||||
|
|
||||||
|
var private LoggerAPI.Definition errCannotLoadAliasSource, errEmptyName; |
||||||
|
var private LoggerAPI.Definition errDuplicateCustomSource; |
||||||
|
|
||||||
|
protected function OnEnabled() |
||||||
|
{ |
||||||
|
_.alias._reloadSources(); |
||||||
|
} |
||||||
|
|
||||||
|
protected function OnDisabled() |
||||||
|
{ |
||||||
|
DropSources(); |
||||||
|
_.alias._reloadSources(); |
||||||
|
} |
||||||
|
|
||||||
|
private function DropSources() |
||||||
|
{ |
||||||
|
_.memory.Free(weaponAliasSource); |
||||||
|
weaponAliasSource = none; |
||||||
|
_.memory.Free(colorAliasSource); |
||||||
|
colorAliasSource = none; |
||||||
|
_.memory.Free(featureAliasSource); |
||||||
|
featureAliasSource = none; |
||||||
|
_.memory.Free(entityAliasSource); |
||||||
|
entityAliasSource = none; |
||||||
|
_.memory.Free(customSources); |
||||||
|
customSources = none; |
||||||
|
} |
||||||
|
|
||||||
|
// Create each `AliasSource` instance only once to avoid any possible |
||||||
|
// nonsense with loading named objects several times: alias sources don't use |
||||||
|
// `AcediaConfig`s, so they don't automatically avoid named config reloading |
||||||
|
private function AliasSource GetSource(class<AliasSource> sourceClass) |
||||||
|
{ |
||||||
|
local int i; |
||||||
|
local AliasSource newSource; |
||||||
|
local ClassSourcePair newPair; |
||||||
|
|
||||||
|
if (sourceClass == none) { |
||||||
|
return none; |
||||||
|
} |
||||||
|
for (i = 0; i < loadedSources.length; i += 1) |
||||||
|
{ |
||||||
|
if (loadedSources[i].class == sourceClass) { |
||||||
|
return loadedSources[i].source; |
||||||
|
} |
||||||
|
} |
||||||
|
newSource = AliasSource(_.memory.Allocate(sourceClass)); |
||||||
|
if (newSource != none) |
||||||
|
{ |
||||||
|
newPair.class = sourceClass; |
||||||
|
newPair.source = newSource; |
||||||
|
// One reference we store, one we return |
||||||
|
newSource.NewRef(); |
||||||
|
} |
||||||
|
else { |
||||||
|
_.logger.Auto(errCannotLoadAliasSource).ArgClass(sourceClass); |
||||||
|
} |
||||||
|
return newSource; |
||||||
|
} |
||||||
|
|
||||||
|
protected function SwapConfig(FeatureConfig config) |
||||||
|
{ |
||||||
|
local Aliases newConfig; |
||||||
|
|
||||||
|
newConfig = Aliases(config); |
||||||
|
if (newConfig == none) { |
||||||
|
return; |
||||||
|
} |
||||||
|
_.memory.Free(weaponAliasSource); |
||||||
|
DropSources(); |
||||||
|
weaponAliasSource = GetSource(newConfig.weaponAliasSource); |
||||||
|
colorAliasSource = GetSource(newConfig.colorAliasSource); |
||||||
|
featureAliasSource = GetSource(newConfig.featureAliasSource); |
||||||
|
entityAliasSource = GetSource(newConfig.entityAliasSource); |
||||||
|
LoadCustomSources(newConfig.customSource); |
||||||
|
_.alias._reloadSources(); |
||||||
|
} |
||||||
|
|
||||||
|
private function LoadCustomSources( |
||||||
|
array<Aliases.CustomSourceRecord> configCustomSources) |
||||||
|
{ |
||||||
|
local int i; |
||||||
|
local bool reportedEmptyName; |
||||||
|
local Text nextKey; |
||||||
|
local AliasSource nextSource, conflictingSource; |
||||||
|
|
||||||
|
_.memory.Free(customSources); |
||||||
|
customSources = _.collections.EmptyHashTable(); |
||||||
|
for (i = 0; i < configCustomSources.length; i += 1) |
||||||
|
{ |
||||||
|
if (configCustomSources[i].name == "" && !reportedEmptyName) |
||||||
|
{ |
||||||
|
reportedEmptyName = true; |
||||||
|
_.logger.Auto(errEmptyName); |
||||||
|
} |
||||||
|
nextKey = _.text.FromString(configCustomSources[i].name); |
||||||
|
// We only store `AliasSource`s |
||||||
|
conflictingSource = AliasSource(customSources.GetItem(nextKey)); |
||||||
|
if (conflictingSource != none) |
||||||
|
{ |
||||||
|
_.logger.Auto(errDuplicateCustomSource) |
||||||
|
.ArgClass(conflictingSource.class) |
||||||
|
.Arg(nextKey) // Releases `nextKey` |
||||||
|
.ArgClass(configCustomSources[i].source); |
||||||
|
conflictingSource.FreeSelf(); |
||||||
|
continue; |
||||||
|
} |
||||||
|
nextSource = GetSource(configCustomSources[i].source); |
||||||
|
if (nextSource != none) |
||||||
|
{ |
||||||
|
customSources.SetItem(nextKey, nextSource); |
||||||
|
nextSource.FreeSelf(); |
||||||
|
} |
||||||
|
nextKey.FreeSelf(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Returns `AliasSource` for weapon aliases. |
||||||
|
* |
||||||
|
* @return `AliasSource`, configured to store weapon aliases. |
||||||
|
*/ |
||||||
|
public function AliasSource GetWeaponSource() |
||||||
|
{ |
||||||
|
if (weaponAliasSource != none) { |
||||||
|
weaponAliasSource.Newref(); |
||||||
|
} |
||||||
|
return weaponAliasSource; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Returns `AliasSource` for color aliases. |
||||||
|
* |
||||||
|
* @return `AliasSource`, configured to store color aliases. |
||||||
|
*/ |
||||||
|
public function AliasSource GetColorSource() |
||||||
|
{ |
||||||
|
if (colorAliasSource != none) { |
||||||
|
colorAliasSource.Newref(); |
||||||
|
} |
||||||
|
return colorAliasSource; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Returns `AliasSource` for feature aliases. |
||||||
|
* |
||||||
|
* @return `AliasSource`, configured to store feature aliases. |
||||||
|
*/ |
||||||
|
public function AliasSource GetFeatureSource() |
||||||
|
{ |
||||||
|
if (featureAliasSource != none) { |
||||||
|
featureAliasSource.Newref(); |
||||||
|
} |
||||||
|
return featureAliasSource; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Returns `AliasSource` for entity aliases. |
||||||
|
* |
||||||
|
* @return `AliasSource`, configured to store entity aliases. |
||||||
|
*/ |
||||||
|
public function AliasSource GetEntitySource() |
||||||
|
{ |
||||||
|
if (entityAliasSource != none) { |
||||||
|
entityAliasSource.Newref(); |
||||||
|
} |
||||||
|
return entityAliasSource; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Returns custom `AliasSource` with a given name. |
||||||
|
* |
||||||
|
* @return Custom `AliasSource`, configured with a given name `sourceName`. |
||||||
|
*/ |
||||||
|
public function AliasSource GetCustomSource(BaseText sourceName) |
||||||
|
{ |
||||||
|
if (sourceName == none) { |
||||||
|
return none; |
||||||
|
} |
||||||
|
// We only store `AliasSource`s |
||||||
|
return AliasSource(customSources.GetItem(sourceName)); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Returns custom `AliasSource` with a given name `sourceName. |
||||||
|
* |
||||||
|
* @return Custom `AliasSource`, configured with a given name `sourceName`. |
||||||
|
*/ |
||||||
|
public function AliasSource GetCustomSource_S(string sourceName) |
||||||
|
{ |
||||||
|
local Text wrapper; |
||||||
|
local AliasSource result; |
||||||
|
|
||||||
|
wrapper = _.text.FromString(sourceName); |
||||||
|
result = GetCustomSource(wrapper); |
||||||
|
wrapper.FreeSelf(); |
||||||
|
return result; |
||||||
|
} |
||||||
|
|
||||||
|
defaultproperties |
||||||
|
{ |
||||||
|
configClass = class'Aliases' |
||||||
|
errEmptyName = (l=LOG_Error,m="Empty name provided for the custom alias source. This is likely due to an erroneous config.") |
||||||
|
errCannotLoadAliasSource = (l=LOG_Error,m="Failed to load alias source class `%1`.") |
||||||
|
errDuplicateCustomSource = (l=LOG_Error,m="Custom alias source `%1` is already registered with name '%2'. Alias source `%3` with the same name will be ignored.") |
||||||
|
} |
@ -0,0 +1,283 @@ |
|||||||
|
/** |
||||||
|
* Aliases allow users to define human-readable and easier to use |
||||||
|
* "synonyms" to some symbol sequences (mainly names of UnrealScript classes). |
||||||
|
* This is an interface class that can be implemented in various different |
||||||
|
* ways. |
||||||
|
* Several `AliasSource`s are supposed to exist separately, each storing |
||||||
|
* aliases of particular kind: for weapon, zeds, colors, etc.. |
||||||
|
* Copyright 2022 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 BaseAliasSource extends AcediaObject |
||||||
|
abstract; |
||||||
|
|
||||||
|
/** |
||||||
|
* # `AliasSource` |
||||||
|
* |
||||||
|
* Interface for any alias source instance that includes basic methods for |
||||||
|
* alias lookup and adding/removal. |
||||||
|
* |
||||||
|
* ## Aliases |
||||||
|
* |
||||||
|
* Aliases in Acedia are usually defined as either `$<alias_name>`. |
||||||
|
* `<alias_name>` can only contain ASCII latin letters and digits. |
||||||
|
* `<alias_name>` is meant to define a human-readable name for something |
||||||
|
* (e.g. "m14" for `KFMod.M14EBRBattleRifle`). |
||||||
|
* Aliases are *case-insensitive*. |
||||||
|
* '$' prefix is used to emphasize that what user is specifying is, |
||||||
|
* in fact, an alias and it *is not* actually important for aliases feature |
||||||
|
* and API: only `<alias_name>` is used. However, for convenience's sake, |
||||||
|
* `AliasesAPI` usually recognizes aliases both with and without '$' prefix. |
||||||
|
* Alias sources (classes derived from `BaseAliasSource`), however should only |
||||||
|
* handle resolving `<alias_name>`, treating '$' prefix as a mistake in alias |
||||||
|
* parameter. |
||||||
|
* |
||||||
|
* ## Implementation |
||||||
|
* |
||||||
|
* As far as implementation goes, it's up to you how your own child alias |
||||||
|
* source class is configured to obtain its aliases, but `Aliases_Feature` |
||||||
|
* should only create a single instance for every source class (although |
||||||
|
* nothing can prevent other mods from creating more instances, so we cannot |
||||||
|
* give any guarantees). |
||||||
|
* Methods that add or remove aliases are allowed to fail for whatever |
||||||
|
* reason is valid for your source's case (it might forbid adding aliases |
||||||
|
* at all), as long as they return `false`. |
||||||
|
* Although all built-in aliases are storing case-insensitive values, |
||||||
|
* `BaseAliasSource` does not demand that and allows to configure this behavior |
||||||
|
* via `AreValuesCaseSensitive()`. This is important for `GetAliases()` method |
||||||
|
* that returns all aliases referring to a given value. |
||||||
|
*/ |
||||||
|
|
||||||
|
/** |
||||||
|
* Returns whether caller alias source class stores case-sensitive values. |
||||||
|
* |
||||||
|
* This information is necessary for organizing lookup of aliases by |
||||||
|
* a given value. Aliases themselves are always case-insensitive. |
||||||
|
* |
||||||
|
* This method should not change returned value for any fixed class. |
||||||
|
* |
||||||
|
* @return `true` if stored values are case-sensitive and `false` if they are |
||||||
|
* case-insensitive. |
||||||
|
*/ |
||||||
|
public static function bool AreValuesCaseSensitive(); |
||||||
|
|
||||||
|
/** |
||||||
|
* Returns all aliases that represent given value `value`. |
||||||
|
* |
||||||
|
* @param value Value for which to return all its aliases. |
||||||
|
* Whether it is treated as case-sensitive is decided by |
||||||
|
* `AreValuesCaseSensitive()` method, but all default alias sources are |
||||||
|
* case-insensitive. |
||||||
|
* @return Array of all aliases that refer to the given `value` inside |
||||||
|
* the caller alias source. All `Text` references are guaranteed to not be |
||||||
|
* `none` or duplicated. |
||||||
|
*/ |
||||||
|
public function array<Text> GetAliases(BaseText value); |
||||||
|
|
||||||
|
/** |
||||||
|
* Returns all aliases that represent given value `value`. |
||||||
|
* |
||||||
|
* @param value Value for which to return all its aliases. |
||||||
|
* Whether it is treated as case-sensitive is decided by |
||||||
|
* `AreValuesCaseSensitive()` method, but all default alias sources are |
||||||
|
* case-insensitive. |
||||||
|
* @return Array of all aliases that refer to the given `value` inside |
||||||
|
* the caller alias source. All `string` references are guaranteed to not |
||||||
|
* be duplicated. |
||||||
|
*/ |
||||||
|
public function array<string> GetAliases_S(string value) |
||||||
|
{ |
||||||
|
local int i; |
||||||
|
local Text valueAsText; |
||||||
|
local array<Text> resultWithTexts; |
||||||
|
local array<string> result; |
||||||
|
|
||||||
|
valueAsText = _.text.FromString(value); |
||||||
|
resultWithTexts = GetAliases(valueAsText); |
||||||
|
_.memory.Free(valueAsText); |
||||||
|
for (i = 0; i < resultWithTexts.length; i += 1) { |
||||||
|
result[result.length] = resultWithTexts[i].ToString(); |
||||||
|
} |
||||||
|
_.memory.FreeMany(resultWithTexts); |
||||||
|
return result; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Checks if given alias is present in caller `AliasSource`. |
||||||
|
* |
||||||
|
* NOTE: having '$' prefix is considered to be invalid for `alias` by this |
||||||
|
* method. |
||||||
|
* |
||||||
|
* @param alias Alias to check, case-insensitive. |
||||||
|
* @return `true` if present, `false` otherwise. |
||||||
|
*/ |
||||||
|
public function bool HasAlias(BaseText alias); |
||||||
|
|
||||||
|
/** |
||||||
|
* Checks if given alias is present in caller `AliasSource`. |
||||||
|
* |
||||||
|
* NOTE: having '$' prefix is considered to be invalid for `alias` by this |
||||||
|
* method. |
||||||
|
* |
||||||
|
* @param alias Alias to check, case-insensitive. |
||||||
|
* @return `true` if present, `false` otherwise. |
||||||
|
*/ |
||||||
|
public function bool HasAlias_S(string alias) |
||||||
|
{ |
||||||
|
local bool result; |
||||||
|
local Text aliasAsText; |
||||||
|
|
||||||
|
aliasAsText = _.text.FromString(alias); |
||||||
|
result = HasAlias(aliasAsText); |
||||||
|
_.memory.Free(aliasAsText); |
||||||
|
return result; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Returns value stored for the given alias in caller `AliasSource` |
||||||
|
* (as well as it's `Aliases` objects). |
||||||
|
* |
||||||
|
* NOTE: having '$' prefix is considered to be invalid for `alias` by this |
||||||
|
* method. |
||||||
|
* |
||||||
|
* @param alias Alias, for which method will attempt to return |
||||||
|
* a value. Case-insensitive. If given `alias` starts with "$" character - |
||||||
|
* that character will be removed before resolving that alias. |
||||||
|
* @param copyOnFailure Whether method should return copy of original |
||||||
|
* `alias` value in case caller source did not have any records |
||||||
|
* corresponding to `alias`. |
||||||
|
* @return If look up was successful - value, associated with the given |
||||||
|
* alias `alias`. If lookup was unsuccessful, it depends on `copyOnFailure` |
||||||
|
* flag: `copyOnFailure == false` means method will return `none` |
||||||
|
* and `copyOnFailure == true` means method will return `alias.Copy()`. |
||||||
|
* If `alias == none` method always returns `none`. |
||||||
|
*/ |
||||||
|
public function Text Resolve(BaseText alias, optional bool copyOnFailure); |
||||||
|
|
||||||
|
/** |
||||||
|
* Returns value stored for the given alias in caller `AliasSource` |
||||||
|
* (as well as it's `Aliases` objects). |
||||||
|
* |
||||||
|
* NOTE: having '$' prefix is considered to be invalid for `alias` by this |
||||||
|
* method. |
||||||
|
* |
||||||
|
* @param alias Alias, for which method will attempt to return |
||||||
|
* a value. Case-insensitive. If given `alias` starts with "$" character - |
||||||
|
* that character will be removed before resolving that alias. |
||||||
|
* @param copyOnFailure Whether method should return copy of original |
||||||
|
* `alias` value in case caller source did not have any records |
||||||
|
* corresponding to `alias`. |
||||||
|
* @return If look up was successful - value, associated with the given |
||||||
|
* alias `alias`. If lookup was unsuccessful, it depends on `copyOnFailure` |
||||||
|
* flag: `copyOnFailure == false` means method will return empty `string` |
||||||
|
* and `copyOnFailure == true` means method will return `alias`. |
||||||
|
*/ |
||||||
|
public function string Resolve_S( |
||||||
|
string alias, |
||||||
|
optional bool copyOnFailure) |
||||||
|
{ |
||||||
|
local Text resultAsText; |
||||||
|
local Text aliasAsText; |
||||||
|
|
||||||
|
aliasAsText = _.text.FromString(alias); |
||||||
|
resultAsText = Resolve(aliasAsText, copyOnFailure); |
||||||
|
return _.text.IntoString(resultAsText); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Adds another alias to the caller `AliasSource`. |
||||||
|
* If alias with the same name as `aliasToAdd` already exists - method |
||||||
|
* overwrites it. |
||||||
|
* |
||||||
|
* Can fail iff `aliasToAdd` is an invalid alias or `aliasValue == none`. |
||||||
|
* |
||||||
|
* NOTE: having '$' prefix is considered to be invalid for `alias` by this |
||||||
|
* method. |
||||||
|
* |
||||||
|
* @param aliasToAdd Alias that you want to add to caller source. |
||||||
|
* Alias names are case-insensitive. |
||||||
|
* @param aliasValue Intended value of this alias. |
||||||
|
* @return `true` if alias was added and `false` otherwise (alias was invalid). |
||||||
|
*/ |
||||||
|
public function bool AddAlias(BaseText aliasToAdd, BaseText aliasValue); |
||||||
|
|
||||||
|
/** |
||||||
|
* Adds another alias to the caller `AliasSource`. |
||||||
|
* If alias with the same name as `aliasToAdd` already exists, - |
||||||
|
* method overwrites it. |
||||||
|
* |
||||||
|
* Can fail iff `aliasToAdd` is an invalid alias. |
||||||
|
* |
||||||
|
* NOTE: having '$' prefix is considered to be invalid for `alias` by this |
||||||
|
* method. |
||||||
|
* |
||||||
|
* @param aliasToAdd Alias that you want to add to caller source. |
||||||
|
* Alias names are case-insensitive. |
||||||
|
* @param aliasValue Intended value of this alias. |
||||||
|
* @return `true` if alias was added and `false` otherwise (alias was invalid). |
||||||
|
*/ |
||||||
|
public function bool AddAlias_S(string aliasToAdd, string aliasValue) |
||||||
|
{ |
||||||
|
local bool result; |
||||||
|
local Text aliasAsText, valueAsText; |
||||||
|
|
||||||
|
aliasAsText = _.text.FromString(aliasToAdd); |
||||||
|
valueAsText = _.text.FromString(aliasValue); |
||||||
|
result = AddAlias(aliasAsText, valueAsText); |
||||||
|
_.memory.Free(aliasAsText); |
||||||
|
_.memory.Free(valueAsText); |
||||||
|
return result; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Removes alias (all records with it, in case of duplicates) from |
||||||
|
* the caller `AliasSource`. |
||||||
|
* |
||||||
|
* NOTE: having '$' prefix is considered to be invalid for `alias` by this |
||||||
|
* method. |
||||||
|
* |
||||||
|
* @param aliasToRemove Alias that you want to remove from caller source. |
||||||
|
* @return `true` if an alias was present in the source and was deleted and |
||||||
|
* `false` if there was no specified alias in the first place. |
||||||
|
*/ |
||||||
|
public function bool RemoveAlias(BaseText aliasToRemove); |
||||||
|
|
||||||
|
/** |
||||||
|
* Removes alias (all records with it, in case of duplicates) from |
||||||
|
* the caller `AliasSource`. |
||||||
|
* |
||||||
|
* NOTE: having '$' prefix is considered to be invalid for `alias` by this |
||||||
|
* method. |
||||||
|
* |
||||||
|
* @param aliasToRemove Alias that you want to remove from caller source. |
||||||
|
* @return `true` if an alias was present in the source and was deleted and |
||||||
|
* `false` if there was no specified alias in the first place. |
||||||
|
*/ |
||||||
|
public function bool RemoveAlias_S(string aliasToRemove) |
||||||
|
{ |
||||||
|
local bool result; |
||||||
|
local Text aliasAsText; |
||||||
|
|
||||||
|
aliasAsText = _.text.FromString(aliasToRemove); |
||||||
|
result = RemoveAlias(aliasAsText); |
||||||
|
_.memory.Free(aliasAsText); |
||||||
|
return result; |
||||||
|
} |
||||||
|
|
||||||
|
defaultproperties |
||||||
|
{ |
||||||
|
} |
Loading…
Reference in new issue