From: slarticodefast <161409025+slarticodefast@users.noreply.github.com> Date: Mon, 5 Jan 2026 12:17:17 +0000 (+0100) Subject: Predict thieving beacon (#39610) X-Git-Url: https://git.smokeofanarchy.ru/gitweb.cgi?a=commitdiff_plain;h=71c3fa8fd732bc7b4f4444713ee12934d330d8e2;p=space-station-14.git Predict thieving beacon (#39610) predict thieving beacon --- diff --git a/Content.Server/Objectives/Components/StealAreaComponent.cs b/Content.Server/Objectives/Components/StealAreaComponent.cs deleted file mode 100644 index 26e752f2f2..0000000000 --- a/Content.Server/Objectives/Components/StealAreaComponent.cs +++ /dev/null @@ -1,23 +0,0 @@ -using Content.Server.Objectives.Systems; -using Content.Server.Thief.Systems; - -namespace Content.Server.Objectives.Components; - -/// -/// An abstract component that allows other systems to count adjacent objects as "stolen" when controlling other systems -/// -[RegisterComponent, Access(typeof(StealConditionSystem), typeof(ThiefBeaconSystem))] -public sealed partial class StealAreaComponent : Component -{ - [DataField] - public bool Enabled = true; - - [DataField] - public float Range = 1f; - - /// - /// all the minds that will be credited with stealing from this area. - /// - [DataField] - public HashSet Owners = new(); -} diff --git a/Content.Shared/Foldable/DeployFoldableSystem.cs b/Content.Shared/Foldable/DeployFoldableSystem.cs index c690f3d51f..8b510664e4 100644 --- a/Content.Shared/Foldable/DeployFoldableSystem.cs +++ b/Content.Shared/Foldable/DeployFoldableSystem.cs @@ -37,7 +37,7 @@ public sealed class DeployFoldableSystem : EntitySystem private void OnDragDropDragged(Entity ent, ref DragDropDraggedEvent args) { if (!TryComp(ent, out var foldable) - || !_foldable.TrySetFolded(ent, foldable, true)) + || !_foldable.TrySetFolded(ent, foldable, true, args.User)) return; _hands.PickupOrDrop(args.User, ent.Owner); @@ -77,7 +77,7 @@ public sealed class DeployFoldableSystem : EntitySystem || !_hands.TryDrop((args.User, hands), args.Used, targetDropLocation: args.ClickLocation)) return; - if (!_foldable.TrySetFolded(ent, foldable, false)) + if (!_foldable.TrySetFolded(ent, foldable, false, args.User)) { _hands.TryPickup(args.User, args.Used, handsComp: hands); return; diff --git a/Content.Shared/Foldable/FoldableSystem.cs b/Content.Shared/Foldable/FoldableSystem.cs index 63ef376d5f..acfec8ac1f 100644 --- a/Content.Shared/Foldable/FoldableSystem.cs +++ b/Content.Shared/Foldable/FoldableSystem.cs @@ -78,14 +78,14 @@ public sealed class FoldableSystem : EntitySystem /// /// Set the folded state of the given /// - public void SetFolded(EntityUid uid, FoldableComponent component, bool folded) + public void SetFolded(EntityUid uid, FoldableComponent component, bool folded, EntityUid? user = null) { component.IsFolded = folded; Dirty(uid, component); _appearance.SetData(uid, FoldedVisuals.State, folded); _buckle.StrapSetEnabled(uid, !component.IsFolded); - var ev = new FoldedEvent(folded); + var ev = new FoldedEvent(folded, user); RaiseLocalEvent(uid, ref ev); } @@ -97,7 +97,7 @@ public sealed class FoldableSystem : EntitySystem public bool TryToggleFold(EntityUid uid, FoldableComponent comp, EntityUid? folder = null) { - var result = TrySetFolded(uid, comp, !comp.IsFolded); + var result = TrySetFolded(uid, comp, !comp.IsFolded, folder); if (!result && folder != null) { if (comp.IsFolded) @@ -129,7 +129,7 @@ public sealed class FoldableSystem : EntitySystem /// /// Try to fold/unfold /// - public bool TrySetFolded(EntityUid uid, FoldableComponent comp, bool state) + public bool TrySetFolded(EntityUid uid, FoldableComponent comp, bool state, EntityUid? user = null) { if (state == comp.IsFolded) return false; @@ -137,7 +137,7 @@ public sealed class FoldableSystem : EntitySystem if (!CanToggleFold(uid, comp)) return false; - SetFolded(uid, comp, state); + SetFolded(uid, comp, state, user); return true; } @@ -180,6 +180,7 @@ public record struct FoldAttemptEvent(FoldableComponent Comp, bool Cancelled = f /// /// Event raised on an entity after it has been folded. /// -/// +/// True is it has been folded, false if it has been unfolded. +/// The player who did the folding. [ByRefEvent] -public readonly record struct FoldedEvent(bool IsFolded); +public readonly record struct FoldedEvent(bool IsFolded, EntityUid? User); diff --git a/Content.Shared/Objectives/Components/StealAreaComponent.cs b/Content.Shared/Objectives/Components/StealAreaComponent.cs new file mode 100644 index 0000000000..50e9d328ac --- /dev/null +++ b/Content.Shared/Objectives/Components/StealAreaComponent.cs @@ -0,0 +1,38 @@ +using Robust.Shared.GameStates; + +namespace Content.Shared.Objectives.Components; + +/// +/// An abstract component that allows other systems to count adjacent objects as "stolen" when controlling other systems +/// +[RegisterComponent, NetworkedComponent, AutoGenerateComponentState] +public sealed partial class StealAreaComponent : Component +{ + /// + /// Is the component currently enabled? + /// + [DataField, AutoNetworkedField] + public bool Enabled = true; + + /// + /// The range to check for items in. + /// + [DataField, AutoNetworkedField] + public float Range = 1f; + + /// + /// All the minds that will be credited with stealing from this area. + /// + /// + /// TODO: Network this when we have WeakEntityReference. + /// + [DataField] + public HashSet Owners = new(); + + /// + /// The count of the owner hashset. + /// This is a separate datafield because networking the list would cause PVS errors if an entity inside would be deleted and networked. + /// + [DataField, AutoNetworkedField] + public int OwnerCount = 0; +} diff --git a/Content.Server/Thief/Components/ThiefBeaconComponent.cs b/Content.Shared/Thief/Components/ThiefBeaconComponent.cs similarity index 71% rename from Content.Server/Thief/Components/ThiefBeaconComponent.cs rename to Content.Shared/Thief/Components/ThiefBeaconComponent.cs index 65db79f861..5701254c98 100644 --- a/Content.Server/Thief/Components/ThiefBeaconComponent.cs +++ b/Content.Shared/Thief/Components/ThiefBeaconComponent.cs @@ -1,12 +1,14 @@ -using Content.Server.Thief.Systems; +using Content.Shared.Thief.Systems; using Robust.Shared.Audio; +using Robust.Shared.GameStates; -namespace Content.Server.Thief.Components; +namespace Content.Shared.Thief.Components; /// /// working together with StealAreaComponent, allows the thief to count objects near the beacon as stolen when setting up. /// -[RegisterComponent, Access(typeof(ThiefBeaconSystem))] +[RegisterComponent, NetworkedComponent] +[Access(typeof(ThiefBeaconSystem))] public sealed partial class ThiefBeaconComponent : Component { [DataField] diff --git a/Content.Server/Thief/Systems/ThiefBeaconSystem.cs b/Content.Shared/Thief/Systems/ThiefBeaconSystem.cs similarity index 70% rename from Content.Server/Thief/Systems/ThiefBeaconSystem.cs rename to Content.Shared/Thief/Systems/ThiefBeaconSystem.cs index 069966a8a4..bff33cb781 100644 --- a/Content.Server/Thief/Systems/ThiefBeaconSystem.cs +++ b/Content.Shared/Thief/Systems/ThiefBeaconSystem.cs @@ -1,15 +1,15 @@ -using Content.Server.Mind; -using Content.Server.Objectives.Components; -using Content.Server.Thief.Components; +using Content.Shared.Mind; +using Content.Shared.Objectives.Components; +using Content.Shared.Roles; +using Content.Shared.Thief.Components; using Content.Shared.Examine; using Content.Shared.Foldable; using Content.Shared.Popups; using Content.Shared.Verbs; -using Content.Shared.Roles; using Content.Shared.Roles.Components; using Robust.Shared.Audio.Systems; -namespace Content.Server.Thief.Systems; +namespace Content.Shared.Thief.Systems; /// /// @@ -18,7 +18,7 @@ public sealed class ThiefBeaconSystem : EntitySystem { [Dependency] private readonly SharedAudioSystem _audio = default!; [Dependency] private readonly SharedPopupSystem _popup = default!; - [Dependency] private readonly MindSystem _mind = default!; + [Dependency] private readonly SharedMindSystem _mind = default!; [Dependency] private readonly SharedRoleSystem _roles = default!; public override void Initialize() { @@ -46,7 +46,7 @@ public sealed class ThiefBeaconSystem : EntitySystem { Act = () => { - SetCoordinate(beacon, mind.Value); + SetCoordinate(beacon, mind.Value, user); }, Message = Loc.GetString("thief-fulton-verb-message"), Text = Loc.GetString("thief-fulton-verb-text"), @@ -56,7 +56,7 @@ public sealed class ThiefBeaconSystem : EntitySystem private void OnFolded(Entity beacon, ref FoldedEvent args) { if (args.IsFolded) - ClearCoordinate(beacon); + ClearCoordinate(beacon, args.User); } private void OnExamined(Entity beacon, ref ExaminedEvent args) @@ -64,23 +64,25 @@ public sealed class ThiefBeaconSystem : EntitySystem if (!TryComp(beacon, out var area)) return; - args.PushText(Loc.GetString(area.Owners.Count == 0 + args.PushText(Loc.GetString(area.OwnerCount == 0 ? "thief-fulton-examined-unset" : "thief-fulton-examined-set")); } - private void SetCoordinate(Entity beacon, EntityUid mind) + private void SetCoordinate(Entity beacon, EntityUid mind, EntityUid? user = null) { if (!TryComp(beacon, out var area)) return; - _audio.PlayPvs(beacon.Comp.LinkSound, beacon); - _popup.PopupEntity(Loc.GetString("thief-fulton-set"), beacon); - area.Owners.Clear(); //We only reconfigure the beacon for ourselves, we don't need multiple thieves to steal from the same beacon. + _audio.PlayPredicted(beacon.Comp.LinkSound, beacon, user); + _popup.PopupClient(Loc.GetString("thief-fulton-set"), beacon, user); + area.Owners.Clear(); // We only reconfigure the beacon for ourselves, we don't need multiple thieves to steal from the same beacon. area.Owners.Add(mind); + area.OwnerCount = area.Owners.Count; + Dirty(beacon.Owner, area); } - private void ClearCoordinate(Entity beacon) + private void ClearCoordinate(Entity beacon, EntityUid? user = null) { if (!TryComp(beacon, out var area)) return; @@ -88,8 +90,10 @@ public sealed class ThiefBeaconSystem : EntitySystem if (area.Owners.Count == 0) return; - _audio.PlayPvs(beacon.Comp.UnlinkSound, beacon); - _popup.PopupEntity(Loc.GetString("thief-fulton-clear"), beacon); + _audio.PlayPredicted(beacon.Comp.UnlinkSound, beacon, user); + _popup.PopupClient(Loc.GetString("thief-fulton-clear"), beacon, user); area.Owners.Clear(); + area.OwnerCount = area.Owners.Count; + Dirty(beacon.Owner, area); } }