]> git.smokeofanarchy.ru Git - space-station-14.git/commitdiff
Add bank toolshed commands (#40614)
authorSamuka-C <47865393+Samuka-C@users.noreply.github.com>
Wed, 15 Oct 2025 15:10:25 +0000 (12:10 -0300)
committerGitHub <noreply@github.com>
Wed, 15 Oct 2025 15:10:25 +0000 (15:10 +0000)
* 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
Content.Server/Station/Commands/BankCommand.cs [new file with mode: 0644]
Content.Shared/Cargo/SharedCargoSystem.cs
Resources/Locale/en-US/commands/toolshed-commands.ftl

index 18ae856fda353b7f5ba5989aca4f268bcbcd7b04..9f3a4d5bf3a3a520d4f0730bfead2c14fb55361d 100644 (file)
@@ -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<StationBankAccountComponent?> ent,
-        int balanceAdded,
-        ProtoId<CargoAccountPrototype> account,
-        bool dirty = true)
-    {
-        UpdateBankAccount(
-            ent,
-            balanceAdded,
-            new Dictionary<ProtoId<CargoAccountPrototype>, double> { {account, 1} },
-            dirty: dirty);
-    }
-
-    /// <summary>
-    /// Adds or removes funds from the <see cref="StationBankAccountComponent"/>.
-    /// </summary>
-    /// <param name="ent">The station.</param>
-    /// <param name="balanceAdded">The amount of funds to add or remove.</param>
-    /// <param name="accountDistribution">The distribution between individual <see cref="CargoAccountPrototype"/>.</param>
-    /// <param name="dirty">Whether to mark the bank account component as dirty.</param>
-    [PublicAPI]
-    public void UpdateBankAccount(
-        Entity<StationBankAccountComponent?> ent,
-        int balanceAdded,
-        Dictionary<ProtoId<CargoAccountPrototype>, 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 (file)
index 0000000..c24cacd
--- /dev/null
@@ -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<BankAccount> Accounts([PipedArgument] EntityUid station)
+    {
+        _cargo ??= GetSys<CargoSystem>();
+
+        foreach (var (account, _) in _cargo.GetAccounts(station))
+        {
+            yield return new BankAccount(account.Id, station, _cargo, EntityManager);
+        }
+    }
+
+    [CommandImplementation("accounts")]
+    public IEnumerable<BankAccount> Accounts([PipedArgument] IEnumerable<EntityUid> stations)
+        => stations.SelectMany(Accounts);
+
+    [CommandImplementation("account")]
+    public BankAccount Account([PipedArgument] EntityUid station, ProtoId<CargoAccountPrototype> account)
+    {
+        _cargo ??= GetSys<CargoSystem>();
+
+        return new BankAccount(account.Id, station, _cargo, EntityManager);
+    }
+
+    [CommandImplementation("account")]
+    public IEnumerable<BankAccount> Account([PipedArgument] IEnumerable<EntityUid> stations, ProtoId<CargoAccountPrototype> account)
+        => stations.Select(x => Account(x, account));
+
+    [CommandImplementation("adjust")]
+    public IEnumerable<BankAccount> Adjust([PipedArgument] IEnumerable<BankAccount> @ref, int by)
+    {
+        _cargo ??= GetSys<CargoSystem>();
+        var bankAccounts = @ref.ToList();
+        foreach (var bankAccount in bankAccounts.ToList())
+        {
+            _cargo.TryAdjustBankAccount(bankAccount.Station, bankAccount.Account, by, true);
+        }
+        return bankAccounts;
+    }
+
+    [CommandImplementation("set")]
+    public IEnumerable<BankAccount> Set([PipedArgument] IEnumerable<BankAccount> @ref, int by)
+    {
+        _cargo ??= GetSys<CargoSystem>();
+        var bankAccounts = @ref.ToList();
+        foreach (var bankAccount in bankAccounts.ToList())
+        {
+            _cargo.TrySetBankAccount(bankAccount.Station, bankAccount.Account, by, true);
+        }
+        return bankAccounts;
+    }
+
+    [CommandImplementation("amount")]
+    public IEnumerable<int> Amount([PipedArgument] IEnumerable<BankAccount> @ref)
+    {
+        _cargo ??= GetSys<CargoSystem>();
+        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<StationBankAccountComponent?> 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}";
+    }
+}
index 8925ce0de14d7246d9962e9728124ebeed84c8b3..9d044d18506ef35db15ce43dff8de7f4fce24930 100644 (file)
@@ -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;
     }
