57 lines
2.4 KiB
C#
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<) 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);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|