#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? ruleIds = null) { var simulation = manager.GetComponentData(singleton); var economy = manager.GetComponentData(singleton); var core = manager.GetComponentData(singleton); var stats = manager.GetComponentData(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() : new List(ruleIds) }; using var entities = manager.GetAllEntities(Allocator.Temp); for (var i = 0; i < entities.Length; i++) { var entity = entities[i]; if (!manager.HasComponent(entity) || !manager.HasComponent(entity)) continue; var row = new Demo2SnapshotEntity { StableId = manager.GetComponentData(entity).Value }; var position = manager.GetComponentData(entity); row.X = position.X; row.Y = position.Y; if (manager.HasComponent(entity)) { var machine = manager.GetComponentData(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(entity)) row.TurretAmmo = manager.GetComponentData(entity).Value; } else if (manager.HasComponent(entity)) { var material = manager.GetComponentData(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(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(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(entity)) manager.AddComponentData(entity, new Demo2TurretAmmo()); if (manager.HasComponent(entity)) manager.SetComponentData(entity, new Demo2TurretAmmo { Value = row.TurretAmmo }); } if (row.StableId > simulation.NextStableId) simulation.NextStableId = row.StableId; } manager.SetComponentData(singleton, simulation); } } }