dkanus
2 years ago
4 changed files with 228 additions and 0 deletions
@ -0,0 +1,193 @@
|
||||
/** |
||||
* Author: dkanus |
||||
* Home repo: https://www.insultplayers.ru/git/AcediaFramework/AcediaCore |
||||
* License: GPL |
||||
* Copyright 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 ACommandSideEffects extends Command; |
||||
|
||||
// Maps `UserID` to `ArrayList` with side effects listed for that player last time |
||||
var private HashTable displayedLists; |
||||
|
||||
protected function Constructor() { |
||||
super.Constructor(); |
||||
displayedLists = _.collections.EmptyHashTable(); |
||||
} |
||||
|
||||
protected function Finalizer() { |
||||
super.Finalizer(); |
||||
_.memory.Free(displayedLists); |
||||
displayedLists = none; |
||||
} |
||||
|
||||
protected function BuildData(CommandDataBuilder builder) { |
||||
builder.Name(P("sideeffects")); |
||||
builder.Group(P("core")); |
||||
builder.Summary(P("Displays information about current side effects.")); |
||||
builder.Describe(P("This command allows to display current side effects, optionally filtering" |
||||
@ "them by specified package names.")); |
||||
builder.OptionalParams(); |
||||
builder.ParamTextList(P("package_names")); |
||||
|
||||
builder.SubCommand(P("show")); |
||||
builder.Describe(P("This sub-command is only usable after side effects have been shown" |
||||
@ "at least once. It takes an index from the last displayed list and displays a verbose" |
||||
@ "information about it.")); |
||||
builder.ParamInteger(P("side_effect_number")); |
||||
|
||||
builder.Option(P("verbose")); |
||||
builder.Describe(P("Display verbose information about each side effect.")); |
||||
} |
||||
|
||||
protected function Executed(CallData arguments, EPlayer instigator) { |
||||
local UserID playerID; |
||||
local array<SideEffect> relevantSideEffects; |
||||
local ArrayList packagesList, storedSideEffectsList; |
||||
|
||||
playerID = instigator.GetUserID(); |
||||
if (arguments.subCommandName.IsEmpty()) { |
||||
relevantSideEffects = _.sideEffects.GetAll(); |
||||
packagesList = arguments.parameters.GetArrayList(P("package_names")); |
||||
FilterSideEffects(/*out*/ relevantSideEffects, packagesList); |
||||
_.memory.Free(packagesList); |
||||
DisplaySideEffects(relevantSideEffects, arguments.options.HasKey(P("verbose"))); |
||||
// Store new side effect list |
||||
storedSideEffectsList = _.collections.NewArrayList(relevantSideEffects); |
||||
displayedLists.SetItem(playerID, storedSideEffectsList); |
||||
_.memory.FreeMany(relevantSideEffects); |
||||
_.memory.Free(storedSideEffectsList); |
||||
} else { |
||||
ShowInfoFor(playerID, arguments.parameters.GetInt(P("side_effect_number"))); |
||||
} |
||||
_.memory.Free(playerID); |
||||
} |
||||
|
||||
private function FilterSideEffects(out array<SideEffect> sideEffects, ArrayList allowedPackages) { |
||||
local int i, j; |
||||
local int packagesLength; |
||||
local bool matchedPackage; |
||||
local Text nextSideEffectPackage, nextAllowedPackage; |
||||
|
||||
if (allowedPackages == none) return; |
||||
if (allowedPackages.GetLength() <= 0) return; |
||||
|
||||
packagesLength = allowedPackages.GetLength(); |
||||
while (i < sideEffects.length) { |
||||
nextSideEffectPackage = sideEffects[i].GetPackage(); |
||||
matchedPackage = false; |
||||
for (j = 0; j < packagesLength; j += 1) { |
||||
nextAllowedPackage = allowedPackages.GetText(j); |
||||
if (nextAllowedPackage.Compare(nextSideEffectPackage, SCASE_INSENSITIVE)) { |
||||
matchedPackage = true; |
||||
_.memory.Free(nextAllowedPackage); |
||||
break; |
||||
} |
||||
_.memory.Free(nextAllowedPackage); |
||||
} |
||||
if (!matchedPackage) { |
||||
sideEffects.Remove(i, 1); |
||||
} else { |
||||
i += 1; |
||||
} |
||||
_.memory.Free(nextSideEffectPackage); |
||||
} |
||||
} |
||||
|
||||
private function DisplaySideEffects(array<SideEffect> toDisplay, bool verbose) { |
||||
local int i; |
||||
local MutableText nextPrefix; |
||||
|
||||
if (toDisplay.length <= 0) { |
||||
callerConsole.Write(F("List of side effects is {$TextNeutral empty}.")); |
||||
} |
||||
for (i = 0; i < toDisplay.length; i += 1) { |
||||
nextPrefix = _.text.FromIntM(i + 1); |
||||
nextPrefix.Append(P(".")); |
||||
DisplaySideEffect(toDisplay[i], nextPrefix, verbose); |
||||
_.memory.Free(nextPrefix); |
||||
} |
||||
} |
||||
|
||||
private function DisplaySideEffect(SideEffect toDisplay, BaseText prefix, bool verbose) { |
||||
local Text effectName, effectDescription, effectPackage, effectSource, effectStatus; |
||||
|
||||
if (toDisplay == none) { |
||||
return; |
||||
} |
||||
if (prefix != none) { |
||||
callerConsole.Write(prefix); |
||||
callerConsole.Write(P(" ")); |
||||
} |
||||
effectName = toDisplay.GetName(); |
||||
effectPackage = toDisplay.GetPackage(); |
||||
effectSource = toDisplay.GetSource(); |
||||
effectStatus = toDisplay.GetStatus(); |
||||
callerConsole.UseColor(_.color.TextEmphasis); |
||||
callerConsole.Write(P("[")); |
||||
callerConsole.Write(effectPackage); |
||||
callerConsole.Write(P(" \\ ")); |
||||
callerConsole.Write(effectSource); |
||||
callerConsole.Write(P("] ")); |
||||
callerConsole.ResetColor(); |
||||
callerConsole.Write(effectName); |
||||
callerConsole.Write(P(" {")); |
||||
callerConsole.Write(effectStatus); |
||||
callerConsole.WriteLine(P("}")); |
||||
if (verbose) { |
||||
effectDescription = toDisplay.GetDescription(); |
||||
callerConsole.WriteBlock(effectDescription); |
||||
} |
||||
_.memory.Free5(effectName, effectDescription, effectPackage, effectSource, effectStatus); |
||||
} |
||||
|
||||
private function ShowInfoFor(UserID playerID, int sideEffectIndex) { |
||||
local SideEffect toDisplay; |
||||
local ArrayList sideEffectList; |
||||
|
||||
if (playerID == none) { |
||||
return; |
||||
} |
||||
if (sideEffectIndex <= 0) { |
||||
callerConsole.WriteLine(F("Specified side effect index {$TextNegative isn't positive}!")); |
||||
return; |
||||
} |
||||
sideEffectList = displayedLists.GetArrayList(playerID); |
||||
if (sideEffectList == none) { |
||||
callerConsole.WriteLine(F("{$TextNegative Cannot display} side effect by index without" |
||||
@ "first listing them. Call {$TextEmphasis sideeffects} command without" |
||||
@ "{$TextEmphasis show} subcommand first.")); |
||||
return; |
||||
} |
||||
if (sideEffectIndex > sideEffectList.GetLength()) { |
||||
callerConsole.WriteLine(F("Specified side effect index is {$TextNegative out of bounds}.")); |
||||
_.memory.Free(sideEffectList); |
||||
return; |
||||
} |
||||
// Above we checked that `sideEffectIndex` lies within `[0; sideEffectList.GetLength()]` segment |
||||
// This means that `sideEffectIndex - 1` points at non-`none` value |
||||
toDisplay = SideEffect(sideEffectList.GetItem(sideEffectIndex - 1)); |
||||
if (!_.sideEffects.IsRegistered(toDisplay)) { |
||||
callerConsole.UseColorOnce(_.color.TextWarning); |
||||
callerConsole.WriteLine(P("Selected side effect is no longer active!")); |
||||
} |
||||
DisplaySideEffect(toDisplay, none, true); |
||||
_.memory.Free2(toDisplay, sideEffectList); |
||||
} |
||||
|
||||
defaultproperties { |
||||
} |
Loading…
Reference in new issue