]> git.smokeofanarchy.ru Git - space-station-14.git/commitdiff
Implement some field-level deltas (#28242)
authormetalgearsloth <31366439+metalgearsloth@users.noreply.github.com>
Sat, 21 Dec 2024 04:54:11 +0000 (15:54 +1100)
committerGitHub <noreply@github.com>
Sat, 21 Dec 2024 04:54:11 +0000 (15:54 +1100)
* Update GasTileOverlayState

* Update DecalGridState

* Update NavMapState

* poke

* poke2

* poke3

* Implement field deltas for guns

* Content done

* Update

---------

Co-authored-by: ElectroJr <leonsfriedrich@gmail.com>
12 files changed:
Content.Server/Weapons/Ranged/Systems/GunSystem.Ballistic.cs
Content.Server/Weapons/Ranged/Systems/GunSystem.Solution.cs
Content.Shared/Nutrition/Components/HungerComponent.cs
Content.Shared/Nutrition/Components/ThirstComponent.cs
Content.Shared/Nutrition/EntitySystems/HungerSystem.cs
Content.Shared/Nutrition/EntitySystems/ThirstSystem.cs
Content.Shared/Weapons/Ranged/Components/AmmoComponent.cs
Content.Shared/Weapons/Ranged/Components/BallisticAmmoProviderComponent.cs
Content.Shared/Weapons/Ranged/Components/GunComponent.cs
Content.Shared/Weapons/Ranged/Components/SolutionAmmoProviderComponent.cs
Content.Shared/Weapons/Ranged/Systems/SharedGunSystem.Ballistic.cs
Content.Shared/Weapons/Ranged/Systems/SharedGunSystem.cs

index 798be3fc8eab6fb4b354abe79edb4e04db8e0ba0..60680deaaaa04dc839198606bb8da95a793f2b5b 100644 (file)
@@ -15,6 +15,7 @@ public sealed partial class GunSystem
         {
             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 @@ public sealed partial class GunSystem
         else if (component.UnspawnedCount > 0)
         {
             component.UnspawnedCount--;
+            DirtyField(uid, component, nameof(BallisticAmmoProviderComponent.UnspawnedCount));
             ent = Spawn(component.Proto, coordinates);
             EnsureShootable(ent.Value);
         }
index cc36132e8e50b4a7665e13a32fb77e176122f597..d0898efaaf84e9e44bd5e0c5f0922889a0db03aa 100644 (file)
@@ -39,8 +39,9 @@ public sealed partial class GunSystem
         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;
         }
 
@@ -48,8 +49,10 @@ public sealed partial class GunSystem
         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);
     }
index 33abb257dd10c03f3b1e709995c364e9a959668f..d5db991b1a002b19d48d1ae07e46e7fa765715d0 100644 (file)
@@ -10,7 +10,7 @@ using Robust.Shared.Serialization.TypeSerializers.Implementations.Generic;
 namespace Content.Shared.Nutrition.Components;
 
 [RegisterComponent, NetworkedComponent, Access(typeof(HungerSystem))]
-[AutoGenerateComponentState, AutoGenerateComponentPause]
+[AutoGenerateComponentState(fieldDeltas: true), AutoGenerateComponentPause]
 public sealed partial class HungerComponent : Component
 {
     /// <summary>
index f3ac881361fc5cf0f30e696cc2193db5fb94974a..5c32b4af286838fe7e95841eae386a3ecb406b5c 100644 (file)
@@ -7,7 +7,7 @@ using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom;
 namespace Content.Shared.Nutrition.Components;
 
 [RegisterComponent, NetworkedComponent, Access(typeof(ThirstSystem))]
-[AutoGenerateComponentState, AutoGenerateComponentPause]
+[AutoGenerateComponentState(fieldDeltas: true), AutoGenerateComponentPause]
 public sealed partial class ThirstComponent : Component
 {
     // Base stuff
index 063c1f6bb1a691db7c85082a2bb954fe9ba2276d..a8697ffee4553a536afec9926a8aa965a795523a 100644 (file)
@@ -122,7 +122,7 @@ public sealed class HungerSystem : EntitySystem
     {
         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)
@@ -133,6 +133,7 @@ public sealed class HungerSystem : EntitySystem
         var calculatedHungerThreshold = GetHungerThreshold(component);
         if (calculatedHungerThreshold == component.CurrentThreshold)
             return;
+
         component.CurrentThreshold = calculatedHungerThreshold;
         DoHungerThresholdEffects(uid, component);
     }
index 0b2bb2e0efacfb4b745db64b9f1acb218d257660..2937c48d482fd10406175502d423e460c667e72a 100644 (file)
@@ -102,7 +102,8 @@ public sealed class ThirstSystem : EntitySystem
             component.ThirstThresholds[ThirstThreshold.Dead],
             component.ThirstThresholds[ThirstThreshold.OverHydrated]
         );
