Make DamageableComponent manually networked again (#43054)

This commit is contained in:
pathetic meowmeow 2026-02-27 11:22:45 -05:00 committed by Coryler
parent 3b9db7359b
commit 190421b7a0
3 changed files with 53 additions and 11 deletions

View File

@ -17,7 +17,7 @@ namespace Content.Shared.Damage.Components;
/// may also have resistances to certain damage types, defined via a <see cref="DamageModifierSetPrototype"/>.
/// </remarks>
[RegisterComponent]
[NetworkedComponent, AutoGenerateComponentState(true)]
[NetworkedComponent]
[Access(typeof(DamageableSystem), Other = AccessPermissions.ReadExecute)]
public sealed partial class DamageableComponent : Component
{
@ -25,7 +25,7 @@ public sealed partial class DamageableComponent : Component
/// This <see cref="DamageContainerPrototype"/> specifies what damage types are supported by this component.
/// If null, all damage types will be supported.
/// </summary>
[DataField("damageContainer"), AutoNetworkedField]
[DataField("damageContainer")]
// ReSharper disable once InconsistentNaming - This is wrong but fixing it is potentially annoying for downstreams.
public ProtoId<DamageContainerPrototype>? DamageContainerID;
@ -37,7 +37,7 @@ public sealed partial class DamageableComponent : Component
/// Though DamageModifierSets can be deserialized directly, we only want to use the prototype version here
/// to reduce duplication.
/// </remarks>
[DataField("damageModifierSet"), AutoNetworkedField]
[DataField("damageModifierSet")]
public ProtoId<DamageModifierSetPrototype>? DamageModifierSetId;
/// <summary>
@ -46,7 +46,7 @@ public sealed partial class DamageableComponent : Component
/// <remarks>
/// If this data-field is specified, this allows damageable components to be initialized with non-zero damage.
/// </remarks>
[DataField, AutoNetworkedField]
[DataField]
public DamageSpecifier Damage = new();
/// <summary>
@ -87,6 +87,20 @@ public sealed partial class DamageableComponent : Component
[DataField]
public ProtoId<HealthIconPrototype> RottingIcon = "HealthIconRotting";
[DataField, AutoNetworkedField]
[DataField]
public FixedPoint2? HealthBarThreshold;
}
[Serializable, NetSerializable]
public sealed class DamageableComponentState(
DamageSpecifier damage,
ProtoId<DamageContainerPrototype>? damageContainerId,
ProtoId<DamageModifierSetPrototype>? modifierSetId,
FixedPoint2? healthBarThreshold)
: ComponentState
{
public readonly DamageSpecifier Damage = damage;
public readonly ProtoId<DamageContainerPrototype>? DamageContainerId = damageContainerId;
public readonly ProtoId<DamageModifierSetPrototype>? ModifierSetId = modifierSetId;
public readonly FixedPoint2? HealthBarThreshold = healthBarThreshold;
}

View File

@ -20,7 +20,8 @@ public sealed partial class DamageableSystem
SubscribeLocalEvent<DamageableComponent, ComponentInit>(DamageableInit);
SubscribeLocalEvent<DamageableComponent, OnIrradiatedEvent>(OnIrradiated);
SubscribeLocalEvent<DamageableComponent, RejuvenateEvent>(OnRejuvenate);
SubscribeLocalEvent<DamageableComponent, AfterAutoHandleStateEvent>(OnAfterAutoHandleState);
SubscribeLocalEvent<DamageableComponent, ComponentHandleState>(DamageableHandleState);
SubscribeLocalEvent<DamageableComponent, ComponentGetState>(DamageableGetState);
_appearanceQuery = GetEntityQuery<AppearanceComponent>();
_damageableQuery = GetEntityQuery<DamageableComponent>();
@ -155,11 +156,6 @@ public sealed partial class DamageableSystem
}
}
private void OnAfterAutoHandleState(Entity<DamageableComponent> ent, ref AfterAutoHandleStateEvent args)
{
OnEntityDamageChanged(ent);
}
/// <summary>
/// Initialize a damageable component
/// </summary>
@ -190,6 +186,37 @@ public sealed partial class DamageableSystem
ClearAllDamage(ent.AsNullable());
_mobThreshold.SetAllowRevives(ent, false);
}
private void DamageableGetState(Entity<DamageableComponent> ent, ref ComponentGetState args)
{
args.State = new DamageableComponentState(
_netMan.IsServer ? ent.Comp.Damage : ent.Comp.Damage.Clone(),
ent.Comp.DamageContainerID,
ent.Comp.DamageModifierSetId,
ent.Comp.HealthBarThreshold
);
}
private void DamageableHandleState(Entity<DamageableComponent> ent, ref ComponentHandleState args)
{
if (args.Current is not DamageableComponentState state)
return;
ent.Comp.DamageContainerID = state.DamageContainerId;
ent.Comp.DamageModifierSetId = state.ModifierSetId;
ent.Comp.HealthBarThreshold = state.HealthBarThreshold;
// Has the damage actually changed?
var delta = state.Damage - ent.Comp.Damage;
delta.TrimZeros();
if (delta.Empty)
return;
ent.Comp.Damage = state.Damage;
OnEntityDamageChanged(ent, delta);
}
}
/// <summary>

View File

@ -17,6 +17,7 @@ public sealed partial class DamageableSystem : EntitySystem
{
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
[Dependency] private readonly SharedAppearanceSystem _appearance = default!;
[Dependency] private readonly INetManager _netMan = default!;
[Dependency] private readonly MobThresholdSystem _mobThreshold = default!;
[Dependency] private readonly IConfigurationManager _config = default!;
[Dependency] private readonly SharedChemistryGuideDataSystem _chemistryGuideData = default!;