Initial import
This commit is contained in:
172
Assets/Scripts/Systems/GatheringSystems.cs
Normal file
172
Assets/Scripts/Systems/GatheringSystems.cs
Normal file
@@ -0,0 +1,172 @@
|
||||
using Unity.Burst;
|
||||
using Unity.Collections;
|
||||
using Unity.Entities;
|
||||
using Unity.Mathematics;
|
||||
using Unity.Transforms;
|
||||
using Unity.NetCode;
|
||||
using EE2Clone.Components;
|
||||
using EE2Clone.Core;
|
||||
|
||||
namespace EE2Clone.Systems
|
||||
{
|
||||
/// <summary>
|
||||
/// Server-side: processes GatherCommandRpc — assigns a gather target to citizens.
|
||||
/// </summary>
|
||||
[BurstCompile]
|
||||
[WorldSystemFilter(WorldSystemFilterFlags.ServerSimulation)]
|
||||
public partial struct GatherCommandSystem : ISystem
|
||||
{
|
||||
[BurstCompile]
|
||||
public void OnUpdate(ref SystemState state)
|
||||
{
|
||||
var ecb = new EntityCommandBuffer(Allocator.Temp);
|
||||
|
||||
foreach (var (cmd, source, entity) in
|
||||
SystemAPI.Query<RefRO<GatherCommandRpc>, RefRO<ReceiveRpcCommandRequest>>()
|
||||
.WithEntityAccess())
|
||||
{
|
||||
var citizen = cmd.ValueRO.CitizenEntity;
|
||||
var node = cmd.ValueRO.ResourceNodeEntity;
|
||||
|
||||
if (state.EntityManager.Exists(citizen) && state.EntityManager.Exists(node) &&
|
||||
state.EntityManager.HasComponent<CitizenStateComponent>(citizen) &&
|
||||
state.EntityManager.HasComponent<ResourceNode>(node))
|
||||
{
|
||||
state.EntityManager.SetComponentData(citizen, new GatherTarget { Target = node });
|
||||
state.EntityManager.SetComponentData(citizen, new CitizenStateComponent { Value = CitizenState.MovingToGather });
|
||||
|
||||
// Set move target to the resource node's position
|
||||
var nodePos = state.EntityManager.GetComponentData<LocalTransform>(node).Position;
|
||||
state.EntityManager.SetComponentData(citizen, new MoveTarget
|
||||
{
|
||||
Position = nodePos,
|
||||
IsActive = true
|
||||
});
|
||||
}
|
||||
|
||||
ecb.DestroyEntity(entity);
|
||||
}
|
||||
|
||||
ecb.Playback(state.EntityManager);
|
||||
ecb.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Server-side: citizen gathering state machine.
|
||||
/// Handles: MovingToGather → Gathering → MovingToDropoff → Depositing → repeat.
|
||||
/// </summary>
|
||||
[BurstCompile]
|
||||
[WorldSystemFilter(WorldSystemFilterFlags.ServerSimulation)]
|
||||
[UpdateAfter(typeof(GatherCommandSystem))]
|
||||
public partial struct GatheringSystem : ISystem
|
||||
{
|
||||
private float _gatherTimer;
|
||||
|
||||
public void OnCreate(ref SystemState state)
|
||||
{
|
||||
_gatherTimer = 0f;
|
||||
}
|
||||
|
||||
[BurstCompile]
|
||||
public void OnUpdate(ref SystemState state)
|
||||
{
|
||||
float dt = SystemAPI.Time.DeltaTime;
|
||||
_gatherTimer += dt;
|
||||
bool gatherTick = _gatherTimer >= GameConstants.GatherTickInterval;
|
||||
if (gatherTick) _gatherTimer -= GameConstants.GatherTickInterval;
|
||||
|
||||
foreach (var (citizenState, gatherTarget, carried, transform, moveTarget, owner) in
|
||||
SystemAPI.Query<RefRW<CitizenStateComponent>, RefRW<GatherTarget>,
|
||||
RefRW<CarriedResource>, RefRO<LocalTransform>, RefRW<MoveTarget>, RefRO<OwnerPlayer>>()
|
||||
.WithAll<CitizenTag>())
|
||||
{
|
||||
switch (citizenState.ValueRO.Value)
|
||||
{
|
||||
case CitizenState.MovingToGather:
|
||||
// Check if arrived (MoveTarget will be deactivated by movement system)
|
||||
if (!moveTarget.ValueRO.IsActive)
|
||||
{
|
||||
citizenState.ValueRW.Value = CitizenState.Gathering;
|
||||
}
|
||||
break;
|
||||
|
||||
case CitizenState.Gathering:
|
||||
if (!gatherTick) break;
|
||||
|
||||
var targetEntity = gatherTarget.ValueRO.Target;
|
||||
if (targetEntity == Entity.Null || !state.EntityManager.Exists(targetEntity))
|
||||
{
|
||||
citizenState.ValueRW.Value = CitizenState.Idle;
|
||||
break;
|
||||
}
|
||||
|
||||
var node = state.EntityManager.GetComponentData<ResourceNode>(targetEntity);
|
||||
if (node.RemainingAmount <= 0)
|
||||
{
|
||||
citizenState.ValueRW.Value = CitizenState.Idle;
|
||||
gatherTarget.ValueRW.Target = Entity.Null;
|
||||
break;
|
||||
}
|
||||
|
||||
// Gather one unit
|
||||
int gatherAmount = math.min(1, node.RemainingAmount);
|
||||
gatherAmount = math.min(gatherAmount, carried.ValueRO.MaxCarryCapacity - carried.ValueRO.Amount);
|
||||
|
||||
if (gatherAmount > 0)
|
||||
{
|
||||
node.RemainingAmount -= gatherAmount;
|
||||
state.EntityManager.SetComponentData(targetEntity, node);
|
||||
|
||||
carried.ValueRW.Amount += gatherAmount;
|
||||
carried.ValueRW.Type = node.Type;
|
||||
}
|
||||
|
||||
// If carrying capacity full, go to dropoff
|
||||
if (carried.ValueRO.Amount >= carried.ValueRO.MaxCarryCapacity)
|
||||
{
|
||||
citizenState.ValueRW.Value = CitizenState.MovingToDropoff;
|
||||
// TODO: Find nearest dropoff building and set as move target
|
||||
// For now, move back toward origin as placeholder
|
||||
moveTarget.ValueRW = new MoveTarget
|
||||
{
|
||||
Position = float3.zero,
|
||||
IsActive = true
|
||||
};
|
||||
}
|
||||
break;
|
||||
|
||||
case CitizenState.MovingToDropoff:
|
||||
if (!moveTarget.ValueRO.IsActive)
|
||||
{
|
||||
citizenState.ValueRW.Value = CitizenState.Depositing;
|
||||
}
|
||||
break;
|
||||
|
||||
case CitizenState.Depositing:
|
||||
// Deposit resources into player economy
|
||||
// TODO: Find PlayerResourcesComponent for this owner and add resources
|
||||
carried.ValueRW.Amount = 0;
|
||||
|
||||
// Go back to gather if the node still exists
|
||||
if (gatherTarget.ValueRO.Target != Entity.Null &&
|
||||
state.EntityManager.Exists(gatherTarget.ValueRO.Target))
|
||||
{
|
||||
var nodePos = state.EntityManager.GetComponentData<LocalTransform>(gatherTarget.ValueRO.Target).Position;
|
||||
moveTarget.ValueRW = new MoveTarget
|
||||
{
|
||||
Position = nodePos,
|
||||
IsActive = true
|
||||
};
|
||||
citizenState.ValueRW.Value = CitizenState.MovingToGather;
|
||||
}
|
||||
else
|
||||
{
|
||||
citizenState.ValueRW.Value = CitizenState.Idle;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user