From 00bae110e1b46bde9894ac96fbe2c172b9630b80 Mon Sep 17 00:00:00 2001 From: deltanedas <39013340+deltanedas@users.noreply.github.com> Date: Sun, 20 Aug 2023 01:37:19 +0100 Subject: [PATCH] move hot plate item placement stuff into its own system (#18923) Co-authored-by: deltanedas <@deltanedas:kde.org> --- .../Components/SolutionHeaterComponent.cs | 21 ------ .../EntitySystems/SolutionHeaterSystem.cs | 57 ++++++--------- .../Components/ArtifactAnalyzerComponent.cs | 6 -- .../Systems/ArtifactAnalyzerSystem.cs | 61 +++++----------- .../Systems/TraversalDistorterSystem.cs | 23 ++---- .../Placeable/ItemPlacerComponent.cs | 31 ++++++++ Content.Shared/Placeable/ItemPlacerSystem.cs | 72 +++++++++++++++++++ .../Structures/Machines/artifact_analyzer.yml | 12 ++++ .../Entities/Structures/Machines/hotplate.yml | 1 + 9 files changed, 160 insertions(+), 124 deletions(-) create mode 100644 Content.Shared/Placeable/ItemPlacerComponent.cs create mode 100644 Content.Shared/Placeable/ItemPlacerSystem.cs diff --git a/Content.Server/Chemistry/Components/SolutionHeaterComponent.cs b/Content.Server/Chemistry/Components/SolutionHeaterComponent.cs index 2c5f5e5ab8..0a9e696c87 100644 --- a/Content.Server/Chemistry/Components/SolutionHeaterComponent.cs +++ b/Content.Server/Chemistry/Components/SolutionHeaterComponent.cs @@ -1,5 +1,3 @@ -using Content.Shared.Whitelist; - namespace Content.Server.Chemistry.Components; [RegisterComponent] @@ -28,23 +26,4 @@ public sealed class SolutionHeaterComponent : Component /// [DataField("partRatingHeatMultiplier")] public float PartRatingHeatMultiplier = 1.5f; - - /// - /// The entities that are placed on the heater. - /// - [DataField("placedEntities")] - public HashSet PlacedEntities = new(); - - /// - /// The max amount of entities that can be heated at the same time. - /// - [DataField("maxEntities")] - public uint MaxEntities = 1; - - /// - /// Whitelist for entities that can be placed on the heater. - /// - [DataField("whitelist")] - [ViewVariables(VVAccess.ReadWrite)] - public EntityWhitelist? Whitelist; } diff --git a/Content.Server/Chemistry/EntitySystems/SolutionHeaterSystem.cs b/Content.Server/Chemistry/EntitySystems/SolutionHeaterSystem.cs index 4e3db49e80..b5eb587cf2 100644 --- a/Content.Server/Chemistry/EntitySystems/SolutionHeaterSystem.cs +++ b/Content.Server/Chemistry/EntitySystems/SolutionHeaterSystem.cs @@ -1,4 +1,3 @@ -using System.Linq; using Content.Server.Chemistry.Components; using Content.Server.Chemistry.Components.SolutionManager; using Content.Server.Construction; @@ -6,27 +5,26 @@ using Content.Server.Power.Components; using Content.Server.Power.EntitySystems; using Content.Shared.Chemistry; using Content.Shared.Placeable; -using Robust.Shared.Physics.Events; -using Robust.Shared.Physics.Systems; namespace Content.Server.Chemistry.EntitySystems; public sealed class SolutionHeaterSystem : EntitySystem { - [Dependency] private readonly SharedAppearanceSystem _appearance = default!; - [Dependency] private readonly SharedPhysicsSystem _physics = default!; - [Dependency] private readonly PlaceableSurfaceSystem _placeableSurface = default!; + [Dependency] private readonly ItemPlacerSystem _itemPlacer = default!; [Dependency] private readonly PowerReceiverSystem _powerReceiver = default!; + [Dependency] private readonly SharedAppearanceSystem _appearance = default!; [Dependency] private readonly SolutionContainerSystem _solution = default!; /// public override void Initialize() { + base.Initialize(); + SubscribeLocalEvent(OnPowerChanged); SubscribeLocalEvent(OnRefreshParts); SubscribeLocalEvent(OnUpgradeExamine); - SubscribeLocalEvent(OnStartCollide); - SubscribeLocalEvent(OnEndCollide); + SubscribeLocalEvent(OnItemPlaced); + SubscribeLocalEvent(OnItemRemoved); } private void TurnOn(EntityUid uid) @@ -35,9 +33,12 @@ public sealed class SolutionHeaterSystem : EntitySystem EnsureComp(uid); } - public bool TryTurnOn(EntityUid uid, SolutionHeaterComponent component) + public bool TryTurnOn(EntityUid uid, ItemPlacerComponent? placer = null) { - if (component.PlacedEntities.Count <= 0 || !_powerReceiver.IsPowered(uid)) + if (!Resolve(uid, ref placer)) + return false; + + if (placer.PlacedEntities.Count <= 0 || !_powerReceiver.IsPowered(uid)) return false; TurnOn(uid); @@ -52,7 +53,8 @@ public sealed class SolutionHeaterSystem : EntitySystem private void OnPowerChanged(EntityUid uid, SolutionHeaterComponent component, ref PowerChangedEvent args) { - if (args.Powered && component.PlacedEntities.Count > 0) + var placer = Comp(uid); + if (args.Powered && placer.PlacedEntities.Count > 0) { TurnOn(uid); } @@ -74,43 +76,26 @@ public sealed class SolutionHeaterSystem : EntitySystem args.AddPercentageUpgrade("solution-heater-upgrade-heat", component.HeatPerSecond / component.BaseHeatPerSecond); } - private void OnStartCollide(EntityUid uid, SolutionHeaterComponent component, ref StartCollideEvent args) + private void OnItemPlaced(EntityUid uid, SolutionHeaterComponent comp, ref ItemPlacedEvent args) { - if (component.Whitelist is not null && !component.Whitelist.IsValid(args.OtherEntity)) - return; - - // Disallow sleeping so we can detect when entity is removed from the heater. - _physics.SetSleepingAllowed(args.OtherEntity, args.OtherBody, false); - - component.PlacedEntities.Add(args.OtherEntity); - - TryTurnOn(uid, component); - - if (component.PlacedEntities.Count >= component.MaxEntities) - _placeableSurface.SetPlaceable(uid, false); + TryTurnOn(uid); } - private void OnEndCollide(EntityUid uid, SolutionHeaterComponent component, ref EndCollideEvent args) + private void OnItemRemoved(EntityUid uid, SolutionHeaterComponent component, ref ItemRemovedEvent args) { - // Re-allow sleeping. - _physics.SetSleepingAllowed(args.OtherEntity, args.OtherBody, true); - - component.PlacedEntities.Remove(args.OtherEntity); - - if (component.PlacedEntities.Count == 0) // Last entity was removed + var placer = Comp(uid); + if (placer.PlacedEntities.Count == 0) // Last entity was removed TurnOff(uid); - - _placeableSurface.SetPlaceable(uid, true); } public override void Update(float frameTime) { base.Update(frameTime); - var query = EntityQueryEnumerator(); - while (query.MoveNext(out _, out _, out var heater)) + var query = EntityQueryEnumerator(); + while (query.MoveNext(out _, out _, out var heater, out var placer)) { - foreach (var heatingEntity in heater.PlacedEntities.Take((int) heater.MaxEntities)) + foreach (var heatingEntity in placer.PlacedEntities) { if (!TryComp(heatingEntity, out var solution)) continue; diff --git a/Content.Server/Xenoarchaeology/Equipment/Components/ArtifactAnalyzerComponent.cs b/Content.Server/Xenoarchaeology/Equipment/Components/ArtifactAnalyzerComponent.cs index d07819fd06..e691d8525b 100644 --- a/Content.Server/Xenoarchaeology/Equipment/Components/ArtifactAnalyzerComponent.cs +++ b/Content.Server/Xenoarchaeology/Equipment/Components/ArtifactAnalyzerComponent.cs @@ -45,12 +45,6 @@ public sealed class ArtifactAnalyzerComponent : Component [ViewVariables] public EntityUid? Console; - /// - /// All of the valid artifacts currently touching the analyzer. - /// - [ViewVariables] - public HashSet Contacts = new(); - [ViewVariables(VVAccess.ReadWrite)] public bool ReadyToPrint = false; diff --git a/Content.Server/Xenoarchaeology/Equipment/Systems/ArtifactAnalyzerSystem.cs b/Content.Server/Xenoarchaeology/Equipment/Systems/ArtifactAnalyzerSystem.cs index 47cf5f2766..30d9bae7e8 100644 --- a/Content.Server/Xenoarchaeology/Equipment/Systems/ArtifactAnalyzerSystem.cs +++ b/Content.Server/Xenoarchaeology/Equipment/Systems/ArtifactAnalyzerSystem.cs @@ -10,6 +10,7 @@ using Content.Server.Xenoarchaeology.XenoArtifacts.Events; using Content.Shared.Audio; using Content.Shared.DeviceLinking; using Content.Shared.DeviceLinking.Events; +using Content.Shared.Placeable; using Content.Shared.Popups; using Content.Shared.Research.Components; using Content.Shared.Xenoarchaeology.Equipment; @@ -18,7 +19,6 @@ using JetBrains.Annotations; using Robust.Server.GameObjects; using Robust.Server.Player; using Robust.Shared.Audio; -using Robust.Shared.Physics.Events; using Robust.Shared.Prototypes; using Robust.Shared.Timing; using Robust.Shared.Utility; @@ -45,7 +45,6 @@ public sealed class ArtifactAnalyzerSystem : EntitySystem /// public override void Initialize() { - SubscribeLocalEvent(OnScannedMoved); SubscribeLocalEvent(OnArtifactActivated); SubscribeLocalEvent(OnAnalyzeStart); @@ -54,8 +53,8 @@ public sealed class ArtifactAnalyzerSystem : EntitySystem SubscribeLocalEvent(OnUpgradeExamine); SubscribeLocalEvent(OnRefreshParts); - SubscribeLocalEvent(OnCollide); - SubscribeLocalEvent(OnEndCollide); + SubscribeLocalEvent(OnItemPlaced); + SubscribeLocalEvent(OnItemRemoved); SubscribeLocalEvent(OnMapInit); SubscribeLocalEvent(OnNewLink); @@ -107,22 +106,18 @@ public sealed class ArtifactAnalyzerSystem : EntitySystem } /// - /// Goes through the current contacts on + /// Goes through the current entities on /// the analyzer and returns a valid artifact /// /// - /// + /// /// - private EntityUid? GetArtifactForAnalysis(EntityUid? uid, ArtifactAnalyzerComponent? component = null) + private EntityUid? GetArtifactForAnalysis(EntityUid? uid, ItemPlacerComponent? placer = null) { - if (uid == null) + if (uid == null || !Resolve(uid.Value, ref placer)) return null; - if (!Resolve(uid.Value, ref component)) - return null; - - var validEnts = component.Contacts.Where(HasComp).ToHashSet(); - return validEnts.FirstOrNull(); + return placer.PlacedEntities.FirstOrNull(); } /// @@ -205,11 +200,12 @@ public sealed class ArtifactAnalyzerSystem : EntitySystem artifact = analyzer.LastAnalyzedArtifact; msg = GetArtifactScanMessage(analyzer); totalTime = analyzer.AnalysisDuration * analyzer.AnalysisDurationMulitplier; - canScan = analyzer.Contacts.Any(); + if (TryComp(component.AnalyzerEntity, out var placer)) + canScan = placer.PlacedEntities.Any(); canPrint = analyzer.ReadyToPrint; // the artifact that's actually on the scanner right now. - if (GetArtifactForAnalysis(component.AnalyzerEntity, analyzer) is { } current) + if (GetArtifactForAnalysis(component.AnalyzerEntity, placer) is { } current) points = _artifact.GetResearchPointValue(current); } var analyzerConnected = component.AnalyzerEntity != null; @@ -381,20 +377,6 @@ public sealed class ArtifactAnalyzerSystem : EntitySystem CancelScan(uid); } - /// - /// Checks to make sure that the currently scanned artifact isn't moved off of the scanner - /// - private void OnScannedMoved(EntityUid uid, ActiveScannedArtifactComponent component, ref MoveEvent args) - { - if (!TryComp(component.Scanner, out var analyzer)) - return; - - if (analyzer.Contacts.Contains(uid)) - return; - - CancelScan(uid, component, analyzer); - } - /// /// Stops the current scan /// @@ -448,27 +430,16 @@ public sealed class ArtifactAnalyzerSystem : EntitySystem args.AddPercentageUpgrade("analyzer-artifact-component-upgrade-analysis", component.AnalysisDurationMulitplier); } - private void OnCollide(EntityUid uid, ArtifactAnalyzerComponent component, ref StartCollideEvent args) + private void OnItemPlaced(EntityUid uid, ArtifactAnalyzerComponent component, ref ItemPlacedEvent args) { - var otherEnt = args.OtherEntity; - - if (!HasComp(otherEnt)) - return; - - component.Contacts.Add(otherEnt); - - if (component.Console != null) + if (component.Console != null && Exists(component.Console)) UpdateUserInterface(component.Console.Value); } - private void OnEndCollide(EntityUid uid, ArtifactAnalyzerComponent component, ref EndCollideEvent args) + private void OnItemRemoved(EntityUid uid, ArtifactAnalyzerComponent component, ref ItemRemovedEvent args) { - var otherEnt = args.OtherEntity; - - if (!HasComp(otherEnt)) - return; - component.Contacts.Remove(otherEnt); - + // cancel the scan if the artifact moves off the analyzer + CancelScan(args.OtherEntity); if (component.Console != null && Exists(component.Console)) UpdateUserInterface(component.Console.Value); } diff --git a/Content.Server/Xenoarchaeology/Equipment/Systems/TraversalDistorterSystem.cs b/Content.Server/Xenoarchaeology/Equipment/Systems/TraversalDistorterSystem.cs index e4617efb1b..5a1639de4c 100644 --- a/Content.Server/Xenoarchaeology/Equipment/Systems/TraversalDistorterSystem.cs +++ b/Content.Server/Xenoarchaeology/Equipment/Systems/TraversalDistorterSystem.cs @@ -5,7 +5,7 @@ using Content.Server.Xenoarchaeology.Equipment.Components; using Content.Server.Xenoarchaeology.XenoArtifacts; using Content.Shared.Examine; using Content.Shared.Interaction; -using Robust.Shared.Physics.Events; +using Content.Shared.Placeable; using Robust.Shared.Player; using Robust.Shared.Timing; @@ -13,8 +13,8 @@ namespace Content.Server.Xenoarchaeology.Equipment.Systems; public sealed class TraversalDistorterSystem : EntitySystem { - [Dependency] private readonly PopupSystem _popup = default!; [Dependency] private readonly IGameTiming _timing = default!; + [Dependency] private readonly PopupSystem _popup = default!; /// public override void Initialize() @@ -26,8 +26,8 @@ public sealed class TraversalDistorterSystem : EntitySystem SubscribeLocalEvent(OnRefreshParts); SubscribeLocalEvent(OnUpgradeExamine); - SubscribeLocalEvent(OnCollide); - SubscribeLocalEvent(OnEndCollide); + SubscribeLocalEvent(OnItemPlaced); + SubscribeLocalEvent(OnItemRemoved); } private void OnInit(EntityUid uid, TraversalDistorterComponent component, MapInitEvent args) @@ -88,24 +88,15 @@ public sealed class TraversalDistorterSystem : EntitySystem args.AddPercentageUpgrade("traversal-distorter-upgrade-bias", component.BiasChance / component.BaseBiasChance); } - private void OnCollide(EntityUid uid, TraversalDistorterComponent component, ref StartCollideEvent args) + private void OnItemPlaced(EntityUid uid, TraversalDistorterComponent component, ref ItemPlacedEvent args) { - var otherEnt = args.OtherEntity; - - if (!HasComp(otherEnt)) - return; - - var bias = EnsureComp(otherEnt); + var bias = EnsureComp(args.OtherEntity); bias.Provider = uid; } - private void OnEndCollide(EntityUid uid, TraversalDistorterComponent component, ref EndCollideEvent args) + private void OnItemRemoved(EntityUid uid, TraversalDistorterComponent component, ref ItemRemovedEvent args) { var otherEnt = args.OtherEntity; - - if (!HasComp(otherEnt)) - return; - if (TryComp(otherEnt, out var bias) && bias.Provider == uid) RemComp(otherEnt, bias); } diff --git a/Content.Shared/Placeable/ItemPlacerComponent.cs b/Content.Shared/Placeable/ItemPlacerComponent.cs new file mode 100644 index 0000000000..ce22f56492 --- /dev/null +++ b/Content.Shared/Placeable/ItemPlacerComponent.cs @@ -0,0 +1,31 @@ +using Content.Shared.Whitelist; +using Robust.Shared.GameStates; + +namespace Content.Shared.Placeable; + +/// +/// Detects items placed on it that match a whitelist. +/// +[RegisterComponent, NetworkedComponent, AutoGenerateComponentState, Access(typeof(ItemPlacerSystem))] +public sealed partial class ItemPlacerComponent : Component +{ + /// + /// The entities that are currently on top of the placer. + /// Guaranteed to have less than enitites if it is set. + /// + [DataField("placedEntities"), AutoNetworkedField] + public HashSet PlacedEntities = new(); + + /// + /// Whitelist for entities that can be placed. + /// + [DataField("whitelist"), ViewVariables(VVAccess.ReadWrite)] + public EntityWhitelist? Whitelist; + + /// + /// The max amount of entities that can be placed at the same time. + /// If 0, there is no limit. + /// + [ViewVariables(VVAccess.ReadWrite), DataField("maxEntities"), AutoNetworkedField] + public uint MaxEntities = 1; +} diff --git a/Content.Shared/Placeable/ItemPlacerSystem.cs b/Content.Shared/Placeable/ItemPlacerSystem.cs new file mode 100644 index 0000000000..83bb47b617 --- /dev/null +++ b/Content.Shared/Placeable/ItemPlacerSystem.cs @@ -0,0 +1,72 @@ +using Robust.Shared.Physics.Events; +using Robust.Shared.Physics.Systems; +using System.Linq; + +namespace Content.Shared.Placeable; + +/// +/// Tracks placed entities +/// Subscribe to or to do things when items or placed or removed. +/// +public sealed class ItemPlacerSystem : EntitySystem +{ + [Dependency] private readonly PlaceableSurfaceSystem _placeableSurface = default!; + [Dependency] private readonly SharedPhysicsSystem _physics = default!; + + public override void Initialize() + { + base.Initialize(); + + SubscribeLocalEvent(OnStartCollide); + SubscribeLocalEvent(OnEndCollide); + } + + private void OnStartCollide(EntityUid uid, ItemPlacerComponent comp, ref StartCollideEvent args) + { + if (comp.Whitelist != null && !comp.Whitelist.IsValid(args.OtherEntity)) + return; + + // Disallow sleeping so we can detect when entity is removed from the heater. + _physics.SetSleepingAllowed(args.OtherEntity, args.OtherBody, false); + + var count = comp.PlacedEntities.Count; + if (comp.MaxEntities == 0 || count < comp.MaxEntities) + { + comp.PlacedEntities.Add(args.OtherEntity); + + var ev = new ItemPlacedEvent(args.OtherEntity); + RaiseLocalEvent(uid, ref ev); + } + + if (comp.MaxEntities > 0 && count >= (comp.MaxEntities - 1)) + { + // Don't let any more items be placed if it's reached its limit. + _placeableSurface.SetPlaceable(uid, false); + } + } + + private void OnEndCollide(EntityUid uid, ItemPlacerComponent comp, ref EndCollideEvent args) + { + // Re-allow sleeping. + _physics.SetSleepingAllowed(args.OtherEntity, args.OtherBody, true); + + comp.PlacedEntities.Remove(args.OtherEntity); + + var ev = new ItemRemovedEvent(args.OtherEntity); + RaiseLocalEvent(uid, ref ev); + + _placeableSurface.SetPlaceable(uid, true); + } +} + +/// +/// Raised on the when an item is placed and it is under the item limit. +/// +[ByRefEvent] +public record struct ItemPlacedEvent(EntityUid OtherEntity); + +/// +/// Raised on the when an item is removed from it. +/// +[ByRefEvent] +public record struct ItemRemovedEvent(EntityUid OtherEntity); diff --git a/Resources/Prototypes/Entities/Structures/Machines/artifact_analyzer.yml b/Resources/Prototypes/Entities/Structures/Machines/artifact_analyzer.yml index 3244dd1541..d1cc01ea40 100644 --- a/Resources/Prototypes/Entities/Structures/Machines/artifact_analyzer.yml +++ b/Resources/Prototypes/Entities/Structures/Machines/artifact_analyzer.yml @@ -46,6 +46,10 @@ powerDrawMultiplier: 0.80 scaling: Exponential - type: ArtifactAnalyzer + - type: ItemPlacer + whitelist: + components: + - Artifact - type: DeviceNetwork deviceNetId: Wired receiveFrequencyId: BasicDevice @@ -109,6 +113,14 @@ powerDrawMultiplier: 0.80 scaling: Exponential - type: TraversalDistorter + - type: ItemPlacer + # don't limit the number of artifacts that can be biased + maxEntities: 0 + whitelist: + components: + - Artifact + - type: PlaceableSurface + placeCentered: true - type: Machine board: TraversalDistorterMachineCircuitboard - type: Appearance diff --git a/Resources/Prototypes/Entities/Structures/Machines/hotplate.yml b/Resources/Prototypes/Entities/Structures/Machines/hotplate.yml index 0c5fa3989a..c5ed1de80c 100644 --- a/Resources/Prototypes/Entities/Structures/Machines/hotplate.yml +++ b/Resources/Prototypes/Entities/Structures/Machines/hotplate.yml @@ -38,6 +38,7 @@ components: - FitsInDispenser - type: SolutionHeater + - type: ItemPlacer whitelist: components: - FitsInDispenser