36 lines
1.9 KiB
C#
36 lines
1.9 KiB
C#
using Unity.Entities;
|
|
|
|
namespace ProjectM.Simulation
|
|
{
|
|
/// <summary>
|
|
/// SERVER-ONLY expiry tracker paired with a <see cref="StatModifier"/> by <see cref="SourceId"/>. It is NOT a
|
|
/// [GhostField] and lives in a SEPARATE buffer so the replicated <see cref="StatModifier"/> layout stays
|
|
/// byte-identical — adding ANY member (even non-ghost) to a [GhostField] buffer element regenerates its
|
|
/// serializer/stride/hash = an effective ghost re-bake. To grant a TIMED buff, append both a StatModifier and a
|
|
/// TimedModifier sharing one unique SourceId; <c>TimedModifierExpirySystem</c> removes the matching StatModifier
|
|
/// when <see cref="UntilTick"/> elapses, and that removal replicates for free via the StatModifier [GhostField]
|
|
/// buffer (OwnerSendType.All), so StatRecomputeSystem reverts the effective stat on both worlds with no change.
|
|
/// </summary>
|
|
public struct TimedModifier : IBufferElementData
|
|
{
|
|
/// <summary>Matches the <see cref="StatModifier.SourceId"/> this row governs.</summary>
|
|
public uint SourceId;
|
|
|
|
/// <summary>Server tick at which the paired StatModifier expires (0 = no expiry / inert; schedule via TickUtil.NonZero).</summary>
|
|
public uint UntilTick;
|
|
}
|
|
|
|
/// <summary>Pure helpers for removing modifiers by provenance (clear-by-type / timed expiry). Deterministic, no RNG/wall-clock.</summary>
|
|
public static class TimedModifierUtil
|
|
{
|
|
/// <summary>Remove every <see cref="StatModifier"/> row whose SourceId matches (RemoveAtSwapBack). Returns the count removed.</summary>
|
|
public static int RemoveBySourceId(DynamicBuffer<StatModifier> mods, uint sourceId)
|
|
{
|
|
int removed = 0;
|
|
for (int j = mods.Length - 1; j >= 0; j--)
|
|
if (mods[j].SourceId == sourceId) { mods.RemoveAtSwapBack(j); removed++; }
|
|
return removed;
|
|
}
|
|
}
|
|
}
|