+
+    /// <summary>
+    /// Returns information about the given bank account.
+    /// </summary>
+    /// <param name="station">Station to get bank account info from.</param>
+    /// <param name="accountPrototypeId">Bank account prototype ID to get info for.</param>
+    /// <param name="money">The amount of money in the account</param>
+    /// <returns>Whether or not the bank account exists.</returns>
+    public bool TryGetAccount(Entity<StationBankAccountComponent?> station, ProtoId<CargoAccountPrototype> accountPrototypeId, out int money)
+    {
+        money = 0;
+
+        if (!Resolve(station, ref station.Comp))
+            return false;
+
+        return station.Comp.Accounts.TryGetValue(accountPrototypeId, out money);
+    }
+
+    /// <summary>
+    /// Returns a readonly dictionary of all accounts and their money info.
+    /// </summary>
+    /// <param name="station">Station to get bank account info from.</param>
+    /// <returns>Whether or not the bank account exists.</returns>
+    public IReadOnlyDictionary<ProtoId<CargoAccountPrototype>, int> GetAccounts(Entity<StationBankAccountComponent?> station)
+    {
+        if (!Resolve(station, ref station.Comp))
+            return new Dictionary<ProtoId<CargoAccountPrototype>, int>();
+
+        return station.Comp.Accounts;
+    }
+
+    /// <summary>
+    /// Attempts to adjust the money of a certain bank account.
+    /// </summary>
+    /// <param name="station">Station where the bank account is from</param>
+    /// <param name="accountPrototypeId">the id of the bank account</param>
+    /// <param name="money">how much money to set the account to</param>
+    /// <param name="createAccount">Whether or not it should create the account if it doesn't exist.</param>
+    /// <param name="dirty">Whether to mark the bank account component as dirty.</param>
+    /// <returns>Whether or not setting the value succeeded.</returns>
+    public bool TryAdjustBankAccount(
+        Entity<StationBankAccountComponent?> station,
+        ProtoId<CargoAccountPrototype> 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;
+    }
+
+    /// <summary>
+    /// Attempts to set the money of a certain bank account.
+    /// </summary>
+    /// <param name="station">Station where the bank account is from</param>
+    /// <param name="accountPrototypeId">the id of the bank account</param>
+    /// <param name="money">how much money to set the account to</param>
+    /// <param name="createAccount">Whether or not it should create the account if it doesn't exist.</param>
+    /// <param name="dirty">Whether to mark the bank account component as dirty.</param>
+    /// <returns>Whether or not setting the value succeeded.</returns>
+    public bool TrySetBankAccount(
+        Entity<StationBankAccountComponent?> station,
+        ProtoId<CargoAccountPrototype> 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<StationBankAccountComponent?> ent,
+        int balanceAdded,
+        ProtoId<CargoAccountPrototype> account,
+        bool dirty = true)
+    {
+        UpdateBankAccount(
+            ent,
+            balanceAdded,
+            new Dictionary<ProtoId<CargoAccountPrototype>, double> { {account, 1} },
+            dirty: dirty);
+    }
+
+    /// <summary>
+    /// Adds or removes funds from the <see cref="StationBankAccountComponent"/>.
+    /// </summary>
+    /// <param name="ent">The station.</param>
+    /// <param name="balanceAdded">The amount of funds to add or remove.</param>
+    /// <param name="accountDistribution">The distribution between individual <see cref="CargoAccountPrototype"/>.</param>
+    /// <param name="dirty">Whether to mark the bank account component as dirty.</param>
+    [PublicAPI]
+    public void UpdateBankAccount(
+        Entity<StationBankAccountComponent?> ent,
+        int balanceAdded,
+        Dictionary<ProtoId<CargoAccountPrototype>, 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]
index 2e3c395198036af88e1b0a03db76c2bcab4f42b0..218235338cbcf7eeb3d0ea6641818e0befb859e1 100644 (file)
@@ -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 =