+++ /dev/null
-using Content.Server.Objectives.Systems;
-using Content.Server.Thief.Systems;
-
-namespace Content.Server.Objectives.Components;
-
-/// <summary>
-/// An abstract component that allows other systems to count adjacent objects as "stolen" when controlling other systems
-/// </summary>
-[RegisterComponent, Access(typeof(StealConditionSystem), typeof(ThiefBeaconSystem))]
-public sealed partial class StealAreaComponent : Component
-{
- [DataField]
- public bool Enabled = true;
-
- [DataField]
- public float Range = 1f;
-
- /// <summary>
- /// all the minds that will be credited with stealing from this area.
- /// </summary>
- [DataField]
- public HashSet<EntityUid> Owners = new();
-}
private void OnDragDropDragged(Entity<DeployFoldableComponent> ent, ref DragDropDraggedEvent args)
{
if (!TryComp<FoldableComponent>(ent, out var foldable)
- || !_foldable.TrySetFolded(ent, foldable, true))
+ || !_foldable.TrySetFolded(ent, foldable, true, args.User))
return;
_hands.PickupOrDrop(args.User, ent.Owner);
|| !_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;
/// <summary>
/// Set the folded state of the given <see cref="FoldableComponent"/>
/// </summary>
- 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);
}
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)
/// <summary>
/// Try to fold/unfold
/// </summary>
- 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;
if (!CanToggleFold(uid, comp))
return false;
- SetFolded(uid, comp, state);
+ SetFolded(uid, comp, state, user);
return true;
}
/// <summary>
/// Event raised on an entity after it has been folded.
/// </summary>
-/// <param name="IsFolded"></param>
+/// <param name="IsFolded">True is it has been folded, false if it has been unfolded.</param>
+/// <param name="User">The player who did the folding.</param>
[ByRefEvent]
-public readonly record struct FoldedEvent(bool IsFolded);
+public readonly record struct FoldedEvent(bool IsFolded, EntityUid? User);
--- /dev/null
+using Robust.Shared.GameStates;
+
+namespace Content.Shared.Objectives.Components;
+
+/// <summary>
+/// An abstract component that allows other systems to count adjacent objects as "stolen" when controlling other systems
+/// </summary>
+[RegisterComponent, NetworkedComponent, AutoGenerateComponentState]
+public sealed partial class StealAreaComponent : Component
+{
+ /// <summary>
+ /// Is the component currently enabled?
+ /// </summary>
+ [DataField, AutoNetworkedField]
+ public bool Enabled = true;
+
+ /// <summary>
+ /// The range to check for items in.
+ /// </summary>
+ [DataField, AutoNetworkedField]
+ public float Range = 1f;
+
+ /// <summary>
+ /// All the minds that will be credited with stealing from this area.
+ /// </summary>
+ /// <remarks>
+ /// TODO: Network this when we have WeakEntityReference.
+ /// </remarks>
+ [DataField]
+ public HashSet<EntityUid> Owners = new();
+
+ /// <summary>
+ /// 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.
+ /// </summary>
+ [DataField, AutoNetworkedField]
+ public int OwnerCount = 0;
+}
-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;
/// <summary>
/// working together with StealAreaComponent, allows the thief to count objects near the beacon as stolen when setting up.
/// </summary>
-[RegisterComponent, Access(typeof(ThiefBeaconSystem))]
+[RegisterComponent, NetworkedComponent]
+[Access(typeof(ThiefBeaconSystem))]
public sealed partial class ThiefBeaconComponent : Component
{
[DataField]
-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;
/// <summary>
/// <see cref="ThiefBeaconComponent"/>
{
[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()
{
{
Act = () =>
{
- SetCoordinate(beacon, mind.Value);
+ SetCoordinate(beacon, mind.Value, user);
},
Message = Loc.GetString("thief-fulton-verb-message"),
Text = Loc.GetString("thief-fulton-verb-text"),
private void OnFolded(Entity<ThiefBeaconComponent> beacon, ref FoldedEvent args)
{
if (args.IsFolded)
- ClearCoordinate(beacon);
+ ClearCoordinate(beacon, args.User);
}
private void OnExamined(Entity<ThiefBeaconComponent> beacon, ref ExaminedEvent args)
if (!TryComp<StealAreaComponent>(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<ThiefBeaconComponent> beacon, EntityUid mind)
+ private void SetCoordinate(Entity<ThiefBeaconComponent> beacon, EntityUid mind, EntityUid? user = null)
{
if (!TryComp<StealAreaComponent>(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<ThiefBeaconComponent> beacon)
+ private void ClearCoordinate(Entity<ThiefBeaconComponent> beacon, EntityUid? user = null)
{
if (!TryComp<StealAreaComponent>(beacon, out var area))
return;
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);
}
}