using Unity.Entities; using Unity.Mathematics; using Unity.NetCode; namespace ProjectM.Simulation { /// /// Structure type ids (a byte, not an enum, per the cross-assembly enum-in-Burst hazard). Turret is the /// first concrete structure; Harvester/Fabricator/Conveyor are RESERVED now (free) for the M7 automation /// pillar (production chains) so adding them later is purely additive. /// public static class StructureType { public const byte None = 0; public const byte Turret = 1; // Reserved for M7 automation — do not reuse these codes: public const byte Harvester = 2; public const byte Fabricator = 3; public const byte Conveyor = 4; // World-pass structural/cosmetic build-out (additive; these byte values keep PlacedStructure.Type's // [GhostField] serializer identical — no re-bake of existing ghosts). Do NOT reuse 2-4 (M7 automation). public const byte Wall = 5; public const byte Pylon = 6; } /// /// A built base structure occupying one grid cell. An ownerless INTERPOLATED ghost (RegionTag{Base}, /// world-owned, runtime-spawned by BuildPlaceSystem). is the only replicated field /// (a cheap byte for client visual branching); is server-only (clients derive it from /// the replicated LocalTransform via , so it stays off the wire). /// / are server-only raw NetworkTick values /// (-guarded; 0 = inactive): the Turret reuses as its /// fire cooldown NOW (not dead weight), and M7 production reuses both as the next-production-tick + /// deterministic offline catch-up linchpin (produced = floor((now - LastProcessedTick)/period)). These two /// tick fields are the IDENTITY/TIMING that cannot be reconstructed retroactively, so they are baked now. /// public struct PlacedStructure : IComponentData { /// Structure type (see ); the only replicated field. [GhostField] public byte Type; /// Occupied grid cell (server-only; clients derive it from LocalTransform). public int2 Cell; /// Next action tick (server-only; turret cooldown now / next production tick in M7). 0 = inactive. public uint NextTick; /// Last tick this structure was processed (server-only; M7 offline-catch-up baseline). Stamped at spawn. public uint LastProcessedTick; } /// /// A buildable defense turret (the first structure). Hitscan: TurretFireSystem applies a direct /// DamageEvent to the nearest in-range living Husk on cooldown (reusing /// ) — reuses HealthApplyDamageSystem, no projectile/friendly-fire. /// public struct Turret : IComponentData { public float Range; public int CooldownTicks; public float Damage; } /// /// One row of the build catalog: cost + prefab per structure type. Modeled on AbilityPrefabElement /// (prefab baked via GetEntity, NEVER inside a blob — blobs don't remap entity refs). M7 adds a recipe /// column to this element additively (the catalog is baked, not replicated → no format break). /// public struct StructureCatalogEntry : IBufferElementData { public byte Type; public Entity Prefab; public byte CostResourceId; public int CostAmount; } /// Tag on the baked singleton carrying the buffer (the build cost/prefab table). public struct StructureCatalog : IComponentData { } }