diff --git a/Content.Client/Maps/GridDraggingCommand.cs b/Content.Client/Maps/GridDraggingCommand.cs index eb8579aa5f..daea5674dc 100644 --- a/Content.Client/Maps/GridDraggingCommand.cs +++ b/Content.Client/Maps/GridDraggingCommand.cs @@ -13,6 +13,12 @@ public sealed class GridDraggingCommand : IConsoleCommand public string Help => $"{Command}"; public void Execute(IConsoleShell shell, string argStr, string[] args) { - IoCManager.Resolve().GetEntitySystem().Enabled ^= true; + var system = IoCManager.Resolve().GetEntitySystem(); + system.Enabled ^= true; + + if (system.Enabled) + shell.WriteLine("Grid dragging toggled on"); + else + shell.WriteLine("Grid dragging toggled off"); } } diff --git a/Content.Client/Weapons/Ranged/TetherGunCommand.cs b/Content.Client/Weapons/Ranged/TetherGunCommand.cs index 7c030304d5..4a9609addf 100644 --- a/Content.Client/Weapons/Ranged/TetherGunCommand.cs +++ b/Content.Client/Weapons/Ranged/TetherGunCommand.cs @@ -9,6 +9,12 @@ public sealed class TetherGunCommand : IConsoleCommand public string Help => $"{Command}"; public void Execute(IConsoleShell shell, string argStr, string[] args) { - IoCManager.Resolve().GetEntitySystem().Enabled ^= true; + var system = IoCManager.Resolve().GetEntitySystem(); + system.Enabled ^= true; + + if (system.Enabled) + shell.WriteLine("Tether gun toggled on"); + else + shell.WriteLine("Tether gun toggled off"); } } diff --git a/Content.Client/Weapons/Ranged/TetherGunSystem.cs b/Content.Client/Weapons/Ranged/TetherGunSystem.cs index 0736ecec0b..67a0e1a2d8 100644 --- a/Content.Client/Weapons/Ranged/TetherGunSystem.cs +++ b/Content.Client/Weapons/Ranged/TetherGunSystem.cs @@ -23,9 +23,36 @@ public sealed class TetherGunSystem : SharedTetherGunSystem /// The entity being dragged around. /// private EntityUid? _dragging; + private EntityUid? _tether; private MapCoordinates? _lastMousePosition; + public override void Initialize() + { + base.Initialize(); + SubscribeNetworkEvent(OnPredictTether); + } + + private void OnPredictTether(PredictTetherEvent ev) + { + if (_dragging != ev.Entity) return; + + _tether = ev.Entity; + } + + public override void FrameUpdate(float frameTime) + { + base.FrameUpdate(frameTime); + if (!TryComp(_dragging, out var body)) return; + + body.Predict = true; + + if (TryComp(_tether, out var tetherBody)) + { + tetherBody.Predict = true; + } + } + public override void Update(float frameTime) { base.Update(frameTime); @@ -46,18 +73,18 @@ public sealed class TetherGunSystem : SharedTetherGunSystem if (_dragging == null) { var bodyQuery = GetEntityQuery(); - var lowest = new List<(int DrawDepth, EntityUid Entity)>(); + var lowest = new List<(int DrawDepth, uint RenderOrder, EntityUid Entity)>(); - foreach (var ent in _lookup.GetEntitiesIntersecting(mousePos)) + foreach (var ent in _lookup.GetEntitiesIntersecting(mousePos, LookupFlags.Approximate | LookupFlags.Anchored)) { if (!bodyQuery.HasComponent(ent) || !TryComp(ent, out var clickable) || - !clickable.CheckClick(mousePos.Position, out var drawDepth, out _)) continue; + !clickable.CheckClick(mousePos.Position, out var drawDepth, out var renderOrder)) continue; - lowest.Add((drawDepth, ent)); + lowest.Add((drawDepth, renderOrder, ent)); } - lowest.Sort((x, y) => y.DrawDepth.CompareTo(x.DrawDepth)); + lowest.Sort((x, y) => y.DrawDepth == x.DrawDepth ? y.RenderOrder.CompareTo(x.RenderOrder) : y.DrawDepth.CompareTo(x.DrawDepth)); foreach (var ent in lowest) { @@ -69,12 +96,20 @@ public sealed class TetherGunSystem : SharedTetherGunSystem } if (!TryComp(_dragging!.Value, out var xform) || - _lastMousePosition!.Value.MapId != xform.MapID) + _lastMousePosition!.Value.MapId != xform.MapID || + !TryComp(_dragging, out var body)) { StopDragging(); return; } + body.Predict = true; + + if (TryComp(_tether, out var tetherBody)) + { + tetherBody.Predict = true; + } + if (_lastMousePosition.Value.Position.EqualsApprox(mousePos.Position)) return; _lastMousePosition = mousePos; @@ -92,6 +127,7 @@ public sealed class TetherGunSystem : SharedTetherGunSystem RaiseNetworkEvent(new StopTetherEvent()); _dragging = null; _lastMousePosition = null; + _tether = null; } private void StartDragging(EntityUid uid, MapCoordinates coordinates) diff --git a/Content.Server/Weapon/Ranged/TetherGunSystem.cs b/Content.Server/Weapon/Ranged/TetherGunSystem.cs index d93d132ced..7dbb7526c8 100644 --- a/Content.Server/Weapon/Ranged/TetherGunSystem.cs +++ b/Content.Server/Weapon/Ranged/TetherGunSystem.cs @@ -1,3 +1,4 @@ +using Content.Server.Ghost.Components; using Content.Shared.Administration; using Content.Shared.Weapons.Ranged; using Robust.Server.Console; @@ -52,8 +53,7 @@ public sealed class TetherGunSystem : SharedTetherGunSystem !Exists(msg.Entity) || Deleted(msg.Entity) || msg.Coordinates == MapCoordinates.Nullspace || - _tethered.ContainsKey(args.SenderSession) || - _container.IsEntityInContainer(msg.Entity)) return; + _tethered.ContainsKey(args.SenderSession)) return; var tether = Spawn("TetherEntity", msg.Coordinates); @@ -71,6 +71,11 @@ public sealed class TetherGunSystem : SharedTetherGunSystem xform.Anchored = false; } + if (_container.IsEntityInContainer(msg.Entity)) + { + xform?.AttachToGridOrMap(); + } + if (TryComp(msg.Entity, out var body)) { body.BodyStatus = BodyStatus.InAir; @@ -81,9 +86,13 @@ public sealed class TetherGunSystem : SharedTetherGunSystem SharedJointSystem.LinearStiffness(5f, 0.7f, bodyA.Mass, bodyB.Mass, out var stiffness, out var damping); joint.Stiffness = stiffness; joint.Damping = damping; - joint.MaxForce = 5000f * bodyB.Mass; + joint.MaxForce = 10000f * bodyB.Mass; _tethered.Add(playerSession, (msg.Entity, tether, joint)); + RaiseNetworkEvent(new PredictTetherEvent() + { + Entity = msg.Entity + }, args.SenderSession.ConnectedClient); } private void OnStopTether(StopTetherEvent msg, EntitySessionEventArgs args) @@ -98,7 +107,8 @@ public sealed class TetherGunSystem : SharedTetherGunSystem RemComp(weh.Entity); - if (TryComp(weh.Entity, out var body)) + if (TryComp(weh.Entity, out var body) && + !HasComp(weh.Entity)) { Timer.Spawn(1000, () => { diff --git a/Content.Shared/Audio/AmbientSoundComponent.cs b/Content.Shared/Audio/AmbientSoundComponent.cs index 39c31af34d..3163dcb701 100644 --- a/Content.Shared/Audio/AmbientSoundComponent.cs +++ b/Content.Shared/Audio/AmbientSoundComponent.cs @@ -12,7 +12,7 @@ namespace Content.Shared.Audio [DataField("enabled")] public bool Enabled { get; set; } = true; - [DataField("sound", required: true)] + [DataField("sound", required: true), ViewVariables(VVAccess.ReadWrite)] public SoundSpecifier Sound = default!; /// diff --git a/Content.Shared/Weapons/Ranged/SharedTetherGunSystem.cs b/Content.Shared/Weapons/Ranged/SharedTetherGunSystem.cs index c871298c6a..ff937d4deb 100644 --- a/Content.Shared/Weapons/Ranged/SharedTetherGunSystem.cs +++ b/Content.Shared/Weapons/Ranged/SharedTetherGunSystem.cs @@ -23,3 +23,12 @@ public sealed class TetherMoveEvent : EntityEventArgs { public MapCoordinates Coordinates; } + +/// +/// Client can't know the tether's in advance so needs to be told about it for prediction. +/// +[Serializable, NetSerializable] +public sealed class PredictTetherEvent : EntityEventArgs +{ + public EntityUid Entity; +}