From fa333efd4608cfb06412bf4fa80199c04a9046c1 Mon Sep 17 00:00:00 2001 From: ElectroJr Date: Sun, 19 May 2024 20:03:08 +1200 Subject: [PATCH 1/9] Update GasTileOverlayState --- .../EntitySystems/GasTileOverlaySystem.cs | 39 ++++++++++++------- .../Components/GasTileOverlayComponent.cs | 38 +++++++----------- .../SharedGasTileOverlaySystem.cs | 2 +- 3 files changed, 41 insertions(+), 38 deletions(-) diff --git a/Content.Client/Atmos/EntitySystems/GasTileOverlaySystem.cs b/Content.Client/Atmos/EntitySystems/GasTileOverlaySystem.cs index 78185ce6b0e6..86cf0a9eb824 100644 --- a/Content.Client/Atmos/EntitySystems/GasTileOverlaySystem.cs +++ b/Content.Client/Atmos/EntitySystems/GasTileOverlaySystem.cs @@ -1,4 +1,5 @@ using Content.Client.Atmos.Overlays; +using Content.Shared.Atmos; using Content.Shared.Atmos.Components; using Content.Shared.Atmos.EntitySystems; using JetBrains.Annotations; @@ -36,28 +37,38 @@ public override void Shutdown() private void OnHandleState(EntityUid gridUid, GasTileOverlayComponent comp, ref ComponentHandleState args) { - if (args.Current is not GasTileOverlayState state) - return; + Dictionary modifiedChunks; - // is this a delta or full state? - if (!state.FullState) + switch (args.Current) { - foreach (var index in comp.Chunks.Keys) + // is this a delta or full state? + case GasTileOverlayDeltaState delta: { - if (!state.AllChunks!.Contains(index)) - comp.Chunks.Remove(index); + modifiedChunks = delta.ModifiedChunks; + foreach (var index in comp.Chunks.Keys) + { + if (!delta.AllChunks.Contains(index)) + comp.Chunks.Remove(index); + } + + break; } - } - else - { - foreach (var index in comp.Chunks.Keys) + case GasTileOverlayState state: { - if (!state.Chunks.ContainsKey(index)) - comp.Chunks.Remove(index); + modifiedChunks = state.Chunks; + foreach (var index in comp.Chunks.Keys) + { + if (!state.Chunks.ContainsKey(index)) + comp.Chunks.Remove(index); + } + + break; } + default: + return; } - foreach (var (index, data) in state.Chunks) + foreach (var (index, data) in modifiedChunks) { comp.Chunks[index] = data; } diff --git a/Content.Shared/Atmos/Components/GasTileOverlayComponent.cs b/Content.Shared/Atmos/Components/GasTileOverlayComponent.cs index e72a1d675841..9ed5621a701a 100644 --- a/Content.Shared/Atmos/Components/GasTileOverlayComponent.cs +++ b/Content.Shared/Atmos/Components/GasTileOverlayComponent.cs @@ -24,48 +24,40 @@ public sealed partial class GasTileOverlayComponent : Component public GameTick ForceTick { get; set; } } - [Serializable, NetSerializable] -public sealed class GasTileOverlayState : ComponentState, IComponentDeltaState +public sealed class GasTileOverlayState(Dictionary chunks) : ComponentState { - public readonly Dictionary Chunks; - public bool FullState => AllChunks == null; - - // required to infer deleted/missing chunks for delta states - public HashSet? AllChunks; + public readonly Dictionary Chunks = chunks; +} - public GasTileOverlayState(Dictionary chunks) - { - Chunks = chunks; - } +[Serializable, NetSerializable] +public sealed class GasTileOverlayDeltaState( + Dictionary modifiedChunks, + HashSet allChunks) + : ComponentState, IComponentDeltaState +{ + public readonly Dictionary ModifiedChunks = modifiedChunks; + public readonly HashSet AllChunks = allChunks; - public void ApplyToFullState(IComponentState fullState) + public void ApplyToFullState(GasTileOverlayState state) { - DebugTools.Assert(!FullState); - var state = (GasTileOverlayState) fullState; - DebugTools.Assert(state.FullState); - foreach (var key in state.Chunks.Keys) { if (!AllChunks!.Contains(key)) state.Chunks.Remove(key); } - foreach (var (chunk, data) in Chunks) + foreach (var (chunk, data) in ModifiedChunks) { state.Chunks[chunk] = new(data); } } - public IComponentState CreateNewFullState(IComponentState fullState) + public GasTileOverlayState CreateNewFullState(GasTileOverlayState state) { - DebugTools.Assert(!FullState); - var state = (GasTileOverlayState) fullState; - DebugTools.Assert(state.FullState); - var chunks = new Dictionary(state.Chunks.Count); - foreach (var (chunk, data) in Chunks) + foreach (var (chunk, data) in ModifiedChunks) { chunks[chunk] = new(data); } diff --git a/Content.Shared/Atmos/EntitySystems/SharedGasTileOverlaySystem.cs b/Content.Shared/Atmos/EntitySystems/SharedGasTileOverlaySystem.cs index f468724db333..8e7dfdedaf90 100644 --- a/Content.Shared/Atmos/EntitySystems/SharedGasTileOverlaySystem.cs +++ b/Content.Shared/Atmos/EntitySystems/SharedGasTileOverlaySystem.cs @@ -55,7 +55,7 @@ private void OnGetState(EntityUid uid, GasTileOverlayComponent component, ref Co data[index] = chunk; } - args.State = new GasTileOverlayState(data) { AllChunks = new(component.Chunks.Keys) }; + args.State = new GasTileOverlayDeltaState(data, new(component.Chunks.Keys)); } public static Vector2i GetGasChunkIndices(Vector2i indices) From 8c2bd021a2c8218289b7a4a3ff4f92943a8b7d2d Mon Sep 17 00:00:00 2001 From: ElectroJr Date: Sun, 19 May 2024 20:03:20 +1200 Subject: [PATCH 2/9] Update DecalGridState --- Content.Client/Decals/DecalSystem.cs | 39 +++++++++++++-------- Content.Shared/Decals/DecalGridComponent.cs | 35 +++++++----------- Content.Shared/Decals/SharedDecalSystem.cs | 2 +- 3 files changed, 38 insertions(+), 38 deletions(-) diff --git a/Content.Client/Decals/DecalSystem.cs b/Content.Client/Decals/DecalSystem.cs index 901ab270fb59..41e5f39c2867 100644 --- a/Content.Client/Decals/DecalSystem.cs +++ b/Content.Client/Decals/DecalSystem.cs @@ -56,34 +56,43 @@ protected override void OnDecalRemoved(EntityUid gridId, uint decalId, DecalGrid private void OnHandleState(EntityUid gridUid, DecalGridComponent gridComp, ref ComponentHandleState args) { - if (args.Current is not DecalGridState state) - return; - // is this a delta or full state? _removedChunks.Clear(); + Dictionary modifiedChunks; - if (!state.FullState) + switch (args.Current) { - foreach (var key in gridComp.ChunkCollection.ChunkCollection.Keys) + case DecalGridDeltaState delta: { - if (!state.AllChunks!.Contains(key)) - _removedChunks.Add(key); + modifiedChunks = delta.ModifiedChunks; + foreach (var key in gridComp.ChunkCollection.ChunkCollection.Keys) + { + if (!delta.AllChunks.Contains(key)) + _removedChunks.Add(key); + } + + break; } - } - else - { - foreach (var key in gridComp.ChunkCollection.ChunkCollection.Keys) + case DecalGridState state: { - if (!state.Chunks.ContainsKey(key)) - _removedChunks.Add(key); + modifiedChunks = state.Chunks; + foreach (var key in gridComp.ChunkCollection.ChunkCollection.Keys) + { + if (!state.Chunks.ContainsKey(key)) + _removedChunks.Add(key); + } + + break; } + default: + return; } if (_removedChunks.Count > 0) RemoveChunks(gridUid, gridComp, _removedChunks); - if (state.Chunks.Count > 0) - UpdateChunks(gridUid, gridComp, state.Chunks); + if (modifiedChunks.Count > 0) + UpdateChunks(gridUid, gridComp, modifiedChunks); } private void OnChunkUpdate(DecalChunkUpdateEvent ev) diff --git a/Content.Shared/Decals/DecalGridComponent.cs b/Content.Shared/Decals/DecalGridComponent.cs index 8ac05cb280fa..67a9c037696d 100644 --- a/Content.Shared/Decals/DecalGridComponent.cs +++ b/Content.Shared/Decals/DecalGridComponent.cs @@ -62,46 +62,37 @@ public record DecalGridChunkCollection(Dictionary ChunkCol } [Serializable, NetSerializable] - public sealed class DecalGridState : ComponentState, IComponentDeltaState + public sealed class DecalGridState(Dictionary chunks) : ComponentState { - public Dictionary Chunks; - public bool FullState => AllChunks == null; - - // required to infer deleted/missing chunks for delta states - public HashSet? AllChunks; + public Dictionary Chunks = chunks; + } - public DecalGridState(Dictionary chunks) - { - Chunks = chunks; - } + [Serializable, NetSerializable] + public sealed class DecalGridDeltaState(Dictionary modifiedChunks, HashSet allChunks) + : ComponentState, IComponentDeltaState + { + public Dictionary ModifiedChunks = modifiedChunks; + public HashSet AllChunks = allChunks; - public void ApplyToFullState(IComponentState fullState) + public void ApplyToFullState(DecalGridState state) { - DebugTools.Assert(!FullState); - var state = (DecalGridState) fullState; - DebugTools.Assert(state.FullState); - foreach (var key in state.Chunks.Keys) { if (!AllChunks!.Contains(key)) state.Chunks.Remove(key); } - foreach (var (chunk, data) in Chunks) + foreach (var (chunk, data) in ModifiedChunks) { state.Chunks[chunk] = new(data); } } - public IComponentState CreateNewFullState(IComponentState fullState) + public DecalGridState CreateNewFullState(DecalGridState state) { - DebugTools.Assert(!FullState); - var state = (DecalGridState) fullState; - DebugTools.Assert(state.FullState); - var chunks = new Dictionary(state.Chunks.Count); - foreach (var (chunk, data) in Chunks) + foreach (var (chunk, data) in ModifiedChunks) { chunks[chunk] = new(data); } diff --git a/Content.Shared/Decals/SharedDecalSystem.cs b/Content.Shared/Decals/SharedDecalSystem.cs index 0665ccbf84b3..0a2349ea299a 100644 --- a/Content.Shared/Decals/SharedDecalSystem.cs +++ b/Content.Shared/Decals/SharedDecalSystem.cs @@ -49,7 +49,7 @@ private void OnGetState(EntityUid uid, DecalGridComponent component, ref Compone data[index] = chunk; } - args.State = new DecalGridState(data) { AllChunks = new(component.ChunkCollection.ChunkCollection.Keys) }; + args.State = new DecalGridDeltaState(data, new(component.ChunkCollection.ChunkCollection.Keys)); } private void OnGridInitialize(GridInitializeEvent msg) From 6691612c24c78f34fbf05cebf93c753ace582c0d Mon Sep 17 00:00:00 2001 From: ElectroJr Date: Sun, 19 May 2024 20:08:59 +1200 Subject: [PATCH 3/9] Update NavMapState --- Content.Client/Pinpointer/NavMapSystem.cs | 41 +++++++++++------ .../Pinpointer/SharedNavMapSystem.cs | 46 ++++++++----------- 2 files changed, 47 insertions(+), 40 deletions(-) diff --git a/Content.Client/Pinpointer/NavMapSystem.cs b/Content.Client/Pinpointer/NavMapSystem.cs index e33bc5d32917..9aeb792a429f 100644 --- a/Content.Client/Pinpointer/NavMapSystem.cs +++ b/Content.Client/Pinpointer/NavMapSystem.cs @@ -14,27 +14,40 @@ public override void Initialize() private void OnHandleState(EntityUid uid, NavMapComponent component, ref ComponentHandleState args) { - if (args.Current is not NavMapComponentState state) - return; + Dictionary modifiedChunks; + Dictionary beacons; - if (!state.FullState) + switch (args.Current) { - foreach (var index in component.Chunks.Keys) + case NavMapDeltaState delta: { - if (!state.AllChunks!.Contains(index)) - component.Chunks.Remove(index); + modifiedChunks = delta.ModifiedChunks; + beacons = delta.Beacons; + foreach (var index in component.Chunks.Keys) + { + if (!delta.AllChunks!.Contains(index)) + component.Chunks.Remove(index); + } + + break; } - } - else - { - foreach (var index in component.Chunks.Keys) + case NavMapState state: { - if (!state.Chunks.ContainsKey(index)) - component.Chunks.Remove(index); + modifiedChunks = state.Chunks; + beacons = state.Beacons; + foreach (var index in component.Chunks.Keys) + { + if (!state.Chunks.ContainsKey(index)) + component.Chunks.Remove(index); + } + + break; } + default: + return; } - foreach (var (origin, chunk) in state.Chunks) + foreach (var (origin, chunk) in modifiedChunks) { var newChunk = new NavMapChunk(origin); Array.Copy(chunk, newChunk.TileData, chunk.Length); @@ -42,7 +55,7 @@ private void OnHandleState(EntityUid uid, NavMapComponent component, ref Compone } component.Beacons.Clear(); - foreach (var (nuid, beacon) in state.Beacons) + foreach (var (nuid, beacon) in beacons) { component.Beacons[nuid] = beacon; } diff --git a/Content.Shared/Pinpointer/SharedNavMapSystem.cs b/Content.Shared/Pinpointer/SharedNavMapSystem.cs index ffe81c2d0ea4..7c12321b5db6 100644 --- a/Content.Shared/Pinpointer/SharedNavMapSystem.cs +++ b/Content.Shared/Pinpointer/SharedNavMapSystem.cs @@ -96,7 +96,7 @@ private void OnGetState(EntityUid uid, NavMapComponent component, ref ComponentG chunks.Add(origin, chunk.TileData); } - args.State = new NavMapComponentState(chunks, component.Beacons); + args.State = new NavMapState(chunks, component.Beacons); return; } @@ -109,12 +109,7 @@ private void OnGetState(EntityUid uid, NavMapComponent component, ref ComponentG chunks.Add(origin, chunk.TileData); } - args.State = new NavMapComponentState(chunks, component.Beacons) - { - // TODO NAVMAP cache a single AllChunks hashset in the component. - // Or maybe just only send them if a chunk gets removed. - AllChunks = new(component.Chunks.Keys), - }; + args.State = new NavMapDeltaState(chunks, component.Beacons, new(component.Chunks.Keys)); } #endregion @@ -122,32 +117,35 @@ private void OnGetState(EntityUid uid, NavMapComponent component, ref ComponentG #region: System messages [Serializable, NetSerializable] - protected sealed class NavMapComponentState( + protected sealed class NavMapState( Dictionary chunks, Dictionary beacons) - : ComponentState, IComponentDeltaState + : ComponentState { public Dictionary Chunks = chunks; public Dictionary Beacons = beacons; + } - // Required to infer deleted/missing chunks for delta states - public HashSet? AllChunks; - - public bool FullState => AllChunks == null; + [Serializable, NetSerializable] + protected sealed class NavMapDeltaState( + Dictionary modifiedChunks, + Dictionary beacons, + HashSet allChunks) + : ComponentState, IComponentDeltaState + { + public Dictionary ModifiedChunks = modifiedChunks; + public Dictionary Beacons = beacons; + public HashSet AllChunks = allChunks; - public void ApplyToFullState(IComponentState fullState) + public void ApplyToFullState(NavMapState state) { - DebugTools.Assert(!FullState); - var state = (NavMapComponentState) fullState; - DebugTools.Assert(state.FullState); - foreach (var key in state.Chunks.Keys) { if (!AllChunks!.Contains(key)) state.Chunks.Remove(key); } - foreach (var (index, data) in Chunks) + foreach (var (index, data) in ModifiedChunks) { if (!state.Chunks.TryGetValue(index, out var stateValue)) state.Chunks[index] = stateValue = new int[data.Length]; @@ -162,12 +160,8 @@ public void ApplyToFullState(IComponentState fullState) } } - public IComponentState CreateNewFullState(IComponentState fullState) + public NavMapState CreateNewFullState(NavMapState state) { - DebugTools.Assert(!FullState); - var state = (NavMapComponentState) fullState; - DebugTools.Assert(state.FullState); - var chunks = new Dictionary(state.Chunks.Count); foreach (var (index, data) in state.Chunks) { @@ -176,13 +170,13 @@ public IComponentState CreateNewFullState(IComponentState fullState) var newData = chunks[index] = new int[ArraySize]; - if (Chunks.TryGetValue(index, out var updatedData)) + if (ModifiedChunks.TryGetValue(index, out var updatedData)) Array.Copy(newData, updatedData, ArraySize); else Array.Copy(newData, data, ArraySize); } - return new NavMapComponentState(chunks, new(Beacons)); + return new NavMapState(chunks, new(Beacons)); } } From 1eb2b4eb51782e9b71413ebef5d8e87f686191d8 Mon Sep 17 00:00:00 2001 From: ElectroJr Date: Sun, 19 May 2024 20:42:05 +1200 Subject: [PATCH 4/9] poke From 48ccd81cd3cdfb00f17ee58556d57f1dfcce42a5 Mon Sep 17 00:00:00 2001 From: ElectroJr Date: Sun, 19 May 2024 22:50:45 +1200 Subject: [PATCH 5/9] poke2 From 7d23c91a471f166400f8e2d3aee8cb7031f1663c Mon Sep 17 00:00:00 2001 From: ElectroJr Date: Sun, 19 May 2024 23:16:09 +1200 Subject: [PATCH 6/9] poke3 From cb2a68ad313b2694749f0c924cc2c022e06a622d Mon Sep 17 00:00:00 2001 From: metalgearsloth Date: Fri, 24 May 2024 12:10:43 +1000 Subject: [PATCH 7/9] Implement field deltas for guns --- .../Ranged/Systems/GunSystem.Ballistic.cs | 2 + .../Ranged/Systems/GunSystem.Solution.cs | 9 ++- .../Nutrition/EntitySystems/HungerSystem.cs | 5 +- .../Nutrition/EntitySystems/ThirstSystem.cs | 3 +- .../Ranged/Components/AmmoComponent.cs | 18 ++--- .../BallisticAmmoProviderComponent.cs | 4 +- .../Systems/SharedGunSystem.Ballistic.cs | 9 ++- .../Weapons/Ranged/Systems/SharedGunSystem.cs | 78 +++++++++++++++---- 8 files changed, 90 insertions(+), 38 deletions(-) diff --git a/Content.Server/Weapons/Ranged/Systems/GunSystem.Ballistic.cs b/Content.Server/Weapons/Ranged/Systems/GunSystem.Ballistic.cs index 798be3fc8eab..60680deaaaa0 100644 --- a/Content.Server/Weapons/Ranged/Systems/GunSystem.Ballistic.cs +++ b/Content.Server/Weapons/Ranged/Systems/GunSystem.Ballistic.cs @@ -15,6 +15,7 @@ protected override void Cycle(EntityUid uid, BallisticAmmoProviderComponent comp { var existing = component.Entities[^1]; component.Entities.RemoveAt(component.Entities.Count - 1); + DirtyField(uid, component, nameof(BallisticAmmoProviderComponent.Entities)); Containers.Remove(existing, component.Container); EnsureShootable(existing); @@ -22,6 +23,7 @@ protected override void Cycle(EntityUid uid, BallisticAmmoProviderComponent comp else if (component.UnspawnedCount > 0) { component.UnspawnedCount--; + DirtyField(uid, component, nameof(BallisticAmmoProviderComponent.UnspawnedCount)); ent = Spawn(component.Proto, coordinates); EnsureShootable(ent.Value); } diff --git a/Content.Server/Weapons/Ranged/Systems/GunSystem.Solution.cs b/Content.Server/Weapons/Ranged/Systems/GunSystem.Solution.cs index 7ad4b15ffc70..93ef6db9fa70 100644 --- a/Content.Server/Weapons/Ranged/Systems/GunSystem.Solution.cs +++ b/Content.Server/Weapons/Ranged/Systems/GunSystem.Solution.cs @@ -12,7 +12,7 @@ namespace Content.Server.Weapons.Ranged.Systems; public sealed partial class GunSystem { - [Dependency] private readonly SolutionContainerSystem _solutionContainer = default!; + [Dependency] private readonly SharedSolutionContainerSystem _solutionContainer = default!; protected override void InitializeSolution() { @@ -40,8 +40,9 @@ protected override void UpdateSolutionShots(EntityUid uid, SolutionAmmoProviderC if (solution == null && !_solutionContainer.TryGetSolution(uid, component.SolutionId, out _, out solution)) { component.Shots = shots; + DirtyField(uid, component, nameof(SolutionAmmoProviderComponent.Shots)); component.MaxShots = maxShots; - Dirty(uid, component); + DirtyField(uid, component, nameof(SolutionAmmoProviderComponent.MaxShots)); return; } @@ -49,8 +50,10 @@ protected override void UpdateSolutionShots(EntityUid uid, SolutionAmmoProviderC maxShots = (int) (solution.MaxVolume / component.FireCost); component.Shots = shots; + DirtyField(uid, component, nameof(SolutionAmmoProviderComponent.Shots)); + component.MaxShots = maxShots; - Dirty(uid, component); + DirtyField(uid, component, nameof(SolutionAmmoProviderComponent.MaxShots)); UpdateSolutionAppearance(uid, component); } diff --git a/Content.Shared/Nutrition/EntitySystems/HungerSystem.cs b/Content.Shared/Nutrition/EntitySystems/HungerSystem.cs index 4de4e4d5feb0..21caad17bfb1 100644 --- a/Content.Shared/Nutrition/EntitySystems/HungerSystem.cs +++ b/Content.Shared/Nutrition/EntitySystems/HungerSystem.cs @@ -107,7 +107,7 @@ public void SetHunger(EntityUid uid, float amount, HungerComponent? component = component.Thresholds[HungerThreshold.Dead], component.Thresholds[HungerThreshold.Overfed]); UpdateCurrentThreshold(uid, component); - Dirty(uid, component); + EntityManager.DirtyField(uid, component, nameof(HungerComponent.CurrentHunger)); } private void UpdateCurrentThreshold(EntityUid uid, HungerComponent? component = null) @@ -118,9 +118,10 @@ private void UpdateCurrentThreshold(EntityUid uid, HungerComponent? component = var calculatedHungerThreshold = GetHungerThreshold(component); if (calculatedHungerThreshold == component.CurrentThreshold) return; + component.CurrentThreshold = calculatedHungerThreshold; DoHungerThresholdEffects(uid, component); - Dirty(uid, component); + EntityManager.DirtyField(uid, component, nameof(HungerComponent.CurrentThreshold)); } private void DoHungerThresholdEffects(EntityUid uid, HungerComponent? component = null, bool force = false) diff --git a/Content.Shared/Nutrition/EntitySystems/ThirstSystem.cs b/Content.Shared/Nutrition/EntitySystems/ThirstSystem.cs index 8ea7d9140c36..2650381f089d 100644 --- a/Content.Shared/Nutrition/EntitySystems/ThirstSystem.cs +++ b/Content.Shared/Nutrition/EntitySystems/ThirstSystem.cs @@ -109,7 +109,8 @@ public void SetThirst(EntityUid uid, ThirstComponent component, float amount) component.ThirstThresholds[ThirstThreshold.Dead], component.ThirstThresholds[ThirstThreshold.OverHydrated] ); - Dirty(uid, component); + + EntityManager.DirtyField(uid, component, nameof(ThirstComponent.CurrentThirst)); } private bool IsMovementThreshold(ThirstThreshold threshold) diff --git a/Content.Shared/Weapons/Ranged/Components/AmmoComponent.cs b/Content.Shared/Weapons/Ranged/Components/AmmoComponent.cs index 62af124252b9..08eb1ba355d0 100644 --- a/Content.Shared/Weapons/Ranged/Components/AmmoComponent.cs +++ b/Content.Shared/Weapons/Ranged/Components/AmmoComponent.cs @@ -13,8 +13,8 @@ public partial class AmmoComponent : Component, IShootable { // Muzzle flash stored on ammo because if we swap a gun to whatever we may want to override it. - [ViewVariables(VVAccess.ReadWrite), DataField("muzzleFlash", customTypeSerializer:typeof(PrototypeIdSerializer))] - public string? MuzzleFlash = "MuzzleFlashEffect"; + [DataField] + public EntProtoId? MuzzleFlash = "MuzzleFlashEffect"; } /// @@ -23,29 +23,29 @@ public partial class AmmoComponent : Component, IShootable [RegisterComponent, NetworkedComponent, AutoGenerateComponentState] public sealed partial class CartridgeAmmoComponent : AmmoComponent { - [ViewVariables(VVAccess.ReadWrite), DataField("proto", required: true, customTypeSerializer: typeof(PrototypeIdSerializer))] - public string Prototype = default!; + [ViewVariables(VVAccess.ReadWrite), DataField("proto", required: true)] + public EntProtoId Prototype; - [ViewVariables(VVAccess.ReadWrite), DataField("spent")] + [ViewVariables(VVAccess.ReadWrite), DataField] [AutoNetworkedField] - public bool Spent = false; + public bool Spent; /// /// How much the ammo spreads when shot, in degrees. Does nothing if count is 0. /// - [ViewVariables(VVAccess.ReadWrite), DataField("spread")] + [ViewVariables(VVAccess.ReadWrite), DataField] public Angle Spread = Angle.FromDegrees(5); /// /// How many prototypes are spawned when shot. /// - [ViewVariables(VVAccess.ReadWrite), DataField("count")] + [ViewVariables(VVAccess.ReadWrite), DataField] public int Count = 1; /// /// Caseless ammunition. /// - [DataField("deleteOnSpawn")] + [DataField] public bool DeleteOnSpawn; [DataField("soundEject")] diff --git a/Content.Shared/Weapons/Ranged/Components/BallisticAmmoProviderComponent.cs b/Content.Shared/Weapons/Ranged/Components/BallisticAmmoProviderComponent.cs index eb04d3227db6..1f049dc94ad0 100644 --- a/Content.Shared/Weapons/Ranged/Components/BallisticAmmoProviderComponent.cs +++ b/Content.Shared/Weapons/Ranged/Components/BallisticAmmoProviderComponent.cs @@ -9,10 +9,10 @@ namespace Content.Shared.Weapons.Ranged.Components; [RegisterComponent, NetworkedComponent, AutoGenerateComponentState] public sealed partial class BallisticAmmoProviderComponent : Component { - [ViewVariables(VVAccess.ReadWrite), DataField] + [DataField] public SoundSpecifier? SoundRack = new SoundPathSpecifier("/Audio/Weapons/Guns/Cock/smg_cock.ogg"); - [ViewVariables(VVAccess.ReadWrite), DataField] + [DataField] public SoundSpecifier? SoundInsert = new SoundPathSpecifier("/Audio/Weapons/Guns/MagIn/bullet_insert.ogg"); [ViewVariables(VVAccess.ReadWrite), DataField] diff --git a/Content.Shared/Weapons/Ranged/Systems/SharedGunSystem.Ballistic.cs b/Content.Shared/Weapons/Ranged/Systems/SharedGunSystem.Ballistic.cs index 6242312b0709..4a49daa88026 100644 --- a/Content.Shared/Weapons/Ranged/Systems/SharedGunSystem.Ballistic.cs +++ b/Content.Shared/Weapons/Ranged/Systems/SharedGunSystem.Ballistic.cs @@ -53,7 +53,7 @@ private void OnBallisticInteractUsing(EntityUid uid, BallisticAmmoProviderCompon Audio.PlayPredicted(component.SoundInsert, uid, args.User); args.Handled = true; UpdateBallisticAppearance(uid, component); - Dirty(uid, component); + DirtyField(uid, component, nameof(BallisticAmmoProviderComponent.Entities)); } private void OnBallisticAfterInteract(EntityUid uid, BallisticAmmoProviderComponent component, AfterInteractEvent args) @@ -186,9 +186,9 @@ private void ManualCycle(EntityUid uid, BallisticAmmoProviderComponent component !Paused(uid)) { gunComp.NextFire = Timing.CurTime + TimeSpan.FromSeconds(1 / gunComp.FireRateModified); + DirtyField(uid, gunComp, nameof(GunComponent.NextFire)); } - Dirty(uid, component); Audio.PlayPredicted(component.SoundRack, uid, user); var shots = GetBallisticShots(component); @@ -219,7 +219,7 @@ private void OnBallisticMapInit(EntityUid uid, BallisticAmmoProviderComponent co { component.UnspawnedCount = Math.Max(0, component.Capacity - component.Container.ContainedEntities.Count); UpdateBallisticAppearance(uid, component); - Dirty(uid, component); + DirtyField(uid, component, nameof(BallisticAmmoProviderComponent.UnspawnedCount)); } } @@ -240,18 +240,19 @@ private void OnBallisticTakeAmmo(EntityUid uid, BallisticAmmoProviderComponent c args.Ammo.Add((entity, EnsureShootable(entity))); component.Entities.RemoveAt(component.Entities.Count - 1); + DirtyField(uid, component, nameof(BallisticAmmoProviderComponent.Entities)); Containers.Remove(entity, component.Container); } else if (component.UnspawnedCount > 0) { component.UnspawnedCount--; + DirtyField(uid, component, nameof(BallisticAmmoProviderComponent.UnspawnedCount)); entity = Spawn(component.Proto, args.Coordinates); args.Ammo.Add((entity, EnsureShootable(entity))); } } UpdateBallisticAppearance(uid, component); - Dirty(uid, component); } private void OnBallisticAmmoCount(EntityUid uid, BallisticAmmoProviderComponent component, ref GetAmmoCountEvent args) diff --git a/Content.Shared/Weapons/Ranged/Systems/SharedGunSystem.cs b/Content.Shared/Weapons/Ranged/Systems/SharedGunSystem.cs index 4debc289be1f..f2ed331bb8e1 100644 --- a/Content.Shared/Weapons/Ranged/Systems/SharedGunSystem.cs +++ b/Content.Shared/Weapons/Ranged/Systems/SharedGunSystem.cs @@ -117,7 +117,7 @@ private void OnGunMelee(EntityUid uid, GunComponent component, MeleeHitEvent arg if (melee.NextAttack > component.NextFire) { component.NextFire = melee.NextAttack; - Dirty(uid, component); + EntityManager.DirtyField(uid, component, nameof(MeleeWeaponComponent.NextAttack)); } } @@ -198,7 +198,7 @@ private void StopShooting(EntityUid uid, GunComponent gun) gun.ShotCounter = 0; gun.ShootCoordinates = null; gun.Target = null; - Dirty(uid, gun); + EntityManager.DirtyField(uid, gun, nameof(GunComponent.ShotCounter)); } /// @@ -209,6 +209,7 @@ public void AttemptShoot(EntityUid user, EntityUid gunUid, GunComponent gun, Ent gun.ShootCoordinates = toCoordinates; AttemptShoot(user, gunUid, gun); gun.ShotCounter = 0; + EntityManager.DirtyField(gunUid, gun, nameof(GunComponent.ShotCounter)); } /// @@ -226,7 +227,9 @@ private void AttemptShoot(EntityUid user, EntityUid gunUid, GunComponent gun) { if (gun.FireRateModified <= 0f || !_actionBlockerSystem.CanAttack(user)) + { return; + } var toCoordinates = gun.ShootCoordinates; @@ -272,7 +275,7 @@ private void AttemptShoot(EntityUid user, EntityUid gunUid, GunComponent gun) } // NextFire has been touched regardless so need to dirty the gun. - Dirty(gunUid, gun); + EntityManager.DirtyField(gunUid, gun, nameof(GunComponent.NextFire)); // Get how many shots we're actually allowed to make, due to clip size or otherwise. // Don't do this in the loop so we still reset NextFire. @@ -319,6 +322,7 @@ private void AttemptShoot(EntityUid user, EntityUid gunUid, GunComponent gun) // Even if we don't actually shoot update the ShotCounter. This is to avoid spamming empty sounds // where the gun may be SemiAuto or Burst. gun.ShotCounter += shots; + EntityManager.DirtyField(gunUid, gun, nameof(GunComponent.ShotCounter)); if (ev.Ammo.Count <= 0) { @@ -355,8 +359,6 @@ private void AttemptShoot(EntityUid user, EntityUid gunUid, GunComponent gun) if (_gravity.IsWeightless(user, userPhysics)) CauseImpulse(fromCoordinates, toCoordinates.Value, user, userPhysics); } - - Dirty(gunUid, gun); } public void Shoot( @@ -410,7 +412,7 @@ protected virtual void UpdateAmmoCount(EntityUid uid, bool prediction = true) {} protected void SetCartridgeSpent(EntityUid uid, CartridgeAmmoComponent cartridge, bool spent) { if (cartridge.Spent != spent) - Dirty(uid, cartridge); + DirtyField(uid, cartridge, nameof(CartridgeAmmoComponent.Spent)); cartridge.Spent = spent; Appearance.SetData(uid, AmmoVisuals.Spent, spent); @@ -509,17 +511,59 @@ public void RefreshModifiers(Entity gun) RaiseLocalEvent(gun, ref ev); - comp.SoundGunshotModified = ev.SoundGunshot; - comp.CameraRecoilScalarModified = ev.CameraRecoilScalar; - comp.AngleIncreaseModified = ev.AngleIncrease; - comp.AngleDecayModified = ev.AngleDecay; - comp.MaxAngleModified = ev.MaxAngle; - comp.MinAngleModified = ev.MinAngle; - comp.ShotsPerBurstModified = ev.ShotsPerBurst; - comp.FireRateModified = ev.FireRate; - comp.ProjectileSpeedModified = ev.ProjectileSpeed; - - Dirty(gun); + if (comp.SoundGunshotModified != ev.SoundGunshot) + { + comp.SoundGunshotModified = ev.SoundGunshot; + DirtyField(gun, nameof(GunComponent.SoundGunshotModified)); + } + + if (!MathHelper.CloseTo(comp.CameraRecoilScalarModified, ev.CameraRecoilScalar)) + { + comp.CameraRecoilScalarModified = ev.CameraRecoilScalar; + DirtyField(gun, nameof(GunComponent.CameraRecoilScalarModified)); + } + + if (!comp.AngleIncreaseModified.EqualsApprox(ev.AngleIncrease)) + { + comp.AngleIncreaseModified = ev.AngleIncrease; + DirtyField(gun, nameof(GunComponent.AngleIncreaseModified)); + } + + if (!comp.AngleDecayModified.EqualsApprox(ev.AngleDecay)) + { + comp.AngleDecayModified = ev.AngleDecay; + DirtyField(gun, nameof(GunComponent.AngleDecayModified)); + } + + if (!comp.MaxAngleModified.EqualsApprox(ev.MinAngle)) + { + comp.MaxAngleModified = ev.MaxAngle; + DirtyField(gun, nameof(GunComponent.MaxAngleModified)); + } + + if (!comp.MinAngleModified.EqualsApprox(ev.MinAngle)) + { + comp.MinAngleModified = ev.MinAngle; + DirtyField(gun, nameof(GunComponent.MinAngleModified)); + } + + if (comp.ShotsPerBurstModified != ev.ShotsPerBurst) + { + comp.ShotsPerBurstModified = ev.ShotsPerBurst; + DirtyField(gun, nameof(GunComponent.ShotsPerBurstModified)); + } + + if (!MathHelper.CloseTo(comp.FireRateModified, ev.FireRate)) + { + comp.FireRateModified = ev.FireRate; + DirtyField(gun, nameof(GunComponent.FireRateModified)); + } + + if (!MathHelper.CloseTo(comp.ProjectileSpeedModified, ev.ProjectileSpeed)) + { + comp.ProjectileSpeedModified = ev.ProjectileSpeed; + DirtyField(gun, nameof(GunComponent.ProjectileSpeedModified)); + } } protected abstract void CreateEffect(EntityUid gunUid, MuzzleFlashEvent message, EntityUid? user = null); From c0cd4abf83ca8c23b46626e913cae3dbfa1bf1a2 Mon Sep 17 00:00:00 2001 From: metalgearsloth Date: Sat, 21 Dec 2024 15:14:46 +1100 Subject: [PATCH 8/9] Content done --- .../Nutrition/Components/HungerComponent.cs | 2 +- .../Nutrition/Components/ThirstComponent.cs | 2 +- .../Weapons/Ranged/Components/AmmoComponent.cs | 2 +- .../Components/BallisticAmmoProviderComponent.cs | 2 +- .../Weapons/Ranged/Components/GunComponent.cs | 2 +- .../Components/SolutionAmmoProviderComponent.cs | 14 +++++++------- 6 files changed, 12 insertions(+), 12 deletions(-) diff --git a/Content.Shared/Nutrition/Components/HungerComponent.cs b/Content.Shared/Nutrition/Components/HungerComponent.cs index 79d895ddae66..895005cc91c6 100644 --- a/Content.Shared/Nutrition/Components/HungerComponent.cs +++ b/Content.Shared/Nutrition/Components/HungerComponent.cs @@ -10,7 +10,7 @@ namespace Content.Shared.Nutrition.Components; [RegisterComponent, NetworkedComponent, Access(typeof(HungerSystem))] -[AutoGenerateComponentState, AutoGenerateComponentPause] +[AutoGenerateComponentState(fieldDeltas: true), AutoGenerateComponentPause] public sealed partial class HungerComponent : Component { /// diff --git a/Content.Shared/Nutrition/Components/ThirstComponent.cs b/Content.Shared/Nutrition/Components/ThirstComponent.cs index f3ac881361fc..5c32b4af2868 100644 --- a/Content.Shared/Nutrition/Components/ThirstComponent.cs +++ b/Content.Shared/Nutrition/Components/ThirstComponent.cs @@ -7,7 +7,7 @@ namespace Content.Shared.Nutrition.Components; [RegisterComponent, NetworkedComponent, Access(typeof(ThirstSystem))] -[AutoGenerateComponentState, AutoGenerateComponentPause] +[AutoGenerateComponentState(fieldDeltas: true), AutoGenerateComponentPause] public sealed partial class ThirstComponent : Component { // Base stuff diff --git a/Content.Shared/Weapons/Ranged/Components/AmmoComponent.cs b/Content.Shared/Weapons/Ranged/Components/AmmoComponent.cs index 9092b59fd00c..13cee5bad6f8 100644 --- a/Content.Shared/Weapons/Ranged/Components/AmmoComponent.cs +++ b/Content.Shared/Weapons/Ranged/Components/AmmoComponent.cs @@ -20,7 +20,7 @@ public partial class AmmoComponent : Component, IShootable /// /// Spawns another prototype to be shot instead of itself. /// -[RegisterComponent, NetworkedComponent, AutoGenerateComponentState] +[RegisterComponent, NetworkedComponent, AutoGenerateComponentState(fieldDeltas: true)] public sealed partial class CartridgeAmmoComponent : AmmoComponent { [ViewVariables(VVAccess.ReadWrite), DataField("proto", required: true)] diff --git a/Content.Shared/Weapons/Ranged/Components/BallisticAmmoProviderComponent.cs b/Content.Shared/Weapons/Ranged/Components/BallisticAmmoProviderComponent.cs index 1b752e927562..ee806125e786 100644 --- a/Content.Shared/Weapons/Ranged/Components/BallisticAmmoProviderComponent.cs +++ b/Content.Shared/Weapons/Ranged/Components/BallisticAmmoProviderComponent.cs @@ -7,7 +7,7 @@ namespace Content.Shared.Weapons.Ranged.Components; -[RegisterComponent, NetworkedComponent, AutoGenerateComponentState, Access(typeof(SharedGunSystem))] +[RegisterComponent, NetworkedComponent, AutoGenerateComponentState(fieldDeltas: true), Access(typeof(SharedGunSystem))] public sealed partial class BallisticAmmoProviderComponent : Component { [DataField] diff --git a/Content.Shared/Weapons/Ranged/Components/GunComponent.cs b/Content.Shared/Weapons/Ranged/Components/GunComponent.cs index 98b1d2fe2a4f..3ec832613d2e 100644 --- a/Content.Shared/Weapons/Ranged/Components/GunComponent.cs +++ b/Content.Shared/Weapons/Ranged/Components/GunComponent.cs @@ -8,7 +8,7 @@ namespace Content.Shared.Weapons.Ranged.Components; -[RegisterComponent, NetworkedComponent, AutoGenerateComponentState, AutoGenerateComponentPause] +[RegisterComponent, NetworkedComponent, AutoGenerateComponentState(fieldDeltas: true), AutoGenerateComponentPause] [Access(typeof(SharedGunSystem))] public sealed partial class GunComponent : Component { diff --git a/Content.Shared/Weapons/Ranged/Components/SolutionAmmoProviderComponent.cs b/Content.Shared/Weapons/Ranged/Components/SolutionAmmoProviderComponent.cs index d936f3a9e2fe..19c6af69b186 100644 --- a/Content.Shared/Weapons/Ranged/Components/SolutionAmmoProviderComponent.cs +++ b/Content.Shared/Weapons/Ranged/Components/SolutionAmmoProviderComponent.cs @@ -5,38 +5,38 @@ namespace Content.Shared.Weapons.Ranged.Components; -[RegisterComponent, NetworkedComponent, AutoGenerateComponentState, Access(typeof(SharedGunSystem))] +[RegisterComponent, NetworkedComponent, AutoGenerateComponentState(fieldDeltas: true), Access(typeof(SharedGunSystem))] public sealed partial class SolutionAmmoProviderComponent : Component { /// /// The solution where reagents are extracted from for the projectile. /// - [DataField("solutionId", required: true), AutoNetworkedField] + [DataField(required: true), AutoNetworkedField] public string SolutionId = default!; /// /// How much reagent it costs to fire once. /// - [DataField("fireCost"), ViewVariables(VVAccess.ReadWrite), AutoNetworkedField] + [DataField, AutoNetworkedField] public float FireCost = 5; /// /// The amount of shots currently available. /// used for network predictions. /// - [DataField("shots"), ViewVariables, AutoNetworkedField] + [DataField, AutoNetworkedField] public int Shots; /// /// The max amount of shots the gun can fire. /// used for network prediction /// - [DataField("maxShots"), ViewVariables, AutoNetworkedField] + [DataField, AutoNetworkedField] public int MaxShots; /// /// The prototype that's fired by the gun. /// - [DataField("proto", customTypeSerializer: typeof(PrototypeIdSerializer)), ViewVariables(VVAccess.ReadWrite)] - public string Prototype = default!; + [DataField("proto")] + public EntProtoId Prototype; } From 696ddb1b9ce9fc981022ec1421c5f81cddbf1a34 Mon Sep 17 00:00:00 2001 From: metalgearsloth Date: Sat, 21 Dec 2024 15:28:31 +1100 Subject: [PATCH 9/9] Update --- Content.Shared/Nutrition/EntitySystems/HungerSystem.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Content.Shared/Nutrition/EntitySystems/HungerSystem.cs b/Content.Shared/Nutrition/EntitySystems/HungerSystem.cs index ce55bebff253..a8697ffee455 100644 --- a/Content.Shared/Nutrition/EntitySystems/HungerSystem.cs +++ b/Content.Shared/Nutrition/EntitySystems/HungerSystem.cs @@ -122,7 +122,7 @@ private void SetAuthoritativeHungerValue(Entity entity, float v { entity.Comp.LastAuthoritativeHungerChangeTime = _timing.CurTime; entity.Comp.LastAuthoritativeHungerValue = ClampHungerWithinThresholds(entity.Comp, value); - Dirty(entity); + DirtyField(entity.Owner, entity.Comp, nameof(HungerComponent.LastAuthoritativeHungerChangeTime)); } private void UpdateCurrentThreshold(EntityUid uid, HungerComponent? component = null)