Initial import
This commit is contained in:
219
Assets/Scripts/Hybrid/CommandDispatcher.cs
Normal file
219
Assets/Scripts/Hybrid/CommandDispatcher.cs
Normal file
@@ -0,0 +1,219 @@
|
||||
using Unity.Entities;
|
||||
using Unity.Mathematics;
|
||||
using Unity.Transforms;
|
||||
using Unity.Collections;
|
||||
using Unity.Physics;
|
||||
using UnityEngine;
|
||||
using EE2Clone.Components;
|
||||
using EE2Clone.NetCode;
|
||||
|
||||
namespace EE2Clone.Hybrid
|
||||
{
|
||||
/// <summary>
|
||||
/// Processes right-click context commands: move, attack, gather, build/repair.
|
||||
/// Sends the appropriate RPC to the server based on what was right-clicked.
|
||||
/// Client-side MonoBehaviour.
|
||||
/// </summary>
|
||||
public class CommandDispatcher : MonoBehaviour
|
||||
{
|
||||
private Camera _mainCamera;
|
||||
|
||||
private void Start()
|
||||
{
|
||||
_mainCamera = Camera.main;
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
var input = RTSInputActions.Instance;
|
||||
if (input == null || _mainCamera == null) return;
|
||||
|
||||
if (input.RightClickPressed)
|
||||
HandleRightClick(input.MousePosition);
|
||||
|
||||
if (input.StopPressed)
|
||||
HandleStop();
|
||||
}
|
||||
|
||||
private void HandleRightClick(Vector2 screenPos)
|
||||
{
|
||||
var selection = SelectionManager.Instance;
|
||||
if (selection == null || selection.SelectedEntities.Count == 0) return;
|
||||
|
||||
var world = World.DefaultGameObjectInjectionWorld;
|
||||
if (world == null || !world.IsCreated) return;
|
||||
|
||||
var em = world.EntityManager;
|
||||
var ray = _mainCamera.ScreenPointToRay(new Vector3(screenPos.x, screenPos.y, 0));
|
||||
|
||||
// Raycast to find what was clicked
|
||||
var physicsWorldQuery = em.CreateEntityQuery(typeof(PhysicsWorldSingleton));
|
||||
if (physicsWorldQuery.IsEmpty) return;
|
||||
|
||||
var physicsWorld = physicsWorldQuery.GetSingleton<PhysicsWorldSingleton>();
|
||||
var rayInput = new RaycastInput
|
||||
{
|
||||
Start = ray.origin,
|
||||
End = ray.origin + ray.direction * 500f,
|
||||
Filter = new CollisionFilter
|
||||
{
|
||||
BelongsTo = ~0u,
|
||||
CollidesWith = ~0u,
|
||||
GroupIndex = 0
|
||||
}
|
||||
};
|
||||
|
||||
Entity hitEntity = Entity.Null;
|
||||
float3 hitPosition = float3.zero;
|
||||
|
||||
if (physicsWorld.CastRay(rayInput, out var hit))
|
||||
{
|
||||
hitEntity = physicsWorld.Bodies[hit.RigidBodyIndex].Entity;
|
||||
hitPosition = hit.Position;
|
||||
}
|
||||
else
|
||||
{
|
||||
// No hit — use ground plane intersection
|
||||
if (ray.direction.y != 0)
|
||||
{
|
||||
float t = -ray.origin.y / ray.direction.y;
|
||||
if (t > 0)
|
||||
hitPosition = new float3(ray.origin.x + ray.direction.x * t, 0, ray.origin.z + ray.direction.z * t);
|
||||
}
|
||||
return; // Only move command if no entity hit
|
||||
}
|
||||
|
||||
// Determine command type based on what was clicked
|
||||
if (hitEntity != Entity.Null && em.Exists(hitEntity))
|
||||
{
|
||||
if (em.HasComponent<ResourceNodeTag>(hitEntity))
|
||||
{
|
||||
// Gather command for citizens
|
||||
SendGatherCommands(hitEntity);
|
||||
return;
|
||||
}
|
||||
|
||||
if (em.HasComponent<UnitTag>(hitEntity) || em.HasComponent<BuildingTag>(hitEntity))
|
||||
{
|
||||
if (em.HasComponent<OwnerPlayer>(hitEntity))
|
||||
{
|
||||
var owner = em.GetComponentData<OwnerPlayer>(hitEntity);
|
||||
// TODO: compare with local player id
|
||||
// For now, treat as enemy → attack
|
||||
SendAttackCommands(hitEntity);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (em.HasComponent<BuildingTag>(hitEntity) && em.HasComponent<UnderConstructionTag>(hitEntity))
|
||||
{
|
||||
// Build/repair command for citizens
|
||||
SendBuildRepairCommands(hitEntity);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Default: move command
|
||||
SendMoveCommands(hitPosition);
|
||||
}
|
||||
|
||||
private void SendMoveCommands(float3 position)
|
||||
{
|
||||
var world = World.DefaultGameObjectInjectionWorld;
|
||||
if (world == null) return;
|
||||
var em = world.EntityManager;
|
||||
|
||||
foreach (var unit in SelectionManager.Instance.SelectedEntities)
|
||||
{
|
||||
if (!em.Exists(unit) || !em.HasComponent<UnitTag>(unit)) continue;
|
||||
|
||||
var rpcEntity = em.CreateEntity();
|
||||
em.AddComponentData(rpcEntity, new MoveCommandRpc
|
||||
{
|
||||
UnitEntity = unit,
|
||||
TargetPosition = position
|
||||
});
|
||||
em.AddComponent<SendRpcCommandRequest>(rpcEntity);
|
||||
}
|
||||
}
|
||||
|
||||
private void SendAttackCommands(Entity target)
|
||||
{
|
||||
var world = World.DefaultGameObjectInjectionWorld;
|
||||
if (world == null) return;
|
||||
var em = world.EntityManager;
|
||||
|
||||
foreach (var unit in SelectionManager.Instance.SelectedEntities)
|
||||
{
|
||||
if (!em.Exists(unit) || !em.HasComponent<UnitTag>(unit)) continue;
|
||||
|
||||
var rpcEntity = em.CreateEntity();
|
||||
em.AddComponentData(rpcEntity, new AttackCommandRpc
|
||||
{
|
||||
AttackerEntity = unit,
|
||||
TargetEntity = target
|
||||
});
|
||||
em.AddComponent<SendRpcCommandRequest>(rpcEntity);
|
||||
}
|
||||
}
|
||||
|
||||
private void SendGatherCommands(Entity resourceNode)
|
||||
{
|
||||
var world = World.DefaultGameObjectInjectionWorld;
|
||||
if (world == null) return;
|
||||
var em = world.EntityManager;
|
||||
|
||||
foreach (var unit in SelectionManager.Instance.SelectedEntities)
|
||||
{
|
||||
if (!em.Exists(unit) || !em.HasComponent<CitizenTag>(unit)) continue;
|
||||
|
||||
var rpcEntity = em.CreateEntity();
|
||||
em.AddComponentData(rpcEntity, new GatherCommandRpc
|
||||
{
|
||||
CitizenEntity = unit,
|
||||
ResourceNodeEntity = resourceNode
|
||||
});
|
||||
em.AddComponent<SendRpcCommandRequest>(rpcEntity);
|
||||
}
|
||||
}
|
||||
|
||||
private void SendBuildRepairCommands(Entity building)
|
||||
{
|
||||
var world = World.DefaultGameObjectInjectionWorld;
|
||||
if (world == null) return;
|
||||
var em = world.EntityManager;
|
||||
|
||||
foreach (var unit in SelectionManager.Instance.SelectedEntities)
|
||||
{
|
||||
if (!em.Exists(unit) || !em.HasComponent<CitizenTag>(unit)) continue;
|
||||
|
||||
var rpcEntity = em.CreateEntity();
|
||||
em.AddComponentData(rpcEntity, new BuildRepairCommandRpc
|
||||
{
|
||||
CitizenEntity = unit,
|
||||
BuildingEntity = building
|
||||
});
|
||||
em.AddComponent<SendRpcCommandRequest>(rpcEntity);
|
||||
}
|
||||
}
|
||||
|
||||
private void HandleStop()
|
||||
{
|
||||
var world = World.DefaultGameObjectInjectionWorld;
|
||||
if (world == null) return;
|
||||
var em = world.EntityManager;
|
||||
|
||||
foreach (var unit in SelectionManager.Instance.SelectedEntities)
|
||||
{
|
||||
if (!em.Exists(unit) || !em.HasComponent<UnitTag>(unit)) continue;
|
||||
|
||||
var rpcEntity = em.CreateEntity();
|
||||
em.AddComponentData(rpcEntity, new StopCommandRpc
|
||||
{
|
||||
UnitEntity = unit
|
||||
});
|
||||
em.AddComponent<SendRpcCommandRequest>(rpcEntity);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user