diff --git a/Content.Client/Materials/UI/MaterialStorageControl.xaml.cs b/Content.Client/Materials/UI/MaterialStorageControl.xaml.cs index 3ef247d529..2d4934d5ce 100644 --- a/Content.Client/Materials/UI/MaterialStorageControl.xaml.cs +++ b/Content.Client/Materials/UI/MaterialStorageControl.xaml.cs @@ -43,8 +43,15 @@ public sealed partial class MaterialStorageControl : BoxContainer return; } + var gridStorage = _entityManager.TryGetComponent(_owner, out var transformComponent) && + _entityManager.TryGetComponent(transformComponent.GridUid, + out var materialStorageComponent) ? materialStorageComponent : null; + + materialStorage = gridStorage ?? materialStorage; + var canEject = materialStorage.CanEjectStoredMaterials; var mats = materialStorage.Storage.Select(pair => (pair.Key.Id, pair.Value)).ToDictionary(); + if (_currentMaterials.Equals(mats)) return; diff --git a/Content.Server/Lathe/LatheSystem.cs b/Content.Server/Lathe/LatheSystem.cs index 621c583a55..5b0c152ad3 100644 --- a/Content.Server/Lathe/LatheSystem.cs +++ b/Content.Server/Lathe/LatheSystem.cs @@ -164,7 +164,15 @@ namespace Content.Server.Lathe ? (int) (-amount * component.MaterialUseMultiplier) : -amount; - _materialStorage.TryChangeMaterialAmount(uid, mat, adjustedAmount); + var gridUid = + TryComp(uid, out var transformComponent) ? transformComponent.GridUid : null; + + var gridStorage = + gridUid.HasValue && + TryComp(gridUid.Value, out var materialStorageComponent) ? materialStorageComponent : null; + + _materialStorage.TryChangeMaterialAmount(uid, mat, adjustedAmount, gridUid: gridUid, gridStorage: gridStorage); + } component.Queue.Add(recipe); diff --git a/Content.Server/Materials/MaterialStorageSystem.cs b/Content.Server/Materials/MaterialStorageSystem.cs index 25e409fd01..1cf99a35e6 100644 --- a/Content.Server/Materials/MaterialStorageSystem.cs +++ b/Content.Server/Materials/MaterialStorageSystem.cs @@ -78,7 +78,17 @@ public sealed class MaterialStorageSystem : SharedMaterialStorageSystem volume = sheetsToExtract * volumePerSheet; } - if (volume <= 0 || !TryChangeMaterialAmount(uid, msg.Material, -volume)) + var gridUid = TryComp(uid, out var transformComponent) + ? transformComponent.GridUid + : null; + + var gridStorage = gridUid.HasValue && + TryComp(gridUid, out var materialStorageComponent) + ? materialStorageComponent + : null; + + + if (volume <= 0 || !TryChangeMaterialAmount(uid, msg.Material, -volume, gridUid: gridUid, gridStorage: gridStorage)) return; var mats = SpawnMultipleFromMaterial(volume, material, Transform(uid).Coordinates, out _); diff --git a/Content.Shared/Lathe/SharedLatheSystem.cs b/Content.Shared/Lathe/SharedLatheSystem.cs index b41a91f9c3..7b8770bf46 100644 --- a/Content.Shared/Lathe/SharedLatheSystem.cs +++ b/Content.Shared/Lathe/SharedLatheSystem.cs @@ -44,9 +44,20 @@ public abstract class SharedLatheSystem : EntitySystem { var adjustedAmount = AdjustMaterial(needed, recipe.ApplyMaterialDiscount, component.MaterialUseMultiplier); - if (_materialStorage.GetMaterialAmount(uid, material) < adjustedAmount * amount) + var gridUid = + TryComp(uid, out var transformComponent) + ? transformComponent.GridUid + : null; + + var gridStorage = gridUid.HasValue && + TryComp(gridUid, out var materialStorageComponent) + ? materialStorageComponent + : null; + + if (_materialStorage.GetMaterialAmount(uid, material, gridUid: gridUid, gridStorage: gridStorage) < adjustedAmount * amount) return false; } + return true; } diff --git a/Content.Shared/Materials/MaterialStorageComponent.cs b/Content.Shared/Materials/MaterialStorageComponent.cs index 7d8dd5c749..e92f46918a 100644 --- a/Content.Shared/Materials/MaterialStorageComponent.cs +++ b/Content.Shared/Materials/MaterialStorageComponent.cs @@ -7,7 +7,6 @@ using Robust.Shared.Serialization; namespace Content.Shared.Materials; [RegisterComponent, NetworkedComponent, AutoGenerateComponentState] -[Access(typeof(SharedMaterialStorageSystem))] public sealed partial class MaterialStorageComponent : Component { [DataField, AutoNetworkedField] diff --git a/Content.Shared/Materials/SharedMaterialStorageSystem.cs b/Content.Shared/Materials/SharedMaterialStorageSystem.cs index 9f7c87df3c..5605b8a5d9 100644 --- a/Content.Shared/Materials/SharedMaterialStorageSystem.cs +++ b/Content.Shared/Materials/SharedMaterialStorageSystem.cs @@ -1,6 +1,7 @@ using System.Linq; using Content.Shared.Interaction; using Content.Shared.Interaction.Components; +using Content.Shared.Lathe; using Content.Shared.Stacks; using JetBrains.Annotations; using Robust.Shared.Prototypes; @@ -77,10 +78,19 @@ public abstract class SharedMaterialStorageSystem : EntitySystem /// /// /// The volume of the material - public int GetMaterialAmount(EntityUid uid, string material, MaterialStorageComponent? component = null) + public int GetMaterialAmount(EntityUid uid, string material, MaterialStorageComponent? component = null, EntityUid? gridUid = null, MaterialStorageComponent? gridStorage = null) { + if (gridUid.HasValue && gridStorage != null) + { + if (!Resolve(gridUid.Value, ref gridStorage)) + return 0; //you have nothing + + return gridStorage.Storage.GetValueOrDefault(material, 0); + } + if (!Resolve(uid, ref component)) return 0; //you have nothing + return component.Storage.GetValueOrDefault(material, 0); } @@ -104,10 +114,19 @@ public abstract class SharedMaterialStorageSystem : EntitySystem /// /// /// If the specified volume will fit - public bool CanTakeVolume(EntityUid uid, int volume, MaterialStorageComponent? component = null) + public bool CanTakeVolume(EntityUid uid, int volume, MaterialStorageComponent? component = null, EntityUid? gridUid = null, MaterialStorageComponent? gridStorage = null) { + if (gridUid.HasValue && gridStorage != null) + { + if (!Resolve(gridUid.Value, ref gridStorage)) + return false; + + return gridStorage.StorageLimit == null || GetTotalMaterialAmount(gridUid.Value, gridStorage) + volume <= gridStorage.StorageLimit; + } + if (!Resolve(uid, ref component)) - return false; + return false; + return component.StorageLimit == null || GetTotalMaterialAmount(uid, component) + volume <= component.StorageLimit; } @@ -119,18 +138,21 @@ public abstract class SharedMaterialStorageSystem : EntitySystem /// /// /// If the amount can be changed - public bool CanChangeMaterialAmount(EntityUid uid, string materialId, int volume, MaterialStorageComponent? component = null) + public bool CanChangeMaterialAmount(EntityUid uid, string materialId, int volume, MaterialStorageComponent? component, EntityUid? gridUid = null, MaterialStorageComponent? gridStorage = null) { if (!Resolve(uid, ref component)) return false; - if (!CanTakeVolume(uid, volume, component)) + if (!CanTakeVolume(uid, volume, component, gridUid:gridUid, gridStorage:gridStorage)) return false; if (component.MaterialWhiteList != null && !component.MaterialWhiteList.Contains(materialId)) return false; - var amount = component.Storage.GetValueOrDefault(materialId); + var amount = gridStorage != null + ? gridStorage.Storage.GetValueOrDefault(materialId) + : component.Storage.GetValueOrDefault(materialId); + return amount + volume >= 0; } @@ -164,21 +186,37 @@ public abstract class SharedMaterialStorageSystem : EntitySystem /// /// /// If it was successful - public bool TryChangeMaterialAmount(EntityUid uid, string materialId, int volume, MaterialStorageComponent? component = null, bool dirty = true) + public bool TryChangeMaterialAmount(EntityUid uid, string materialId, int volume, MaterialStorageComponent? component = null, bool dirty = true, EntityUid? gridUid = null, MaterialStorageComponent? gridStorage = null) { if (!Resolve(uid, ref component)) return false; - if (!CanChangeMaterialAmount(uid, materialId, volume, component)) + + if (!CanChangeMaterialAmount(uid, materialId, volume, component, gridUid:gridUid, gridStorage:gridStorage)) return false; - component.Storage.TryAdd(materialId, 0); - component.Storage[materialId] += volume; + + var rightStorage = gridStorage ?? component; + + rightStorage.Storage.TryAdd(materialId, 0); + rightStorage.Storage[materialId] += volume; var ev = new MaterialAmountChangedEvent(); RaiseLocalEvent(uid, ref ev); if (dirty) Dirty(uid, component); + + // ShitSilo + if (!gridUid.HasValue || gridStorage == null) + return true; // Early return if conditions aren't met + + var eventGrid = new MaterialAmountChangedEvent(); + RaiseLocalEvent(gridUid.Value, ref eventGrid); + + if (dirty) + Dirty(gridUid.Value, gridStorage); + return true; + } /// @@ -248,6 +286,7 @@ public abstract class SharedMaterialStorageSystem : EntitySystem if (storage.Whitelist?.IsValid(toInsert) == false) return false; + if (HasComp(toInsert)) return false; @@ -255,21 +294,34 @@ public abstract class SharedMaterialStorageSystem : EntitySystem var multiplier = TryComp(toInsert, out var stackComponent) ? stackComponent.Count : 1; var totalVolume = 0; + + var gridUid = HasComp(receiver) && + TryComp(receiver, out var transformComponent) + ? transformComponent.GridUid + : null; + + var gridStorage = gridUid.HasValue && TryComp(gridUid, + out var materialStorageComponent) + ? materialStorageComponent + : null; + + foreach (var (mat, vol) in composition.MaterialComposition) { - if (!CanChangeMaterialAmount(receiver, mat, vol * multiplier, storage)) + if (!CanChangeMaterialAmount(receiver, mat, vol * multiplier, storage, gridUid:gridUid, gridStorage:gridStorage)) return false; totalVolume += vol * multiplier; } - if (!CanTakeVolume(receiver, totalVolume, storage)) + if (!CanTakeVolume(receiver, totalVolume, storage, gridUid:gridUid, gridStorage: gridStorage)) return false; foreach (var (mat, vol) in composition.MaterialComposition) { - TryChangeMaterialAmount(receiver, mat, vol * multiplier, storage); + TryChangeMaterialAmount(receiver, mat, vol * multiplier, gridUid:gridUid, gridStorage:gridStorage); } + var insertingComp = EnsureComp(receiver); insertingComp.EndTime = _timing.CurTime + storage.InsertionTime; if (!storage.IgnoreColor) diff --git a/Resources/Maps/Test/dev_map.yml b/Resources/Maps/Test/dev_map.yml index f00d7049a5..1ec9085beb 100644 --- a/Resources/Maps/Test/dev_map.yml +++ b/Resources/Maps/Test/dev_map.yml @@ -376,6 +376,7 @@ entities: - type: GasTileOverlay - type: BecomesStation id: Dev + - type: MaterialStorage - type: SpreaderGrid - type: GridPathfinding - type: NavMap diff --git a/Resources/Maps/Test/empty.yml b/Resources/Maps/Test/empty.yml index 830926268e..1cb2172b4a 100644 --- a/Resources/Maps/Test/empty.yml +++ b/Resources/Maps/Test/empty.yml @@ -29,6 +29,7 @@ entities: fixtures: {} - type: BecomesStation id: Empty + - type: MaterialStorage - type: OccluderTree - type: Shuttle - type: GridPathfinding diff --git a/Resources/Maps/Test/test_teg.yml b/Resources/Maps/Test/test_teg.yml index 4a101265bb..48477283b9 100644 --- a/Resources/Maps/Test/test_teg.yml +++ b/Resources/Maps/Test/test_teg.yml @@ -241,6 +241,7 @@ entities: - type: RadiationGridResistance - type: BecomesStation id: TEG + - type: MaterialStorage - proto: AirAlarm entities: - uid: 436 diff --git a/Resources/Maps/atlas.yml b/Resources/Maps/atlas.yml index 68996e61c2..ab804d93cc 100644 --- a/Resources/Maps/atlas.yml +++ b/Resources/Maps/atlas.yml @@ -2546,6 +2546,7 @@ entities: chunkSize: 4 - type: BecomesStation id: Atlas + - type: MaterialStorage - type: OccluderTree - type: SpreaderGrid - type: Shuttle diff --git a/Resources/Maps/bagel.yml b/Resources/Maps/bagel.yml index d27a3cbe43..b483e97dd2 100644 --- a/Resources/Maps/bagel.yml +++ b/Resources/Maps/bagel.yml @@ -459,6 +459,7 @@ entities: fixtures: {} - type: BecomesStation id: Bagel + - type: MaterialStorage - type: Gravity gravityShakeSound: !type:SoundPathSpecifier path: /Audio/Effects/alert.ogg diff --git a/Resources/Maps/box.yml b/Resources/Maps/box.yml index c0d0278c35..9f04f3c1ca 100644 --- a/Resources/Maps/box.yml +++ b/Resources/Maps/box.yml @@ -489,6 +489,7 @@ entities: fixtures: {} - type: BecomesStation id: Boxstation + - type: MaterialStorage - type: Gravity gravityShakeSound: !type:SoundPathSpecifier path: /Audio/Effects/alert.ogg diff --git a/Resources/Maps/centcomm.yml b/Resources/Maps/centcomm.yml index b64158f08b..12a8d33bcc 100644 --- a/Resources/Maps/centcomm.yml +++ b/Resources/Maps/centcomm.yml @@ -162,6 +162,7 @@ entities: fixtures: {} - type: BecomesStation id: centcomm + - type: MaterialStorage - type: Gravity gravityShakeSound: !type:SoundPathSpecifier path: /Audio/Effects/alert.ogg diff --git a/Resources/Maps/cluster.yml b/Resources/Maps/cluster.yml index 14d64ee35e..7c1c125441 100644 --- a/Resources/Maps/cluster.yml +++ b/Resources/Maps/cluster.yml @@ -4423,6 +4423,7 @@ entities: - type: RadiationGridResistance - type: BecomesStation id: Cluster + - type: MaterialStorage - type: SpreaderGrid - type: GridPathfinding - uid: 12281 diff --git a/Resources/Maps/core.yml b/Resources/Maps/core.yml index 4bfbaece03..49f9368d4f 100644 --- a/Resources/Maps/core.yml +++ b/Resources/Maps/core.yml @@ -10938,6 +10938,7 @@ entities: - type: RadiationGridResistance - type: BecomesStation id: Core + - type: MaterialStorage - uid: 17546 components: - type: MetaData @@ -100931,11 +100932,11 @@ entities: After several simulations where Superconducting Magnetic Energy Storage units were drained from the main system from [italic]a variety[/italic] of user errors and other shenanigans, it has been determined that the Singularity should be put on its own power loop, disconnected from the main station. The upsides of this include but are not limited to: - [bold]1.[/bold] Limited external forces from the containments power. + [bold]1.[/bold] Limited external forces from the containments power. - [bold]2.[/bold] An "early warning" system, if you see JUST the PA room run out of power, you know there is an issue. + [bold]2.[/bold] An "early warning" system, if you see JUST the PA room run out of power, you know there is an issue. - [bold]3.[/bold] Due to being on its own small loop, its much easier to spot faults in the system. + [bold]3.[/bold] Due to being on its own small loop, its much easier to spot faults in the system. [italic]While we have listed the upsides we also acknowledge the downside,[/italic] for it being on its own loop you will need an external force if the system "runs out of juice". Our recommendation for this is simply attaching a generator to said SMES and letting it get to full charge before continuing operations but as said from another of our technicians... "just attach it to the main grid for like, a hot moment, and kickstart the thing!" diff --git a/Resources/Maps/europa.yml b/Resources/Maps/europa.yml index e0cb676c39..4350cc21b6 100644 --- a/Resources/Maps/europa.yml +++ b/Resources/Maps/europa.yml @@ -11429,6 +11429,7 @@ entities: - type: LoadedMap - type: BecomesStation id: Europa + - type: MaterialStorage - proto: AccordionInstrument entities: - uid: 2598 diff --git a/Resources/Maps/fland.yml b/Resources/Maps/fland.yml index 7322efa508..5bce8acaf2 100644 --- a/Resources/Maps/fland.yml +++ b/Resources/Maps/fland.yml @@ -596,6 +596,7 @@ entities: fixtures: {} - type: BecomesStation id: Fland + - type: MaterialStorage - type: OccluderTree - type: Shuttle - type: Gravity diff --git a/Resources/Maps/marathon.yml b/Resources/Maps/marathon.yml index bed5dd26f6..0d910d53a7 100644 --- a/Resources/Maps/marathon.yml +++ b/Resources/Maps/marathon.yml @@ -7741,6 +7741,7 @@ entities: chunkSize: 4 - type: BecomesStation id: Marathon + - type: MaterialStorage - type: OccluderTree - type: Shuttle - type: RadiationGridResistance diff --git a/Resources/Maps/meta.yml b/Resources/Maps/meta.yml index 10fa94ffb0..416b8112b3 100644 --- a/Resources/Maps/meta.yml +++ b/Resources/Maps/meta.yml @@ -8197,6 +8197,7 @@ entities: chunkSize: 4 - type: BecomesStation id: Meta + - type: MaterialStorage - type: OccluderTree - type: Shuttle - type: GasTileOverlay diff --git a/Resources/Maps/omega.yml b/Resources/Maps/omega.yml index 8bb990566e..3ee8f0da7d 100644 --- a/Resources/Maps/omega.yml +++ b/Resources/Maps/omega.yml @@ -4186,6 +4186,7 @@ entities: chunkSize: 4 - type: BecomesStation id: Omega + - type: MaterialStorage - type: OccluderTree - type: Shuttle - type: RadiationGridResistance diff --git a/Resources/Maps/origin.yml b/Resources/Maps/origin.yml index 5817fe5a16..325a29a96c 100644 --- a/Resources/Maps/origin.yml +++ b/Resources/Maps/origin.yml @@ -10484,6 +10484,7 @@ entities: chunkSize: 4 - type: BecomesStation id: Origin + - type: MaterialStorage - type: OccluderTree - type: Shuttle - type: RadiationGridResistance diff --git a/Resources/Maps/packed.yml b/Resources/Maps/packed.yml index 00969fa062..b1b542ec91 100644 --- a/Resources/Maps/packed.yml +++ b/Resources/Maps/packed.yml @@ -278,6 +278,7 @@ entities: fixtures: {} - type: BecomesStation id: Packed + - type: MaterialStorage - type: Gravity gravityShakeSound: !type:SoundPathSpecifier path: /Audio/Effects/alert.ogg diff --git a/Resources/Maps/reach.yml b/Resources/Maps/reach.yml index a4d369582b..b9c875579a 100644 --- a/Resources/Maps/reach.yml +++ b/Resources/Maps/reach.yml @@ -95,6 +95,7 @@ entities: fixtures: {} - type: BecomesStation id: Reach + - type: MaterialStorage - type: OccluderTree - type: Shuttle - type: GridPathfinding diff --git a/Resources/Maps/saltern.yml b/Resources/Maps/saltern.yml index 49fc8a3dfc..64c0d8cefd 100644 --- a/Resources/Maps/saltern.yml +++ b/Resources/Maps/saltern.yml @@ -236,6 +236,7 @@ entities: fixtures: {} - type: BecomesStation id: Saltern + - type: MaterialStorage - type: GridAtmosphere version: 2 data: diff --git a/Resources/Maps/train.yml b/Resources/Maps/train.yml index fb6e8ddc4a..f8ddea0e99 100644 --- a/Resources/Maps/train.yml +++ b/Resources/Maps/train.yml @@ -5373,6 +5373,7 @@ entities: - type: FTLDestination - type: BecomesStation id: Train + - type: MaterialStorage - proto: AccordionInstrument entities: - uid: 12393