diff --git a/Content.Server/Cloning/CloningSystem.cs b/Content.Server/Cloning/CloningSystem.cs index 59b96d612f..322b092bfe 100644 --- a/Content.Server/Cloning/CloningSystem.cs +++ b/Content.Server/Cloning/CloningSystem.cs @@ -1,6 +1,5 @@ using Content.Shared.GameTicking; using Content.Shared.Damage; -using Content.Shared.Stacks; using Content.Shared.Examine; using Content.Shared.Cloning; using Content.Shared.Atmos; @@ -18,7 +17,6 @@ using Content.Shared.Chemistry.Components; using Content.Server.Fluids.EntitySystems; using Content.Server.Chat.Systems; using Content.Server.Construction; -using Content.Server.Construction.Components; using Content.Server.Materials; using Content.Server.Stack; using Content.Server.Jobs; @@ -50,8 +48,6 @@ namespace Content.Server.Cloning [Dependency] private readonly AtmosphereSystem _atmosphereSystem = default!; [Dependency] private readonly TransformSystem _transformSystem = default!; [Dependency] private readonly SharedAppearanceSystem _appearance = default!; - [Dependency] private readonly SharedStackSystem _stackSystem = default!; - [Dependency] private readonly StackSystem _serverStackSystem = default!; [Dependency] private readonly SpillableSystem _spillableSystem = default!; [Dependency] private readonly ChatSystem _chatSystem = default!; [Dependency] private readonly IConfigurationManager _configManager = default!; @@ -316,7 +312,7 @@ namespace Content.Server.Cloning } _spillableSystem.SpillAt(uid, bloodSolution, "PuddleBlood"); - _serverStackSystem.SpawnMultipleFromMaterial(_robustRandom.Next(1, (int) (clonePod.UsedBiomass / 2.5)), clonePod.RequiredMaterial, Transform(uid).Coordinates); + _material.SpawnMultipleFromMaterial(_robustRandom.Next(1, (int) (clonePod.UsedBiomass / 2.5)), clonePod.RequiredMaterial, Transform(uid).Coordinates); clonePod.UsedBiomass = 0; RemCompDeferred(uid); diff --git a/Content.Server/Materials/MaterialStorageSystem.cs b/Content.Server/Materials/MaterialStorageSystem.cs index 8dbdfaf97c..4e4aaeec58 100644 --- a/Content.Server/Materials/MaterialStorageSystem.cs +++ b/Content.Server/Materials/MaterialStorageSystem.cs @@ -6,6 +6,9 @@ using Content.Server.Power.Components; using Content.Server.Construction.Components; using Content.Server.Stack; using Content.Shared.Database; +using JetBrains.Annotations; +using Robust.Shared.Map; +using Robust.Shared.Prototypes; namespace Content.Server.Materials; @@ -15,6 +18,7 @@ namespace Content.Server.Materials; public sealed class MaterialStorageSystem : SharedMaterialStorageSystem { [Dependency] private readonly IAdminLogManager _adminLogger = default!; + [Dependency] private readonly IPrototypeManager _prototypeManager = default!; [Dependency] private readonly SharedAudioSystem _audio = default!; [Dependency] private readonly SharedPopupSystem _popup = default!; [Dependency] private readonly StackSystem _stackSystem = default!; @@ -32,7 +36,7 @@ public sealed class MaterialStorageSystem : SharedMaterialStorageSystem foreach (var (material, amount) in component.Storage) { - _stackSystem.SpawnMultipleFromMaterial(amount, material, Transform(uid).Coordinates); + SpawnMultipleFromMaterial(amount, material, Transform(uid).Coordinates); } } @@ -56,4 +60,42 @@ public sealed class MaterialStorageSystem : SharedMaterialStorageSystem $"{ToPrettyString(user):player} inserted {count} {ToPrettyString(toInsert):inserted} into {ToPrettyString(receiver):receiver}"); return true; } + + /// + /// Spawn an amount of a material in stack entities. + /// Note the 'amount' is material dependent. + /// 1 biomass = 1 biomass in its stack, + /// but 100 plasma = 1 sheet of plasma, etc. + /// + [PublicAPI] + public List SpawnMultipleFromMaterial(int amount, string material, EntityCoordinates coordinates) + { + if (!_prototypeManager.TryIndex(material, out var stackType)) + { + Logger.Error("Failed to index material prototype " + material); + return new List(); + } + + return SpawnMultipleFromMaterial(amount, stackType, coordinates); + } + + /// + /// Spawn an amount of a material in stack entities. + /// Note the 'amount' is material dependent. + /// 1 biomass = 1 biomass in its stack, + /// but 100 plasma = 1 sheet of plasma, etc. + /// + public List SpawnMultipleFromMaterial(int amount, MaterialPrototype materialProto, EntityCoordinates coordinates) + { + if (amount <= 0) + return new List(); + + var entProto = _prototypeManager.Index(materialProto.StackEntity); + if (!entProto.TryGetComponent(out var material)) + return new List(); + + var materialPerStack = material.Materials[materialProto.ID]; + var amountToSpawn = amount / materialPerStack; + return _stackSystem.SpawnMultiple(materialProto.StackEntity, amountToSpawn, coordinates); + } } diff --git a/Content.Server/Medical/BiomassReclaimer/BiomassReclaimerSystem.cs b/Content.Server/Medical/BiomassReclaimer/BiomassReclaimerSystem.cs index efb0c9d03a..4fdb37909a 100644 --- a/Content.Server/Medical/BiomassReclaimer/BiomassReclaimerSystem.cs +++ b/Content.Server/Medical/BiomassReclaimer/BiomassReclaimerSystem.cs @@ -17,8 +17,8 @@ using Content.Server.Body.Components; using Content.Server.Climbing; using Content.Server.Construction; using Content.Server.DoAfter; +using Content.Server.Materials; using Content.Server.Mind.Components; -using Content.Server.Stack; using Content.Shared.Humanoid; using Content.Shared.Interaction.Events; using Content.Shared.Popups; @@ -32,7 +32,6 @@ namespace Content.Server.Medical.BiomassReclaimer public sealed class BiomassReclaimerSystem : EntitySystem { [Dependency] private readonly IConfigurationManager _configManager = default!; - [Dependency] private readonly StackSystem _stackSystem = default!; [Dependency] private readonly MobStateSystem _mobState = default!; [Dependency] private readonly SharedJitteringSystem _jitteringSystem = default!; [Dependency] private readonly SharedAudioSystem _sharedAudioSystem = default!; @@ -44,6 +43,7 @@ namespace Content.Server.Medical.BiomassReclaimer [Dependency] private readonly ISharedAdminLogManager _adminLogger = default!; [Dependency] private readonly DoAfterSystem _doAfterSystem = default!; [Dependency] private readonly IPlayerManager _playerManager = default!; + [Dependency] private readonly MaterialStorageSystem _material = default!; public override void Update(float frameTime) { @@ -76,7 +76,7 @@ namespace Content.Server.Medical.BiomassReclaimer continue; } - _stackSystem.SpawnMultipleFromMaterial((int) reclaimer.CurrentExpectedYield, "Biomass", Transform(reclaimer.Owner).Coordinates); + _material.SpawnMultipleFromMaterial(reclaimer.CurrentExpectedYield, "Biomass", Transform(reclaimer.Owner).Coordinates); reclaimer.BloodReagent = null; reclaimer.SpawnedEntities.Clear(); diff --git a/Content.Server/Stack/StackSystem.cs b/Content.Server/Stack/StackSystem.cs index 31a46fc318..4e2d099500 100644 --- a/Content.Server/Stack/StackSystem.cs +++ b/Content.Server/Stack/StackSystem.cs @@ -1,7 +1,6 @@ using Content.Shared.Popups; using Content.Shared.Stacks; using Content.Shared.Verbs; -using Content.Shared.Materials; using JetBrains.Annotations; using Robust.Shared.Map; using Robust.Shared.Prototypes; @@ -16,7 +15,6 @@ namespace Content.Server.Stack public sealed class StackSystem : SharedStackSystem { [Dependency] private readonly IPrototypeManager _prototypeManager = default!; - [Dependency] private readonly SharedStackSystem _sharedStack = default!; public static readonly int[] DefaultSplitAmounts = { 1, 5, 10, 20, 30, 50 }; @@ -91,78 +89,21 @@ namespace Content.Server.Stack /// Say you want to spawn 97 units of something that has a max stack count of 30. /// This would spawn 3 stacks of 30 and 1 stack of 7. /// - public List SpawnMultiple(int amount, MaterialPrototype materialProto, EntityCoordinates coordinates) + public List SpawnMultiple(string entityPrototype, int amount, EntityCoordinates spawnPosition) { - var list = new List(); - if (amount <= 0) - return list; - - // At least 1 is being spawned, we'll use the first to extract otherwise inaccessible information - // ??TODO??: Indexing the entity proto and extracting from its component registry could possibly be better? - // it doesn't look like it would save LOC even compressing this to a single loop and I'm not sure what other issues it might introduce - var firstSpawn = Spawn(materialProto.StackEntity, coordinates); - list.Add(firstSpawn); - - if (!TryComp(firstSpawn, out var stack) || stack.StackTypeId == null) - return list; - - if (!TryComp(firstSpawn, out var material)) - return list; - - int maxCountPerStack = _sharedStack.GetMaxCount(stack); - var materialPerStack = material.Materials[materialProto.ID]; - - var materialPerMaxCount = maxCountPerStack * materialPerStack; - - // no material duping for you - if (amount < materialPerStack) - { - Del(firstSpawn); - return list; - } - - if (amount > materialPerMaxCount) - { - SetCount(firstSpawn, maxCountPerStack, stack); - amount -= materialPerMaxCount; - } else - { - SetCount(firstSpawn, (amount / materialPerStack), stack); - amount = 0; - } - + var proto = _prototypeManager.Index(entityPrototype); + proto.TryGetComponent(out var stack); + var maxCountPerStack = GetMaxCount(stack); + var spawnedEnts = new List(); while (amount > 0) { - var entity = Spawn(materialProto.StackEntity, coordinates); - list.Add(entity); - var nextStack = Comp(entity); - if (amount > materialPerMaxCount) - { - SetCount(entity, materialPerMaxCount, nextStack); - amount -= materialPerMaxCount; - } - else - { - SetCount(entity, (amount / materialPerStack), nextStack); - amount = 0; - } + var entity = Spawn(entityPrototype, spawnPosition); + spawnedEnts.Add(entity); + var countAmount = Math.Min(maxCountPerStack, amount); + SetCount(entity, countAmount); + amount -= countAmount; } - return list; - } - - /// - /// Spawn an amount of a material in stack entities. Note the 'amount' is material dependent. 1 biomass = 1 biomass in its stack, - /// but 100 plasma = 1 sheet of plasma, etc. - /// - public List SpawnMultipleFromMaterial(int amount, string material, EntityCoordinates coordinates) - { - if (!_prototypeManager.TryIndex(material, out var stackType)) - { - Logger.Error("Failed to index material prototype " + material); - return new List(); - } - - return SpawnMultiple(amount, stackType, coordinates); + return spawnedEnts; } private void OnStackAlternativeInteract(EntityUid uid, StackComponent stack, GetVerbsEvent args) diff --git a/Content.Server/Store/Systems/StoreSystem.Ui.cs b/Content.Server/Store/Systems/StoreSystem.Ui.cs index c0f5ecd445..f7a095f1be 100644 --- a/Content.Server/Store/Systems/StoreSystem.Ui.cs +++ b/Content.Server/Store/Systems/StoreSystem.Ui.cs @@ -200,7 +200,7 @@ public sealed partial class StoreSystem : EntitySystem { var cashId = proto.Cash[value]; var amountToSpawn = (int) MathF.Floor((float) (amountRemaining / value)); - var ents = _stack.SpawnMultipleFromMaterial(amountToSpawn, cashId, coordinates); + var ents = _stack.SpawnMultiple(cashId, amountToSpawn, coordinates); _hands.PickupOrDrop(buyer, ents.First()); amountRemaining -= value * amountToSpawn; }