M7 Automation: deterministic Harvester to Conveyor to Fabricator chains
Server-only production chains (never predicted): components + server systems + pure byte-only math (ProductionMath/ConveyorMath/MachineSlotMath), authoring + 3 machine prefabs wired into the Gameplay subscene, StructureCatalog rows, BuildPlace Direction/RuntimePlacedTag, Tuning, and 35 EditMode tests (catch-up gating, conveyor shuffle-invariance, SaveData v2 round-trip). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,85 @@
|
||||
using Unity.Entities;
|
||||
|
||||
namespace ProjectM.Simulation
|
||||
{
|
||||
/// <summary>
|
||||
/// Pure, deterministic deposit/withdraw/total helpers for a machine's server-only <see cref="MachineInput"/> /
|
||||
/// <see cref="MachineOutput"/> staging buffers — the byte-id, non-replicated twin of <see cref="StorageMath"/>
|
||||
/// (which serves the [GhostField] global <see cref="StorageEntry"/> ledger). No RNG/wall-clock. DynamicBuffer is
|
||||
/// a handle, so mutations apply to the underlying entity buffer. Overloaded per buffer type because the two
|
||||
/// element types are deliberately distinct (a machine can carry both without a singleton-buffer clash). Deposit
|
||||
/// is a no-op for count <= 0 or resource id 0; Withdraw clamps to available and drops a row at zero.
|
||||
/// </summary>
|
||||
public static class MachineSlotMath
|
||||
{
|
||||
// ---- MachineOutput ----
|
||||
public static void Deposit(DynamicBuffer<MachineOutput> buffer, byte resourceId, int count)
|
||||
{
|
||||
if (count <= 0 || resourceId == 0) return;
|
||||
for (int i = 0; i < buffer.Length; i++)
|
||||
if (buffer[i].ResourceId == resourceId)
|
||||
{
|
||||
var e = buffer[i]; e.Count += count; buffer[i] = e; return;
|
||||
}
|
||||
buffer.Add(new MachineOutput { ResourceId = resourceId, Count = count });
|
||||
}
|
||||
|
||||
public static int Withdraw(DynamicBuffer<MachineOutput> buffer, byte resourceId, int count)
|
||||
{
|
||||
if (count <= 0 || resourceId == 0) return 0;
|
||||
for (int i = 0; i < buffer.Length; i++)
|
||||
if (buffer[i].ResourceId == resourceId)
|
||||
{
|
||||
var e = buffer[i];
|
||||
int taken = e.Count < count ? e.Count : count;
|
||||
e.Count -= taken;
|
||||
if (e.Count <= 0) buffer.RemoveAt(i); else buffer[i] = e;
|
||||
return taken;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
public static int TotalOf(DynamicBuffer<MachineOutput> buffer, byte resourceId)
|
||||
{
|
||||
int total = 0;
|
||||
for (int i = 0; i < buffer.Length; i++)
|
||||
if (buffer[i].ResourceId == resourceId) total += buffer[i].Count;
|
||||
return total;
|
||||
}
|
||||
|
||||
// ---- MachineInput ----
|
||||
public static void Deposit(DynamicBuffer<MachineInput> buffer, byte resourceId, int count)
|
||||
{
|
||||
if (count <= 0 || resourceId == 0) return;
|
||||
for (int i = 0; i < buffer.Length; i++)
|
||||
if (buffer[i].ResourceId == resourceId)
|
||||
{
|
||||
var e = buffer[i]; e.Count += count; buffer[i] = e; return;
|
||||
}
|
||||
buffer.Add(new MachineInput { ResourceId = resourceId, Count = count });
|
||||
}
|
||||
|
||||
public static int Withdraw(DynamicBuffer<MachineInput> buffer, byte resourceId, int count)
|
||||
{
|
||||
if (count <= 0 || resourceId == 0) return 0;
|
||||
for (int i = 0; i < buffer.Length; i++)
|
||||
if (buffer[i].ResourceId == resourceId)
|
||||
{
|
||||
var e = buffer[i];
|
||||
int taken = e.Count < count ? e.Count : count;
|
||||
e.Count -= taken;
|
||||
if (e.Count <= 0) buffer.RemoveAt(i); else buffer[i] = e;
|
||||
return taken;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
public static int TotalOf(DynamicBuffer<MachineInput> buffer, byte resourceId)
|
||||
{
|
||||
int total = 0;
|
||||
for (int i = 0; i < buffer.Length; i++)
|
||||
if (buffer[i].ResourceId == resourceId) total += buffer[i].Count;
|
||||
return total;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user