From 62ea3e50e6d85287f2d8049fc165c9b6da9cf664 Mon Sep 17 00:00:00 2001 From: Anton Tarasenko Date: Wed, 29 Jun 2022 20:06:29 +0700 Subject: [PATCH] Change feature command to use announcer --- sources/CommandAnnouncer.uc | 43 +++- sources/Commands/ACommandFeature.uc | 221 +++++++---------- sources/Commands/ACommandFeature_Announcer.uc | 224 ++++++++++++++++++ 3 files changed, 338 insertions(+), 150 deletions(-) create mode 100644 sources/Commands/ACommandFeature_Announcer.uc diff --git a/sources/CommandAnnouncer.uc b/sources/CommandAnnouncer.uc index 28b2406..b0817b7 100644 --- a/sources/CommandAnnouncer.uc +++ b/sources/CommandAnnouncer.uc @@ -129,22 +129,24 @@ public final function Setup( ConsoleWriter newPublicConsole) { target = none; + _.memory.Free(targetName); + targetName = none; if (newTarget != none && newTarget.IsAllocated()) { target = newTarget; targetLifeVersion = newTarget.GetLifeVersion(); - _.memory.Free(targetName); targetName = target .GetName() .IntoMutableText() .ChangeDefaultColor(_.color.Gray); } instigator = none; + _.memory.Free(instigatorName); + instigatorName = none; if (newInstigator != none && newInstigator.IsAllocated()) { instigator = newInstigator; instigatorLifeVersion = newInstigator.GetLifeVersion(); - _.memory.Free(instigatorName); instigatorName = instigator .GetName() .IntoMutableText() @@ -168,11 +170,11 @@ protected final function MakeAnnouncement(AnnouncementVariations variations) local ConsoleWriter instigatorConsole, targetConsole; if (!variations.initialized) return; - if (!AreClassesValid()) return; + if (!ValidateClasses()) return; instigatorConsole = _.console.For(instigator); targetConsole = _.console.For(target); - if (instigator.SameAs(target)) + if (target == none || instigator.SameAs(target)) { // If instigator is targeting himself, then there is no need for // a separate announcement to target @@ -218,24 +220,39 @@ protected final function array MakeArray( { local array result; - result[result.length] = variations.toSelfReport; - result[result.length] = variations.toSelfPublic; - result[result.length] = variations.toOtherReport; - result[result.length] = variations.toOtherPrivate; - result[result.length] = variations.toOtherPublic; + if (variations.toSelfReport != none) { + result[result.length] = variations.toSelfReport; + } + if (variations.toSelfPublic != none) { + result[result.length] = variations.toSelfPublic; + } + if (variations.toOtherReport != none) { + result[result.length] = variations.toOtherReport; + } + if (variations.toOtherPrivate != none) { + result[result.length] = variations.toOtherPrivate; + } + if (variations.toOtherPublic != none) { + result[result.length] = variations.toOtherPublic; + } return result; } -private final function bool AreClassesValid() +private final function bool ValidateClasses() { if (instigator == none) return false; - if (target == none) return false; if (publicConsole == none) return false; if (instigator.GetLifeVersion() != instigatorLifeVersion) return false; - if (target.GetLifeVersion() != targetLifeVersion) return false; if (!instigator.IsExistent()) return false; - if (!target.IsExistent()) return false; + if (target != none) + { + if ( target.GetLifeVersion() != targetLifeVersion + || !target.IsExistent()) + { + target = none; + } + } if (publicConsole.GetLifeVersion() != publicConsoleLifeVersion) { return false; } diff --git a/sources/Commands/ACommandFeature.uc b/sources/Commands/ACommandFeature.uc index ab7fe96..7e66779 100644 --- a/sources/Commands/ACommandFeature.uc +++ b/sources/Commands/ACommandFeature.uc @@ -22,6 +22,14 @@ class ACommandFeature extends Command; // TODO: autoconf, newconf, deleteconf, setconf // TODO: when displaying features - display which one is enabled +var private ACommandFeature_Announcer announcer; + +protected function Finalizer() +{ + _.memory.Free(announcer); + super.Finalizer(); +} + protected function BuildData(CommandDataBuilder builder) { builder.Name(P("feature")).Summary(P("Managing features.")) @@ -34,174 +42,116 @@ protected function BuildData(CommandDataBuilder builder) builder.SubCommand(P("disable")) .ParamText(P("feature")) .Describe(P("Disables specified .")); + announcer = ACommandFeature_Announcer( + _.memory.Allocate(class'ACommandFeature_Announcer')); } -protected function Executed(CallData result, EPlayer callerPlayer) +protected function Executed(CallData arguments, EPlayer instigator) { - if (result.subCommandName.IsEmpty()) { + announcer.Setup(none, instigator, othersConsole); + if (arguments.subCommandName.IsEmpty()) { ShowAllFeatures(); } - else if (result.subCommandName.Compare(P("enable"))) + else if (arguments.subCommandName.Compare(P("enable"))) { - TryEnableFeature( - callerPlayer, - result.parameters.GetText(P("feature")), - result.parameters.GetText(P("config"))); + EnableFeature( + arguments.parameters.GetText(P("feature")), + arguments.parameters.GetText(P("config"))); } - else if (result.subCommandName.Compare(P("disable"))) { - DisableFeature(callerPlayer, result.parameters.GetText(P("feature"))); + else if (arguments.subCommandName.Compare(P("disable"))) { + DisableFeature(arguments.parameters.GetText(P("feature"))); } } -protected function TryEnableFeature( - EPlayer callerPlayer, - BaseText featureName, - BaseText chosenConfig) +protected function EnableFeature(BaseText featureName, BaseText configParameter) { - local Text oldConfig, newConfig; - local class featureClass; - local class configClass; - featureClass = LoadFeatureClass(featureName); - if (featureClass == none) return; - configClass = featureClass.default.configClass; - if (configClass == none) return; + local bool wasEnabled; + local Text oldConfig, newConfig; + local Feature instance; + local class featureClass; - if (chosenConfig == none) { - newConfig = configClass.static.GetAutoEnabledConfig(); - } - else if (!configClass.static.Exists(chosenConfig)) - { - callerConsole - .Write(P("Specified config \"")) - .Write(chosenConfig) - .WriteLine(F("\" {$TextFailure doesn't exist}")); - return; - } - else { - newConfig = chosenConfig.Copy(); - } - if (newConfig == none) - { - callerConsole - .Write(F("{$TextFailue No config specified} and" - @ "{$TextFailure no auto-enabled config} exists for feature ")) - .UseColorOnce(_.color.TextEmphasis) - .WriteLine(newConfig); - _.memory.Free(newConfig); + featureClass = LoadFeatureClass(featureName); + if (featureClass == none) { return; } + wasEnabled = featureClass.static.IsEnabled(); oldConfig = featureClass.static.GetCurrentConfig(); - if (oldConfig != none && oldConfig.Compare(chosenConfig, SCASE_INSENSITIVE)) + newConfig = GetConfigFromParameter(configParameter, featureClass); + // Already enabled with the same config! + if (oldConfig != none && oldConfig.Compare(newConfig, SCASE_INSENSITIVE)) { - callerConsole - .Write(P("Config ")) - .Write(chosenConfig) - .WriteLine(P(" is already enabled")); - _.memory.Free(oldConfig); + announcer.AnnounceFailedAlreadyEnabled(featureClass, newConfig); _.memory.Free(newConfig); + _.memory.Free(oldConfig); return; } - EnableFeature( - callerPlayer, - featureClass, - configClass, - newConfig, - chosenConfig == none); + // Try enabling and report the result + instance = featureClass.static.EnableMe(newConfig); + if (instance == none) { + announcer.AnnounceFailedCannotEnableFeature(featureClass, newConfig); + } + else if (wasEnabled) { + announcer.AnnounceSwappedConfig(featureClass, oldConfig, newConfig); + } + else { + announcer.AnnounceEnabledFeature(featureClass, newConfig); + } _.memory.Free(newConfig); _.memory.Free(oldConfig); } -protected function EnableFeature( - EPlayer callerPlayer, - class featureClass, - class configClass, - BaseText chosenConfig, - bool autoConfig) +protected function DisableFeature(Text featureName) { - local bool wasEnabled; - local Feature instance; - local Text featureName, callerName; - if (callerPlayer == none) return; - if (featureClass == none) return; - if (configClass == none) return; + local class featureClass; - callerName = callerPlayer.GetName(); - featureName = _.text.FromClass(featureClass); - wasEnabled = featureClass.static.IsEnabled(); - instance = featureClass.static.EnableMe(chosenConfig); - if (instance == none) - { - callerConsole.Write(F("Something went {$TextFailure wrong}," - @ "{$TextFailure failed} to enabled feature")) - .UseColorOnce(_.color.TextEmphasis).WriteLine(featureName); + featureClass = LoadFeatureClass(featureName); + if (featureClass == none) { + return; } - else if (wasEnabled) + if (!featureClass.static.IsEnabled()) { - callerConsole - .Write(P("Swapping config for the feature ")) - .UseColorOnce(_.color.TextEmphasis).Write(featureName) - .Write(P(" to \"")).Write(chosenConfig).WriteLine(P("\"")); - othersConsole - .Write(callerName) - .Write(P(" swapped config for the feature ")) - .UseColorOnce(_.color.TextEmphasis).Write(featureName) - .Write(P(" to \"")).Write(chosenConfig).WriteLine(P("\"")); + announcer.AnnounceFailedAlreadyDisabled(featureClass); + return; } - else - { - callerConsole - .Write(P("Enabling feature ")) - .UseColorOnce(_.color.TextEmphasis).Write(featureName) - .Write(P(" with config \"")).Write(chosenConfig).WriteLine(P("\"")); - othersConsole - .Write(callerName) - .Write(P(" enabled feature ")) - .UseColorOnce(_.color.TextEmphasis).Write(featureName) - .Write(P(" with config \"")).Write(chosenConfig).WriteLine(P("\"")); + featureClass.static.DisableMe(); + // It is possible that this command itself is destroyed after above command + // so do the check just in case + if (IsAllocated()) { + announcer.AnnounceDisabledFeature(featureClass); } - _.memory.Free(callerName); - _.memory.Free(featureName); } -protected function DisableFeature(EPlayer callerPlayer, Text featureName) +protected function Text GetConfigFromParameter( + BaseText configParameter, + class featureClass) { - local Text playerName; - local Text featureRealName; - local class featureClass; - - featureClass = LoadFeatureClass(featureName); - if (featureClass == none) return; - if (callerPlayer == none) return; + local Text resolvedConfig; + local class configClass; - featureRealName = _.text.FromClass(featureClass); - playerName = callerPlayer.GetName(); - if (!featureClass.static.IsEnabled()) + if (featureClass == none) { + return none; + } + configClass = featureClass.default.configClass; + if (configClass == none) { - callerConsole - .Write(P("Feature ")) - .UseColorOnce(_.color.TextEmphasis).Write(featureRealName) - .WriteLine(F(" is already {$TextNegative disabled}")); - _.memory.Free(featureRealName); - _.memory.Free(playerName); - return; + announcer.AnnounceFailedNoConfigClass(featureClass); + return none; } - featureClass.static.DisableMe(); - // It is possible that this command itself is destroyed after above command - // so do the check just in case - if (IsAllocated()) + // If config was specified - simply check that it exists + if (configParameter != none) { - callerConsole - .Write(P("Feature ")) - .UseColorOnce(_.color.TextEmphasis).Write(featureRealName) - .WriteLine(F(" is {$TextNegative disabled}")); - othersConsole - .Write(playerName) - .Write(F(" {$TextNegative disabled} feature ")) - .UseColorOnce(_.color.TextEmphasis).WriteLine(featureRealName); + if (configClass.static.Exists(configParameter)) { + return configParameter.Copy(); + } + announcer.AnnounceFailedConfigMissing(configParameter); + return none; } - // `_` might be gone here - __().memory.Free(featureRealName); - __().memory.Free(playerName); + // If it wasn't specified - try auto config instead + resolvedConfig = configClass.static.GetAutoEnabledConfig(); + if (resolvedConfig == none) { + announcer.AnnounceFailedNoConfigProvided(featureClass); + } + return resolvedConfig; } protected function class LoadFeatureClass(BaseText featureName) @@ -218,12 +168,8 @@ protected function class LoadFeatureClass(BaseText featureName) featureClassName = featureName.Copy(); } featureClass = class(_.memory.LoadClass(featureClassName)); - if (featureClass == none) - { - callerConsole - .Write(F("{$TextFailure Failed} to load feature `")) - .Write(featureName) - .WriteLine(P("`")); + if (featureClass == none) { + announcer.AnnounceFailedToLoadFeatureClass(featureName); } _.memory.Free(featureClassName); return featureClass; @@ -247,6 +193,7 @@ protected function ShowFeature(class feature) local ReportTool reportTool; local array availableConfigs; local class configClass; + if (feature == none) { return; } diff --git a/sources/Commands/ACommandFeature_Announcer.uc b/sources/Commands/ACommandFeature_Announcer.uc new file mode 100644 index 0000000..e220c8a --- /dev/null +++ b/sources/Commands/ACommandFeature_Announcer.uc @@ -0,0 +1,224 @@ +/** + * Announcer for `ACommandFeature`. + * 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 . + */ +class ACommandFeature_Announcer extends CommandAnnouncer; + +var private AnnouncementVariations enabledFeature, disabledFeature; +var private AnnouncementVariations swappedConfig; +var private AnnouncementVariations failedToLoadFeatureClass; +var private AnnouncementVariations failedNoConfigProvided, failedConfigMissing; +var private AnnouncementVariations failedCannotEnableFeature; +var private AnnouncementVariations failedNoConfigClass; +var private AnnouncementVariations failedAlreadyEnabled, failedAlreadyDisabled; + +protected function Finalizer() +{ + FreeVariations(enabledFeature); + FreeVariations(disabledFeature); + FreeVariations(swappedConfig); + FreeVariations(failedToLoadFeatureClass); + FreeVariations(failedNoConfigProvided); + FreeVariations(failedConfigMissing); + FreeVariations(failedCannotEnableFeature); + FreeVariations(failedNoConfigClass); + FreeVariations(failedAlreadyEnabled); + FreeVariations(failedAlreadyDisabled); + super.Finalizer(); +} + +public final function AnnounceEnabledFeature( + class featureClass, + BaseText configName) +{ + local int i; + local array templates; + + if (!enabledFeature.initialized) + { + enabledFeature.initialized = true; + enabledFeature.toSelfReport = _.text.MakeTemplate_S( + "Feature {$TextEmphasis `%1`} {$TextPositive enabled} with config" + @ "\"%2\""); + enabledFeature.toSelfPublic = _.text.MakeTemplate_S( + "%%instigator%% {$TextPositive enabled} feature" + @ "{$TextEmphasis `%1`} with config \"%2\""); + } + templates = MakeArray(enabledFeature); + for (i = 0; i < templates.length; i += 1) { + templates[i].Reset().ArgClass(featureClass).Arg(configName); + } + MakeAnnouncement(enabledFeature); +} + +public final function AnnounceDisabledFeature(class featureClass) +{ + local int i; + local array templates; + + if (!disabledFeature.initialized) + { + disabledFeature.initialized = true; + disabledFeature.toSelfReport = _.text.MakeTemplate_S( + "Feature {$TextEmphasis `%1`} {$TextNegative disabled}"); + disabledFeature.toSelfPublic = _.text.MakeTemplate_S( + "%%instigator%% {$TextNegative disabled} feature" + @ "{$TextEmphasis `%1`}"); + } + templates = MakeArray(disabledFeature); + for (i = 0; i < templates.length; i += 1) { + templates[i].Reset().ArgClass(featureClass); + } + MakeAnnouncement(disabledFeature); +} + +public final function AnnounceSwappedConfig( + class featureClass, + BaseText oldConfig, + BaseText newConfig) +{ + local int i; + local array templates; + + if (!swappedConfig.initialized) + { + swappedConfig.initialized = true; + swappedConfig.toSelfReport = _.text.MakeTemplate_S( + "Config for feature {$TextEmphasis `%1`} {$TextNeutral swapped}" + @ "from \"%2\" to \"%3\""); + swappedConfig.toSelfPublic = _.text.MakeTemplate_S( + "%%instigator%% {$TextNeutral swapped} config for feature" + @ "{$TextEmphasis `%1`} from \"%2\" to \"%3\""); + } + templates = MakeArray(swappedConfig); + for (i = 0; i < templates.length; i += 1) + { + templates[i] + .Reset() + .ArgClass(featureClass) + .Arg(oldConfig) + .Arg(newConfig); + } + MakeAnnouncement(swappedConfig); +} + +public final function AnnounceFailedToLoadFeatureClass(BaseText failedClassName) +{ + if (!failedToLoadFeatureClass.initialized) + { + failedToLoadFeatureClass.initialized = true; + failedToLoadFeatureClass.toSelfReport = _.text.MakeTemplate_S( + "{$TextFailure Failed} to load feature class {$TextEmphasis `%1`}"); + } + failedToLoadFeatureClass.toSelfReport.Reset().Arg(failedClassName); + MakeAnnouncement(failedToLoadFeatureClass); +} + +public final function AnnounceFailedNoConfigProvided( + class featureClass) +{ + if (!failedNoConfigProvided.initialized) + { + failedNoConfigProvided.initialized = true; + failedNoConfigProvided.toSelfReport = _.text.MakeTemplate_S( + "{$TextFailue No config specified} and {$TextFailure no" + @ "auto-enabled config} exists for feature {$TextEmphasis `%1`}"); + } + failedNoConfigProvided.toSelfReport.Reset().ArgClass(featureClass); + MakeAnnouncement(failedNoConfigProvided); +} + +public final function AnnounceFailedConfigMissing(BaseText config) +{ + if (!failedConfigMissing.initialized) + { + failedConfigMissing.initialized = true; + failedConfigMissing.toSelfReport = _.text.MakeTemplate_S( + "Specified config \"%1\" {$TextFailue doesn't exist}"); + } + failedConfigMissing.toSelfReport.Reset().Arg(config); + MakeAnnouncement(failedConfigMissing); +} + +public final function AnnounceFailedCannotEnableFeature( + class featureClass, + BaseText config) +{ + if (!failedCannotEnableFeature.initialized) + { + failedCannotEnableFeature.initialized = true; + failedCannotEnableFeature.toSelfReport = _.text.MakeTemplate_S( + "Something went {$TextFailure wrong}, {$TextFailure failed} to" + @ "enable feature {$TextEmphasis `%1`} with config \"%2\""); + } + failedCannotEnableFeature.toSelfReport + .Reset() + .ArgClass(featureClass) + .Arg(config); + MakeAnnouncement(failedCannotEnableFeature); +} + +public final function AnnounceFailedNoConfigClass( + class featureClass) +{ + if (!failedNoConfigClass.initialized) + { + failedNoConfigClass.initialized = true; + failedNoConfigClass.toSelfReport = _.text.MakeTemplate_S( + "Feature {$TextEmphasis `%1`} {$TextFailure does not have config" + @ "class}! This is most likely caused by its faulty" + @ "implementation"); + } + failedNoConfigClass.toSelfReport.Reset().ArgClass(featureClass); + MakeAnnouncement(failedNoConfigClass); +} + +public final function AnnounceFailedAlreadyDisabled( + class featureClass) +{ + if (!failedAlreadyDisabled.initialized) + { + failedAlreadyDisabled.initialized = true; + failedAlreadyDisabled.toSelfReport = _.text.MakeTemplate_S( + "Feature {$TextEmphasis `%1`} is already {$TextNegative disabled}"); + } + failedAlreadyDisabled.toSelfReport.Reset().ArgClass(featureClass); + MakeAnnouncement(failedAlreadyDisabled); +} + +public final function AnnounceFailedAlreadyEnabled( + class featureClass, + BaseText config) +{ + if (!failedAlreadyEnabled.initialized) + { + failedAlreadyEnabled.initialized = true; + failedAlreadyEnabled.toSelfReport = _.text.MakeTemplate_S( + "Feature {$TextEmphasis `%1`} is already {$TextNegative enabled}" + @ "with specified config \"%2\""); + } + failedAlreadyEnabled.toSelfReport + .Reset() + .ArgClass(featureClass) + .Arg(config); + MakeAnnouncement(failedAlreadyEnabled); +} + +defaultproperties +{ +} \ No newline at end of file