-        Dirty(uid, component);
+
+        EntityManager.DirtyField(uid, component, nameof(ThirstComponent.CurrentThirst));
     }
 
     private bool IsMovementThreshold(ThirstThreshold threshold)
index 3e1111a97d177b008e8d51f673b5d933f63dc818..13cee5bad6f853c5c78ccb59f8b4fbef2ca80b88 100644 (file)
@@ -13,27 +13,27 @@ 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<EntityPrototype>))]
-    public string? MuzzleFlash = "MuzzleFlashEffect";
+    [DataField]
+    public EntProtoId? MuzzleFlash = "MuzzleFlashEffect";
 }
 
 /// <summary>
 /// Spawns another prototype to be shot instead of itself.
 /// </summary>
-[RegisterComponent, NetworkedComponent, AutoGenerateComponentState]
+[RegisterComponent, NetworkedComponent, AutoGenerateComponentState(fieldDeltas: true)]
 public sealed partial class CartridgeAmmoComponent : AmmoComponent
 {
-    [ViewVariables(VVAccess.ReadWrite), DataField("proto", required: true, customTypeSerializer: typeof(PrototypeIdSerializer<EntityPrototype>))]
-    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;
 
     /// <summary>
     /// Caseless ammunition.
     /// </summary>
-    [DataField("deleteOnSpawn")]
+    [DataField]
     public bool DeleteOnSpawn;
 
     [DataField("soundEject")]
index f825f10550d4d2e54ac116321794f4c5a6f16fc6..ee806125e786a2b781d8a901b1f07a2778cba731 100644 (file)
@@ -7,13 +7,13 @@ using Robust.Shared.Prototypes;
 
 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
 {
-    [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]
index 98b1d2fe2a4fba798d20a5607afa80f230555a83..3ec832613d2e01cab0fca5cdd832c54a4e3b0a93 100644 (file)
@@ -8,7 +8,7 @@ using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom;
 
 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
 {
index d936f3a9e2fed41f644642515d057ff3f794d746..19c6af69b1866d8b9bc35f2aa56891e133c1df6b 100644 (file)
@@ -5,38 +5,38 @@ using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototy
 
 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
 {
     /// <summary>
     /// The solution where reagents are extracted from for the projectile.
     /// </summary>
-    [DataField("solutionId", required: true), AutoNetworkedField]
+    [DataField(required: true), AutoNetworkedField]
     public string SolutionId = default!;
 
     /// <summary>
     /// How much reagent it costs to fire once.
     /// </summary>
-    [DataField("fireCost"), ViewVariables(VVAccess.ReadWrite), AutoNetworkedField]
+    [DataField, AutoNetworkedField]
     public float FireCost = 5;
 
     /// <summary>
     /// The amount of shots currently available.
     /// used for network predictions.
     /// </summary>
-    [DataField("shots"), ViewVariables, AutoNetworkedField]
+    [DataField, AutoNetworkedField]
     public int Shots;
 
     /// <summary>
     /// The max amount of shots the gun can fire.
     /// used for network prediction
     /// </summary>
-    [DataField("maxShots"), ViewVariables, AutoNetworkedField]
+    [DataField, AutoNetworkedField]
     public int MaxShots;
 
     /// <summary>
     /// The prototype that's fired by the gun.
     /// </summary>
-    [DataField("proto", customTypeSerializer: typeof(PrototypeIdSerializer<EntityPrototype>)), ViewVariables(VVAccess.ReadWrite)]
-    public string Prototype = default!;
+    [DataField("proto")]
+    public EntProtoId Prototype;
 }
index 9ef5cbd70285d6d0ad30032c3e89aaaeaf3a59a0..044f75dbc909e55810bb34fc489be239110c6018 100644 (file)
@@ -57,7 +57,7 @@ public abstract partial class SharedGunSystem
         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)
@@ -194,10 +194,9 @@ public abstract partial class SharedGunSystem
             !Paused(uid))
         {
             gunComp.NextFire = Timing.CurTime + TimeSpan.FromSeconds(1 / gunComp.FireRateModified);
-            Dirty(uid, gunComp);
+            DirtyField(uid, gunComp, nameof(GunComponent.NextFire));
         }
 
-        Dirty(uid, component);
         Audio.PlayPredicted(component.SoundRack, uid, user);
 
         var shots = GetBallisticShots(component);
@@ -228,7 +227,7 @@ public abstract partial class SharedGunSystem
         {
             component.UnspawnedCount = Math.Max(0, component.Capacity - component.Container.ContainedEntities.Count);
             UpdateBallisticAppearance(uid, component);
-            Dirty(uid, component);
+            DirtyField(uid, component, nameof(BallisticAmmoProviderComponent.UnspawnedCount));
         }
     }
 
