Files
2026-06-04 11:35:57 -07:00

57 lines
2.4 KiB
C#

using ProjectM.Simulation;
using Unity.Burst;
using Unity.Entities;
using Unity.NetCode;
namespace ProjectM.Server
{
/// <summary>
/// Server-authoritative expiry of TIMED <see cref="StatModifier"/>s. Each tick it walks every entity's
/// server-only <see cref="TimedModifier"/> buffer; for any row whose <see cref="TimedModifier.UntilTick"/> has
/// elapsed (wrap-safe <see cref="Unity.NetCode.NetworkTick.IsNewerThan"/> compare, never raw uint&lt;) it removes
/// the matching StatModifier(s) by SourceId and the timed row. The shortened StatModifier [GhostField] buffer
/// auto-replicates (OwnerSendType.All), so StatRecomputeSystem reverts the effective stat on both worlds with no
/// change. Runs in the plain server <see cref="SimulationSystemGroup"/> (NOT the predicted loop) so it is applied
/// exactly once and never double-removed on rollback; a DynamicBuffer mutation is not a structural change, so it
/// is safe to mutate the iterated entity's own buffers in place.
/// </summary>
[BurstCompile]
[WorldSystemFilter(WorldSystemFilterFlags.ServerSimulation)]
[UpdateInGroup(typeof(SimulationSystemGroup))]
public partial struct TimedModifierExpirySystem : ISystem
{
[BurstCompile]
public void OnCreate(ref SystemState state)
{
state.RequireForUpdate<NetworkTime>();
state.RequireForUpdate(state.GetEntityQuery(ComponentType.ReadOnly<TimedModifier>()));
}
[BurstCompile]
public void OnUpdate(ref SystemState state)
{
var serverTick = SystemAPI.GetSingleton<NetworkTime>().ServerTick;
if (!serverTick.IsValid)
return;
foreach (var (timed, mods) in
SystemAPI.Query<DynamicBuffer<TimedModifier>, DynamicBuffer<StatModifier>>())
{
for (int i = timed.Length - 1; i >= 0; i--)
{
uint until = timed[i].UntilTick;
if (until == 0)
continue; // inert (no expiry scheduled)
var untilTick = new NetworkTick(until);
if (untilTick.IsValid && untilTick.IsNewerThan(serverTick))
continue; // not yet due
TimedModifierUtil.RemoveBySourceId(mods, timed[i].SourceId);
timed.RemoveAtSwapBack(i);
}
}
}
}
}