Files
Workspace/Assets/Demos/Demo2/ECS/Demo2SnapshotCodec.cs
T
2026-08-18 02:03:34 +08:00

146 lines
7.3 KiB
C#

#nullable enable
using System.Collections.Generic;
using Demo2.Domain;
using Unity.Collections;
using Unity.Entities;
namespace Demo2.ECS
{
public static class Demo2SnapshotCodec
{
public static Demo2Snapshot Capture(EntityManager manager, Entity singleton, IReadOnlyList<string>? ruleIds = null)
{
var simulation = manager.GetComponentData<Demo2SimulationState>(singleton);
var economy = manager.GetComponentData<Demo2EconomyState>(singleton);
var core = manager.GetComponentData<Demo2CoreHealth>(singleton);
var stats = manager.GetComponentData<Demo2CycleStats>(singleton);
var snapshot = new Demo2Snapshot
{
Tick = simulation.Tick,
Seed = simulation.Seed,
Phase = simulation.Phase,
Cycle = simulation.Cycle,
CoreHealth = core.Value,
Money = economy.Money,
Payload = economy.Payload,
MultiplierMilli = economy.MultiplierMilli,
Energy = economy.Energy,
ExcessFirepower = economy.ExcessFirepower,
RuleAppliedCycle = simulation.RuleAppliedCycle,
SpeedMultiplier = simulation.SpeedMultiplier,
Extracted = stats.Extracted,
Transported = stats.Transported,
Processed = stats.Processed,
AmmoProduced = stats.AmmoProduced,
CompletedSameRecipeStreak = stats.CompletedSameRecipeStreak,
LastRecipeId = stats.LastRecipeId,
Faults = stats.Faults,
BeltOccupancy = stats.BeltOccupancy,
BeltCapacity = stats.BeltCapacity,
IronFuelAdjacent = stats.IronFuelAdjacent,
FirstBatch = stats.FirstBatch,
DuplicateNextOutputs = stats.DuplicateNextOutputs,
StateHash = simulation.StateHash,
RuleIds = ruleIds == null ? new List<string>() : new List<string>(ruleIds)
};
using var entities = manager.GetAllEntities(Allocator.Temp);
for (var i = 0; i < entities.Length; i++)
{
var entity = entities[i];
if (!manager.HasComponent<Demo2StableId>(entity) || !manager.HasComponent<Demo2GridPosition>(entity)) continue;
var row = new Demo2SnapshotEntity { StableId = manager.GetComponentData<Demo2StableId>(entity).Value };
var position = manager.GetComponentData<Demo2GridPosition>(entity);
row.X = position.X;
row.Y = position.Y;
if (manager.HasComponent<Demo2MachineState>(entity))
{
var machine = manager.GetComponentData<Demo2MachineState>(entity);
row.MachineKind = machine.Kind;
row.Rotation = machine.Rotation;
row.RecipeId = machine.RecipeId;
row.Progress = machine.ProgressTicks;
row.Quantity = machine.StoredInput;
row.Faults = machine.Faults;
row.PendingOutputs = machine.PendingOutputs;
if (manager.HasComponent<Demo2TurretAmmo>(entity)) row.TurretAmmo = manager.GetComponentData<Demo2TurretAmmo>(entity).Value;
}
else if (manager.HasComponent<Demo2MaterialState>(entity))
{
var material = manager.GetComponentData<Demo2MaterialState>(entity);
row.MaterialKind = material.Kind;
row.Rotation = material.Direction;
row.Progress = material.SubCellProgress;
row.Quantity = material.Quantity;
row.MachineKind = (Demo2MachineKind)255;
}
snapshot.Entities.Add(row);
}
snapshot.Entities.Sort((left, right) => left.StableId.CompareTo(right.StableId));
return snapshot;
}
public static void Restore(EntityManager manager, Entity singleton, Demo2Snapshot snapshot)
{
using (var all = manager.GetAllEntities(Allocator.Temp))
for (var i = 0; i < all.Length; i++) if (all[i] != singleton) manager.DestroyEntity(all[i]);
var simulation = manager.GetComponentData<Demo2SimulationState>(singleton);
simulation.Tick = snapshot.Tick;
simulation.Seed = snapshot.Seed;
simulation.Phase = snapshot.Phase;
simulation.Cycle = snapshot.Cycle;
simulation.StateHash = snapshot.StateHash;
simulation.RuleAppliedCycle = snapshot.RuleAppliedCycle;
simulation.SpeedMultiplier = snapshot.SpeedMultiplier;
simulation.NextStableId = 0;
manager.SetComponentData(singleton, simulation);
manager.SetComponentData(singleton, new Demo2CoreHealth { Value = snapshot.CoreHealth });
manager.SetComponentData(singleton, new Demo2EconomyState
{
Money = snapshot.Money, Payload = snapshot.Payload, MultiplierMilli = snapshot.MultiplierMilli,
Energy = snapshot.Energy,
ExcessFirepower = snapshot.ExcessFirepower
});
manager.SetComponentData(singleton, new Demo2CycleStats
{
Extracted = snapshot.Extracted,
Transported = snapshot.Transported,
Processed = snapshot.Processed,
AmmoProduced = snapshot.AmmoProduced,
CompletedSameRecipeStreak = snapshot.CompletedSameRecipeStreak,
LastRecipeId = snapshot.LastRecipeId,
Faults = snapshot.Faults,
BeltOccupancy = snapshot.BeltOccupancy,
BeltCapacity = snapshot.BeltCapacity,
IronFuelAdjacent = snapshot.IronFuelAdjacent,
FirstBatch = snapshot.FirstBatch,
DuplicateNextOutputs = snapshot.DuplicateNextOutputs
});
foreach (var row in snapshot.Entities)
{
if ((byte)row.MachineKind == 255)
Demo2EcsFactory.CreateMaterial(manager, row.StableId, row.MaterialKind, row.X, row.Y, row.Rotation, row.Quantity);
else
{
var entity = Demo2EcsFactory.CreateMachine(manager, row.StableId, row.MachineKind, row.X, row.Y, row.Rotation, row.RecipeId);
var machine = manager.GetComponentData<Demo2MachineState>(entity);
machine.ProgressTicks = row.Progress;
machine.StoredInput = row.Quantity;
machine.Faults = row.Faults;
machine.PendingOutputs = row.PendingOutputs;
manager.SetComponentData(entity, machine);
if (row.MachineKind == Demo2MachineKind.Turret && !manager.HasComponent<Demo2TurretAmmo>(entity))
manager.AddComponentData(entity, new Demo2TurretAmmo());
if (manager.HasComponent<Demo2TurretAmmo>(entity))
manager.SetComponentData(entity, new Demo2TurretAmmo { Value = row.TurretAmmo });
}
if (row.StableId > simulation.NextStableId) simulation.NextStableId = row.StableId;
}
manager.SetComponentData(singleton, simulation);
}
}
}