@@ -249,18 +248,19 @@ public abstract partial class SharedGunSystem
 
                 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)
index c7cc09e618bdb5a2eccece7902af6d01d73f2449..62e63501ee8a6b03b12e0b8aa6ec950296fb4f23 100644 (file)
@@ -119,7 +119,7 @@ public abstract partial class SharedGunSystem : EntitySystem
         if (melee.NextAttack > component.NextFire)
         {
             component.NextFire = melee.NextAttack;
-            Dirty(uid, component);
+            EntityManager.DirtyField(uid, component, nameof(MeleeWeaponComponent.NextAttack));
         }
     }
 
@@ -200,7 +200,7 @@ public abstract partial class SharedGunSystem : EntitySystem
         gun.ShotCounter = 0;
         gun.ShootCoordinates = null;
         gun.Target = null;
-        Dirty(uid, gun);
+        EntityManager.DirtyField(uid, gun, nameof(GunComponent.ShotCounter));
     }
 
     /// <summary>
@@ -211,6 +211,7 @@ public abstract partial class SharedGunSystem : EntitySystem
         gun.ShootCoordinates = toCoordinates;
         AttemptShoot(user, gunUid, gun);
         gun.ShotCounter = 0;
+        EntityManager.DirtyField(gunUid, gun, nameof(GunComponent.ShotCounter));
     }
 
     /// <summary>
@@ -228,7 +229,9 @@ public abstract partial class SharedGunSystem : EntitySystem
     {
         if (gun.FireRateModified <= 0f ||
             !_actionBlockerSystem.CanAttack(user))
+        {
             return;
+        }
 
         var toCoordinates = gun.ShootCoordinates;
 
@@ -277,7 +280,7 @@ public abstract partial class SharedGunSystem : EntitySystem
         }
 
         // 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.
@@ -331,6 +334,7 @@ public abstract partial class SharedGunSystem : EntitySystem
         // 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)
         {
@@ -387,8 +391,6 @@ public abstract partial class SharedGunSystem : EntitySystem
             if (_gravity.IsWeightless(user, userPhysics))
                 CauseImpulse(fromCoordinates, toCoordinates.Value, user, userPhysics);
         }
-
-        Dirty(gunUid, gun);
     }
 
     public void Shoot(
@@ -442,7 +444,7 @@ public abstract partial class SharedGunSystem : EntitySystem
     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);
@@ -541,17 +543,59 @@ public abstract partial class SharedGunSystem : EntitySystem
 
         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);