using ProjectM.Simulation;
using Unity.Burst;
using Unity.Collections;
using Unity.Entities;
using Unity.NetCode;
using Unity.Transforms;
namespace ProjectM.Server
{
///
/// Server-only, one-shot spawner for the GLOBAL cycle-director ghost (mirrors SharedStorageSpawnSystem,
/// but MINUS the RegionTag — the director must stay global so GhostRelevancy keeps it relevant to every
/// region). On its first update it reads the baked + NetworkTime,
/// instantiates the ghost, initializes (Expedition, cycle 1, PhaseEndTick =
/// now + ), adds the server-only , and
/// places it at the base center (preserving the prefab's baked LocalTransform scale — FromPosition would
/// reset the replicated Scale GhostField), then destroys the spawner so it idles.
///
[BurstCompile]
[WorldSystemFilter(WorldSystemFilterFlags.ServerSimulation)]
public partial struct CycleDirectorSpawnSystem : 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;
uint now = serverTick.TickIndexForValidTick;
var spawnerEntity = SystemAPI.GetSingletonEntity();
var spawner = SystemAPI.GetComponent(spawnerEntity);
var ecb = new EntityCommandBuffer(Allocator.Temp);
if (spawner.Prefab != Entity.Null)
{
var director = ecb.Instantiate(spawner.Prefab);
// Place at the base center, preserving the prefab's baked scale/rotation.
var xform = SystemAPI.GetComponent(spawner.Prefab);
if (SystemAPI.TryGetSingleton(out var anchor))
xform.Position = BaseGridMath.PlotCenter(anchor);
ecb.SetComponent(director, xform);
// Override the baked CycleState with the real start tick; add server-only bookkeeping.
ecb.SetComponent(director, new CycleState
{
Phase = CyclePhase.Expedition,
CycleNumber = 1,
PhaseEndTick = TickUtil.NonZero(now + CyclePhase.ExpeditionTicks),
});
ecb.AddComponent(director, new CycleRuntime { DefendStartWave = 0 });
}
// One-shot: remove the spawner so RequireForUpdate fails and the system idles.
ecb.DestroyEntity(spawnerEntity);
ecb.Playback(state.EntityManager);
}
}
}