From 71bbe926a086835a0c197393c36bdd24c6d383a2 Mon Sep 17 00:00:00 2001 From: Samuka-C <47865393+Samuka-C@users.noreply.github.com> Date: Wed, 15 Oct 2025 12:10:25 -0300 Subject: [PATCH] Add bank toolshed commands (#40614) * add bank commands * Follow convention * use protoId * make logic better * Move stuff to shared * Make things dirty * Move UpdateBankAccount to shared as well * nullable + resolve * Fix commands * make things less legible * typo * same typo * im dumb * I don't know how to spell * replace select with foreach Co-authored-by: Simon <63975668+Simyon264@users.noreply.github.com> * replace select with foreach again --------- Co-authored-by: Simon <63975668+Simyon264@users.noreply.github.com> --- Content.Server/Cargo/Systems/CargoSystem.cs | 50 ------ .../Station/Commands/BankCommand.cs | 93 +++++++++++ Content.Shared/Cargo/SharedCargoSystem.cs | 146 ++++++++++++++++++ .../en-US/commands/toolshed-commands.ftl | 10 ++ 4 files changed, 249 insertions(+), 50 deletions(-) create mode 100644 Content.Server/Station/Commands/BankCommand.cs diff --git a/Content.Server/Cargo/Systems/CargoSystem.cs b/Content.Server/Cargo/Systems/CargoSystem.cs index 18ae856fda..9f3a4d5bf3 100644 --- a/Content.Server/Cargo/Systems/CargoSystem.cs +++ b/Content.Server/Cargo/Systems/CargoSystem.cs @@ -1,20 +1,15 @@ using Content.Server.Cargo.Components; using Content.Server.DeviceLinking.Systems; using Content.Server.Popups; -using Content.Server.Shuttles.Systems; using Content.Server.Stack; using Content.Server.Station.Systems; using Content.Shared.Access.Systems; using Content.Shared.Administration.Logs; using Content.Server.Radio.EntitySystems; using Content.Shared.Cargo; -using Content.Shared.Cargo.Components; -using Content.Shared.Cargo.Prototypes; -using Content.Shared.CCVar; using Content.Shared.Containers.ItemSlots; using Content.Shared.Mobs.Components; using Content.Shared.Paper; -using JetBrains.Annotations; using Robust.Server.GameObjects; using Robust.Shared.Audio.Systems; using Robust.Shared.Configuration; @@ -76,49 +71,4 @@ public sealed partial class CargoSystem : SharedCargoSystem UpdateTelepad(frameTime); UpdateBounty(); } - - public void UpdateBankAccount( - Entity ent, - int balanceAdded, - ProtoId account, - bool dirty = true) - { - UpdateBankAccount( - ent, - balanceAdded, - new Dictionary, double> { {account, 1} }, - dirty: dirty); - } - - /// - /// Adds or removes funds from the . - /// - /// The station. - /// The amount of funds to add or remove. - /// The distribution between individual . - /// Whether to mark the bank account component as dirty. - [PublicAPI] - public void UpdateBankAccount( - Entity ent, - int balanceAdded, - Dictionary, double> accountDistribution, - bool dirty = true) - { - if (!Resolve(ent, ref ent.Comp)) - return; - - foreach (var (account, percent) in accountDistribution) - { - var accountBalancedAdded = (int) Math.Round(percent * balanceAdded); - ent.Comp.Accounts[account] += accountBalancedAdded; - } - - var ev = new BankBalanceUpdatedEvent(ent, ent.Comp.Accounts); - RaiseLocalEvent(ent, ref ev, true); - - if (!dirty) - return; - - Dirty(ent); - } } diff --git a/Content.Server/Station/Commands/BankCommand.cs b/Content.Server/Station/Commands/BankCommand.cs new file mode 100644 index 0000000000..c24cacdffb --- /dev/null +++ b/Content.Server/Station/Commands/BankCommand.cs @@ -0,0 +1,93 @@ +using System.Linq; +using Content.Server.Administration; +using Content.Server.Cargo.Systems; +using Content.Shared.Administration; +using Content.Shared.Cargo.Components; +using Content.Shared.Cargo.Prototypes; +using Robust.Shared.Prototypes; +using Robust.Shared.Toolshed; + +namespace Content.Server.Station.Commands; + +[ToolshedCommand, AdminCommand(AdminFlags.Admin)] +public sealed class BankCommand : ToolshedCommand +{ + private CargoSystem? _cargo; + + [CommandImplementation("accounts")] + public IEnumerable Accounts([PipedArgument] EntityUid station) + { + _cargo ??= GetSys(); + + foreach (var (account, _) in _cargo.GetAccounts(station)) + { + yield return new BankAccount(account.Id, station, _cargo, EntityManager); + } + } + + [CommandImplementation("accounts")] + public IEnumerable Accounts([PipedArgument] IEnumerable stations) + => stations.SelectMany(Accounts); + + [CommandImplementation("account")] + public BankAccount Account([PipedArgument] EntityUid station, ProtoId account) + { + _cargo ??= GetSys(); + + return new BankAccount(account.Id, station, _cargo, EntityManager); + } + + [CommandImplementation("account")] + public IEnumerable Account([PipedArgument] IEnumerable stations, ProtoId account) + => stations.Select(x => Account(x, account)); + + [CommandImplementation("adjust")] + public IEnumerable Adjust([PipedArgument] IEnumerable @ref, int by) + { + _cargo ??= GetSys(); + var bankAccounts = @ref.ToList(); + foreach (var bankAccount in bankAccounts.ToList()) + { + _cargo.TryAdjustBankAccount(bankAccount.Station, bankAccount.Account, by, true); + } + return bankAccounts; + } + + [CommandImplementation("set")] + public IEnumerable Set([PipedArgument] IEnumerable @ref, int by) + { + _cargo ??= GetSys(); + var bankAccounts = @ref.ToList(); + foreach (var bankAccount in bankAccounts.ToList()) + { + _cargo.TrySetBankAccount(bankAccount.Station, bankAccount.Account, by, true); + } + return bankAccounts; + } + + [CommandImplementation("amount")] + public IEnumerable Amount([PipedArgument] IEnumerable @ref) + { + _cargo ??= GetSys(); + return @ref.Select(bankAccount => (success: _cargo.TryGetAccount(bankAccount.Station, bankAccount.Account, out var money), money)) + .Where(result => result.success) + .Select(result => result.money); + } +} + +public readonly record struct BankAccount( + string Account, + Entity Station, + CargoSystem Cargo, + IEntityManager EntityManager) +{ + public override string ToString() + { + if (!Cargo.TryGetAccount(Station, Account, out var money)) + { + return $"{EntityManager.ToPrettyString(Station)} Account {Account} : (not a account)"; + } + + return $"{EntityManager.ToPrettyString(Station)} Account {Account} : {money}"; + } +} diff --git a/Content.Shared/Cargo/SharedCargoSystem.cs b/Content.Shared/Cargo/SharedCargoSystem.cs index 8925ce0de1..9d044d1850 100644 --- a/Content.Shared/Cargo/SharedCargoSystem.cs +++ b/Content.Shared/Cargo/SharedCargoSystem.cs @@ -1,5 +1,6 @@ using Content.Shared.Cargo.Components; using Content.Shared.Cargo.Prototypes; +using JetBrains.Annotations; using Robust.Shared.Prototypes; using Robust.Shared.Serialization; using Robust.Shared.Timing; @@ -55,6 +56,151 @@ public abstract class SharedCargoSystem : EntitySystem } return distribution; } + + /// + /// Returns information about the given bank account. + /// + /// Station to get bank account info from. + /// Bank account prototype ID to get info for. + /// The amount of money in the account + /// Whether or not the bank account exists. + public bool TryGetAccount(Entity station, ProtoId accountPrototypeId, out int money) + { + money = 0; + + if (!Resolve(station, ref station.Comp)) + return false; + + return station.Comp.Accounts.TryGetValue(accountPrototypeId, out money); + } + + /// + /// Returns a readonly dictionary of all accounts and their money info. + /// + /// Station to get bank account info from. + /// Whether or not the bank account exists. + public IReadOnlyDictionary, int> GetAccounts(Entity station) + { + if (!Resolve(station, ref station.Comp)) + return new Dictionary, int>(); + + return station.Comp.Accounts; + } + + /// + /// Attempts to adjust the money of a certain bank account. + /// + /// Station where the bank account is from + /// the id of the bank account + /// how much money to set the account to + /// Whether or not it should create the account if it doesn't exist. + /// Whether to mark the bank account component as dirty. + /// Whether or not setting the value succeeded. + public bool TryAdjustBankAccount( + Entity station, + ProtoId accountPrototypeId, + int money, + bool createAccount = false, + bool dirty = true) + { + if (!Resolve(station, ref station.Comp)) + return false; + + var accounts = station.Comp.Accounts; + + if (!accounts.ContainsKey(accountPrototypeId) && !createAccount) + return false; + + accounts[accountPrototypeId] += money; + var ev = new BankBalanceUpdatedEvent(station, station.Comp.Accounts); + RaiseLocalEvent(station, ref ev, true); + + if (!dirty) + return true; + + Dirty(station); + return true; + } + + /// + /// Attempts to set the money of a certain bank account. + /// + /// Station where the bank account is from + /// the id of the bank account + /// how much money to set the account to + /// Whether or not it should create the account if it doesn't exist. + /// Whether to mark the bank account component as dirty. + /// Whether or not setting the value succeeded. + public bool TrySetBankAccount( + Entity station, + ProtoId accountPrototypeId, + int money, + bool createAccount = false, + bool dirty = true) + { + if (!Resolve(station, ref station.Comp)) + return false; + + var accounts = station.Comp.Accounts; + + if (!accounts.ContainsKey(accountPrototypeId) && !createAccount) + return false; + + accounts[accountPrototypeId] = money; + var ev = new BankBalanceUpdatedEvent(station, station.Comp.Accounts); + RaiseLocalEvent(station, ref ev, true); + + if (!dirty) + return true; + + Dirty(station); + return true; + } + + public void UpdateBankAccount( + Entity ent, + int balanceAdded, + ProtoId account, + bool dirty = true) + { + UpdateBankAccount( + ent, + balanceAdded, + new Dictionary, double> { {account, 1} }, + dirty: dirty); + } + + /// + /// Adds or removes funds from the . + /// + /// The station. + /// The amount of funds to add or remove. + /// The distribution between individual . + /// Whether to mark the bank account component as dirty. + [PublicAPI] + public void UpdateBankAccount( + Entity ent, + int balanceAdded, + Dictionary, double> accountDistribution, + bool dirty = true) + { + if (!Resolve(ent, ref ent.Comp)) + return; + + foreach (var (account, percent) in accountDistribution) + { + var accountBalancedAdded = (int) Math.Round(percent * balanceAdded); + ent.Comp.Accounts[account] += accountBalancedAdded; + } + + var ev = new BankBalanceUpdatedEvent(ent, ent.Comp.Accounts); + RaiseLocalEvent(ent, ref ev, true); + + if (!dirty) + return; + + Dirty(ent); + } } [NetSerializable, Serializable] diff --git a/Resources/Locale/en-US/commands/toolshed-commands.ftl b/Resources/Locale/en-US/commands/toolshed-commands.ftl index 2e3c395198..218235338c 100644 --- a/Resources/Locale/en-US/commands/toolshed-commands.ftl +++ b/Resources/Locale/en-US/commands/toolshed-commands.ftl @@ -6,6 +6,16 @@ command-description-acmd-perms = Returns the admin permissions of the given command, if any. command-description-acmd-caninvoke = Check if the given player can invoke the given command. +command-description-bank-accounts = + Returns all accounts on a station. +command-description-bank-account = + Returns a given bank account from a station. +command-description-bank-adjust = + Adjusts the money for the given bank account. +command-description-bank-set = + Sets the money for the given bank account. +command-description-bank-amount = + Returns the money for the given bank account. command-description-jobs-jobs = Returns all jobs on a station. command-description-jobs-job =