Inventory: per-player items backbone (DR-026 Phase 0)
Data-driven ItemDatabase catalog + per-player replicated InventorySlot ([GhostField] OwnerSendType.All, a StatModifier twin). Harvest reroutes to the firing player's personal inventory (optional ComponentLookup<GhostOwner> in ResourceHarvestSystem; remainder/un-owned -> ledger); the G-key InventoryDepositRequest RPC moves the bag into the shared ledger the build economy spends. Catalog asset (Aether/Ore/Biomass + Stone Pickaxe) wired into the Gameplay subscene; read-only HUD inventory panel. ushort ItemId subsumes ResourceId; byte Category/Tier baked for gear-tier progression. Session-only (no SaveData bump). Play-validated host+client: catalog baked into both worlds, the re-baked player ghost carries InventorySlot with a clean handshake, a server write replicates to the client owner, the deposit RPC round-trips, and the HUD renders catalog names. See DR-026. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,64 @@
|
||||
using ProjectM.Simulation;
|
||||
using Unity.Entities;
|
||||
using Unity.NetCode;
|
||||
|
||||
namespace ProjectM.Client
|
||||
{
|
||||
/// <summary>
|
||||
/// Client-only sender for <see cref="InventoryDepositRequest"/> RPCs (move the local player's PERSONAL
|
||||
/// inventory into the shared base stockpile / global ledger). A one-off action (not per-tick predicted
|
||||
/// input), so it is an RPC: on the deposit key edge (G = deposit ALL) it creates the request entity
|
||||
/// targeted at the server connection, and the server applies it authoritatively in
|
||||
/// <see cref="ProjectM.Server.InventoryDepositSystem"/>. Managed SystemBase because it reads the managed
|
||||
/// Input System; Input System types are fully qualified and <c>using UnityEngine.InputSystem;</c> is
|
||||
/// intentionally omitted (that namespace defines a PlayerInput type that collides with
|
||||
/// <see cref="ProjectM.Simulation.PlayerInput"/>). An editor-only static hook (<see cref="Deposit"/>)
|
||||
/// drives the same path from execute_code for headless validation without a focused Game view. The wire
|
||||
/// type is unconditional; only this send SYSTEM is build-time managed.
|
||||
/// </summary>
|
||||
[WorldSystemFilter(WorldSystemFilterFlags.ClientSimulation)]
|
||||
public partial class InventoryDepositSendSystem : SystemBase
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
struct PendingDeposit { public ushort ItemId; public int Count; }
|
||||
|
||||
static readonly System.Collections.Generic.Queue<PendingDeposit> s_Pending =
|
||||
new System.Collections.Generic.Queue<PendingDeposit>();
|
||||
|
||||
/// <summary>EDITOR / execute_code hook: queue a deposit (ItemId 0 = deposit all; Count <= 0 = all of that item).</summary>
|
||||
public static void Deposit(ushort itemId = 0, int count = 0) =>
|
||||
s_Pending.Enqueue(new PendingDeposit { ItemId = itemId, Count = count });
|
||||
#endif
|
||||
|
||||
protected override void OnCreate()
|
||||
{
|
||||
RequireForUpdate<NetworkId>();
|
||||
}
|
||||
|
||||
protected override void OnUpdate()
|
||||
{
|
||||
// Need the server connection to target the RPC; bail (keeping any queued ops) until connected.
|
||||
if (!SystemAPI.TryGetSingletonEntity<NetworkId>(out var connection))
|
||||
return;
|
||||
|
||||
var keyboard = UnityEngine.InputSystem.Keyboard.current;
|
||||
if (keyboard != null && keyboard.gKey.wasPressedThisFrame)
|
||||
Send(connection, 0, 0); // G -> deposit everything to the base stockpile
|
||||
|
||||
#if UNITY_EDITOR
|
||||
while (s_Pending.Count > 0)
|
||||
{
|
||||
var d = s_Pending.Dequeue();
|
||||
Send(connection, d.ItemId, d.Count);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void Send(Entity connection, ushort itemId, int count)
|
||||
{
|
||||
var request = EntityManager.CreateEntity();
|
||||
EntityManager.AddComponentData(request, new InventoryDepositRequest { ItemId = itemId, Count = count });
|
||||
EntityManager.AddComponentData(request, new SendRpcCommandRequest { TargetConnection = connection });
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user