Core Game Loop Additions
This commit is contained in:
@@ -0,0 +1,85 @@
|
||||
using ProjectM.Simulation;
|
||||
using Unity.Burst;
|
||||
using Unity.Collections;
|
||||
using Unity.Entities;
|
||||
using Unity.Mathematics;
|
||||
using Unity.Transforms;
|
||||
|
||||
namespace ProjectM.Server
|
||||
{
|
||||
/// <summary>
|
||||
/// Server-only walk-in gate transit: a player who walks within a gate's radius (and whose region matches the
|
||||
/// gate's <see cref="ExpeditionGate.FromRegion"/>) is transited to the gate's ToRegion at its ArrivalPos
|
||||
/// (RegionTag flipped + LocalTransform teleported — GhostRelevancy re-scopes their ghosts, as in
|
||||
/// <c>RegionTransitSystem</c>). Returning to the BASE during the Expedition phase expires the Expedition
|
||||
/// timer so Defend starts early ("timer cap + early return"). Plain server SimulationSystemGroup
|
||||
/// <c>[UpdateAfter(CyclePhaseSystem)]</c>. Arrival points are offset from the destination gate so a transited
|
||||
/// player does not immediately re-trigger.
|
||||
/// </summary>
|
||||
[BurstCompile]
|
||||
[WorldSystemFilter(WorldSystemFilterFlags.ServerSimulation)]
|
||||
[UpdateInGroup(typeof(SimulationSystemGroup))]
|
||||
[UpdateAfter(typeof(CyclePhaseSystem))]
|
||||
public partial struct ExpeditionGateSystem : ISystem
|
||||
{
|
||||
[BurstCompile]
|
||||
public void OnCreate(ref SystemState state)
|
||||
{
|
||||
state.RequireForUpdate<ExpeditionGate>();
|
||||
}
|
||||
|
||||
[BurstCompile]
|
||||
public void OnUpdate(ref SystemState state)
|
||||
{
|
||||
// Snapshot gates once.
|
||||
var gateFrom = new NativeList<byte>(Allocator.Temp);
|
||||
var gateTo = new NativeList<byte>(Allocator.Temp);
|
||||
var gateRadiusSq = new NativeList<float>(Allocator.Temp);
|
||||
var gatePos = new NativeList<float2>(Allocator.Temp);
|
||||
var gateArrival = new NativeList<float3>(Allocator.Temp);
|
||||
foreach (var (gate, xform) in SystemAPI.Query<RefRO<ExpeditionGate>, RefRO<LocalTransform>>())
|
||||
{
|
||||
gateFrom.Add(gate.ValueRO.FromRegion);
|
||||
gateTo.Add(gate.ValueRO.ToRegion);
|
||||
gateRadiusSq.Add(gate.ValueRO.Radius * gate.ValueRO.Radius);
|
||||
gatePos.Add(xform.ValueRO.Position.xz);
|
||||
gateArrival.Add(gate.ValueRO.ArrivalPos);
|
||||
}
|
||||
|
||||
bool returnedToBase = false;
|
||||
foreach (var (region, xform) in
|
||||
SystemAPI.Query<RefRW<RegionTag>, RefRW<LocalTransform>>().WithAll<PlayerTag>())
|
||||
{
|
||||
byte r = region.ValueRO.Region;
|
||||
float2 pp = xform.ValueRO.Position.xz;
|
||||
for (int i = 0; i < gateFrom.Length; i++)
|
||||
{
|
||||
if (gateFrom[i] != r) continue;
|
||||
if (math.distancesq(pp, gatePos[i]) > gateRadiusSq[i]) continue;
|
||||
region.ValueRW.Region = gateTo[i];
|
||||
xform.ValueRW.Position = gateArrival[i];
|
||||
if (gateTo[i] == RegionId.Base)
|
||||
returnedToBase = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
gateFrom.Dispose();
|
||||
gateTo.Dispose();
|
||||
gateRadiusSq.Dispose();
|
||||
gatePos.Dispose();
|
||||
gateArrival.Dispose();
|
||||
|
||||
// Early return: a player came back to base mid-Expedition -> expire the Expedition timer (-> Defend).
|
||||
if (returnedToBase && SystemAPI.TryGetSingletonEntity<CycleState>(out var cycleEntity))
|
||||
{
|
||||
var cs = SystemAPI.GetComponent<CycleState>(cycleEntity);
|
||||
if (cs.Phase == CyclePhase.Expedition)
|
||||
{
|
||||
cs.PhaseEndTick = 1; // CyclePhaseSystem sees timedPhaseDue next tick -> Defend
|
||||
SystemAPI.SetComponent(cycleEntity, cs);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user