using ProjectM.Simulation;
using Unity.Entities;
using Unity.NetCode;
namespace ProjectM.Client
{
///
/// Client-only sender for shared-storage deposit/withdraw RPCs. A
/// one-off action (not per-tick predicted input), so it is an RPC: on an interact key edge (E =
/// deposit, Q = withdraw a default test item) it creates the request entity targeted at the server
/// connection, and the server applies it authoritatively in StorageOpReceiveSystem. Managed
/// SystemBase because it reads the managed Input System. Input System types are fully qualified and
/// using UnityEngine.InputSystem; is intentionally omitted (that namespace defines a
/// PlayerInput type that collides with ). An editor-only
/// static hook (Deposit/Withdraw) drives the same path from execute_code for headless validation
/// without a focused Game view.
///
[WorldSystemFilter(WorldSystemFilterFlags.ClientSimulation)]
public partial class StorageOpSendSystem : SystemBase
{
// Default test item used by the keyboard interact and the parameterless debug hooks.
const ushort DefaultItemId = 1;
const int DefaultCount = 1;
#if UNITY_EDITOR
struct PendingStorageOp { public byte Op; public ushort ItemId; public int Count; }
static readonly System.Collections.Generic.Queue s_Pending =
new System.Collections.Generic.Queue();
/// EDITOR / execute_code hook: queue a deposit of of .
public static void Deposit(ushort itemId = DefaultItemId, int count = DefaultCount) =>
s_Pending.Enqueue(new PendingStorageOp { Op = StorageOp.Deposit, ItemId = itemId, Count = count });
/// EDITOR / execute_code hook: queue a withdraw of of .
public static void Withdraw(ushort itemId = DefaultItemId, int count = DefaultCount) =>
s_Pending.Enqueue(new PendingStorageOp { Op = StorageOp.Withdraw, ItemId = itemId, Count = count });
#endif
protected override void OnCreate()
{
RequireForUpdate();
}
protected override void OnUpdate()
{
// Need the server connection to target the RPC; bail (keeping any queued ops) until connected.
if (!SystemAPI.TryGetSingletonEntity(out var connection))
return;
var keyboard = UnityEngine.InputSystem.Keyboard.current;
if (keyboard != null)
{
if (keyboard.eKey.wasPressedThisFrame)
Send(connection, StorageOp.Deposit, DefaultItemId, DefaultCount);
if (keyboard.qKey.wasPressedThisFrame)
Send(connection, StorageOp.Withdraw, DefaultItemId, DefaultCount);
}
#if UNITY_EDITOR
while (s_Pending.Count > 0)
{
var op = s_Pending.Dequeue();
Send(connection, op.Op, op.ItemId, op.Count);
}
#endif
}
void Send(Entity connection, byte op, ushort itemId, int count)
{
var request = EntityManager.CreateEntity();
EntityManager.AddComponentData(request, new StorageOpRequest { Op = op, ItemId = itemId, Count = count });
EntityManager.AddComponentData(request, new SendRpcCommandRequest { TargetConnection = connection });
}
}
}