From d805704a1f176707923d53d1db26ff869f4b2a51 Mon Sep 17 00:00:00 2001
From: Kyle Tyo <36606155+VerinSenpai@users.noreply.github.com>
Date: Fri, 1 Aug 2025 13:40:15 -0400
Subject: [PATCH] Predict EmitterSystem ExamineEvent and GetVerbsEvent (#39318)
* ididathing.exe
* commit
* cleanup
---------
Co-authored-by: slarticodefast <161409025+slarticodefast@users.noreply.github.com>
---
.../Singularity/Systems/EmitterSystem.cs | 2 +
.../EntitySystems/EmitterSystem.cs | 47 --------------
.../Components/SharedEmitterComponent.cs | 38 ++++++------
.../EntitySystems/SharedEmitterSystem.cs | 62 ++++++++++++++++++-
4 files changed, 81 insertions(+), 68 deletions(-)
diff --git a/Content.Client/Singularity/Systems/EmitterSystem.cs b/Content.Client/Singularity/Systems/EmitterSystem.cs
index e9e0846340..b35c3297a1 100644
--- a/Content.Client/Singularity/Systems/EmitterSystem.cs
+++ b/Content.Client/Singularity/Systems/EmitterSystem.cs
@@ -12,6 +12,8 @@ public sealed class EmitterSystem : SharedEmitterSystem
///
public override void Initialize()
{
+ base.Initialize();
+
SubscribeLocalEvent(OnAppearanceChange);
}
diff --git a/Content.Server/Singularity/EntitySystems/EmitterSystem.cs b/Content.Server/Singularity/EntitySystems/EmitterSystem.cs
index 662df43e12..28d3eedd32 100644
--- a/Content.Server/Singularity/EntitySystems/EmitterSystem.cs
+++ b/Content.Server/Singularity/EntitySystems/EmitterSystem.cs
@@ -7,7 +7,6 @@ using Content.Server.Projectiles;
using Content.Server.Weapons.Ranged.Systems;
using Content.Shared.Database;
using Content.Shared.DeviceLinking.Events;
-using Content.Shared.Examine;
using Content.Shared.Interaction;
using Content.Shared.Lock;
using Content.Shared.Popups;
@@ -15,9 +14,7 @@ using Content.Shared.Power;
using Content.Shared.Projectiles;
using Content.Shared.Singularity.Components;
using Content.Shared.Singularity.EntitySystems;
-using Content.Shared.Verbs;
using Content.Shared.Weapons.Ranged.Components;
-using JetBrains.Annotations;
using Robust.Shared.Map;
using Robust.Shared.Physics;
using Robust.Shared.Physics.Components;
@@ -28,7 +25,6 @@ using Timer = Robust.Shared.Timing.Timer;
namespace Content.Server.Singularity.EntitySystems
{
- [UsedImplicitly]
public sealed class EmitterSystem : SharedEmitterSystem
{
[Dependency] private readonly IRobustRandom _random = default!;
@@ -46,8 +42,6 @@ namespace Content.Server.Singularity.EntitySystems
SubscribeLocalEvent(ReceivedChanged);
SubscribeLocalEvent(OnApcChanged);
SubscribeLocalEvent(OnActivate);
- SubscribeLocalEvent>(OnGetVerb);
- SubscribeLocalEvent(OnExamined);
SubscribeLocalEvent(OnAnchorStateChanged);
SubscribeLocalEvent(OnSignalReceived);
}
@@ -99,47 +93,6 @@ namespace Content.Server.Singularity.EntitySystems
}
}
- private void OnGetVerb(EntityUid uid, EmitterComponent component, GetVerbsEvent args)
- {
- if (!args.CanAccess || !args.CanInteract || !args.CanComplexInteract || args.Hands == null)
- return;
-
- if (TryComp(uid, out var lockComp) && lockComp.Locked)
- return;
-
- if (component.SelectableTypes.Count < 2)
- return;
-
- foreach (var type in component.SelectableTypes)
- {
- var proto = _prototype.Index(type);
-
- var v = new Verb
- {
- Priority = 1,
- Category = VerbCategory.SelectType,
- Text = proto.Name,
- Disabled = type == component.BoltType,
- Impact = LogImpact.Medium,
- DoContactInteraction = true,
- Act = () =>
- {
- component.BoltType = type;
- _popup.PopupEntity(Loc.GetString("emitter-component-type-set", ("type", proto.Name)), uid);
- }
- };
- args.Verbs.Add(v);
- }
- }
-
- private void OnExamined(EntityUid uid, EmitterComponent component, ExaminedEvent args)
- {
- if (component.SelectableTypes.Count < 2)
- return;
- var proto = _prototype.Index(component.BoltType);
- args.PushMarkup(Loc.GetString("emitter-component-current-type", ("type", proto.Name)));
- }
-
private void ReceivedChanged(
EntityUid uid,
EmitterComponent component,
diff --git a/Content.Shared/Singularity/Components/SharedEmitterComponent.cs b/Content.Shared/Singularity/Components/SharedEmitterComponent.cs
index dce2f92d0c..d181757968 100644
--- a/Content.Shared/Singularity/Components/SharedEmitterComponent.cs
+++ b/Content.Shared/Singularity/Components/SharedEmitterComponent.cs
@@ -3,12 +3,10 @@ using Content.Shared.DeviceLinking;
using Robust.Shared.GameStates;
using Robust.Shared.Prototypes;
using Robust.Shared.Serialization;
-using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
-using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.Dictionary;
namespace Content.Shared.Singularity.Components;
-[RegisterComponent, NetworkedComponent]
+[RegisterComponent, NetworkedComponent, AutoGenerateComponentState]
public sealed partial class EmitterComponent : Component
{
public CancellationTokenSource? TimerCancel;
@@ -27,8 +25,8 @@ public sealed partial class EmitterComponent : Component
///
/// The entity that is spawned when the emitter fires.
///
- [DataField("boltType", customTypeSerializer: typeof(PrototypeIdSerializer))]
- public string BoltType = "EmitterBolt";
+ [DataField, AutoNetworkedField]
+ public EntProtoId BoltType = "EmitterBolt";
[DataField]
public List SelectableTypes = new();
@@ -36,68 +34,68 @@ public sealed partial class EmitterComponent : Component
///
/// The current amount of power being used.
///
- [DataField("powerUseActive")]
+ [DataField]
public int PowerUseActive = 600;
///
/// The amount of shots that are fired in a single "burst"
///
- [DataField("fireBurstSize")]
+ [DataField]
public int FireBurstSize = 3;
///
/// The time between each shot during a burst.
///
- [DataField("fireInterval")]
+ [DataField]
public TimeSpan FireInterval = TimeSpan.FromSeconds(2);
///
/// The current minimum delay between bursts.
///
- [DataField("fireBurstDelayMin")]
+ [DataField]
public TimeSpan FireBurstDelayMin = TimeSpan.FromSeconds(4);
///
/// The current maximum delay between bursts.
///
- [DataField("fireBurstDelayMax")]
+ [DataField]
public TimeSpan FireBurstDelayMax = TimeSpan.FromSeconds(10);
///
/// The visual state that is set when the emitter is turned on
///
- [DataField("onState")]
+ [DataField]
public string? OnState = "beam";
///
/// The visual state that is set when the emitter doesn't have enough power.
///
- [DataField("underpoweredState")]
+ [DataField]
public string? UnderpoweredState = "underpowered";
///
/// Signal port that turns on the emitter.
///
- [DataField("onPort", customTypeSerializer: typeof(PrototypeIdSerializer))]
- public string OnPort = "On";
+ [DataField]
+ public ProtoId OnPort = "On";
///
/// Signal port that turns off the emitter.
///
- [DataField("offPort", customTypeSerializer: typeof(PrototypeIdSerializer))]
- public string OffPort = "Off";
+ [DataField]
+ public ProtoId OffPort = "Off";
///
/// Signal port that toggles the emitter on or off.
///
- [DataField("togglePort", customTypeSerializer: typeof(PrototypeIdSerializer))]
- public string TogglePort = "Toggle";
+ [DataField]
+ public ProtoId TogglePort = "Toggle";
///
/// Map of signal ports to entity prototype IDs of the entity that will be fired.
///
- [DataField("setTypePorts", customTypeSerializer: typeof(PrototypeIdDictionarySerializer))]
- public Dictionary SetTypePorts = new();
+ [DataField]
+ public Dictionary, EntProtoId> SetTypePorts = new();
}
[NetSerializable, Serializable]
diff --git a/Content.Shared/Singularity/EntitySystems/SharedEmitterSystem.cs b/Content.Shared/Singularity/EntitySystems/SharedEmitterSystem.cs
index bba6629988..9ef7dcfbdb 100644
--- a/Content.Shared/Singularity/EntitySystems/SharedEmitterSystem.cs
+++ b/Content.Shared/Singularity/EntitySystems/SharedEmitterSystem.cs
@@ -1,6 +1,66 @@
-namespace Content.Shared.Singularity.EntitySystems;
+using Content.Shared.Database;
+using Content.Shared.Examine;
+using Content.Shared.Lock;
+using Content.Shared.Popups;
+using Content.Shared.Singularity.Components;
+using Content.Shared.Verbs;
+using Robust.Shared.Prototypes;
+
+namespace Content.Shared.Singularity.EntitySystems;
public abstract class SharedEmitterSystem : EntitySystem
{
+ [Dependency] private readonly IPrototypeManager _prototype = default!;
+ [Dependency] private readonly SharedPopupSystem _popup = default!;
+ public override void Initialize()
+ {
+ base.Initialize();
+
+ SubscribeLocalEvent(OnExamined);
+ SubscribeLocalEvent>(OnGetVerb);
+ }
+
+ private void OnGetVerb(Entity ent, ref GetVerbsEvent args)
+ {
+ if (!args.CanAccess || !args.CanInteract || !args.CanComplexInteract || args.Hands == null)
+ return;
+
+ if (TryComp(ent.Owner, out var lockComp) && lockComp.Locked)
+ return;
+
+ if (ent.Comp.SelectableTypes.Count < 2)
+ return;
+
+ foreach (var type in ent.Comp.SelectableTypes)
+ {
+ var proto = _prototype.Index(type);
+
+ var v = new Verb
+ {
+ Priority = 1,
+ Category = VerbCategory.SelectType,
+ Text = proto.Name,
+ Disabled = type == ent.Comp.BoltType,
+ Impact = LogImpact.Medium,
+ DoContactInteraction = true,
+ Act = () =>
+ {
+ ent.Comp.BoltType = type;
+ Dirty(ent);
+ _popup.PopupClient(Loc.GetString("emitter-component-type-set", ("type", proto.Name)), ent.Owner);
+ },
+ };
+ args.Verbs.Add(v);
+ }
+ }
+
+ private void OnExamined(Entity ent, ref ExaminedEvent args)
+ {
+ if (ent.Comp.SelectableTypes.Count < 2)
+ return;
+
+ var proto = _prototype.Index(ent.Comp.BoltType);
+ args.PushMarkup(Loc.GetString("emitter-component-current-type", ("type", proto.Name)));
+ }
}