using ProjectM.Simulation; using Unity.Burst; using Unity.Collections; using Unity.Entities; using Unity.NetCode; namespace ProjectM.Server { /// /// SERVER-ONLY decoy-wisp lifecycle: despawns a decoy ghost when its Health is spent (Husks "killed" it) or /// its lifetime elapses. Server-authoritative ghost despawn (the client's /// copy is removed by GhostSendSystem — never DestroyEntity a ghost client-side). The decoy draws aggro via /// EnemyAISystem's decoy target set; this system only ends its life. Presence-gated on DecoyTag. /// [BurstCompile] [WorldSystemFilter(WorldSystemFilterFlags.ServerSimulation)] [UpdateInGroup(typeof(SimulationSystemGroup))] public partial struct DecoySystem : ISystem { [BurstCompile] public void OnCreate(ref SystemState state) { state.RequireForUpdate(); state.RequireForUpdate(); } [BurstCompile] public void OnUpdate(ref SystemState state) { var serverTick = SystemAPI.GetSingleton().ServerTick; if (!serverTick.IsValid) return; var ecb = new EntityCommandBuffer(Allocator.Temp); foreach (var (decoy, hp, e) in SystemAPI.Query, RefRO>().WithEntityAccess()) { bool expired = decoy.ValueRO.ExpireTick != 0u && !new NetworkTick(decoy.ValueRO.ExpireTick).IsNewerThan(serverTick); if (hp.ValueRO.Current <= 0f || expired) ecb.DestroyEntity(e); } ecb.Playback(state.EntityManager); ecb.Dispose(); } } }