using System.Collections.Generic; using AcDream.Core.Terrain; using AcDream.Core.World; namespace AcDream.App.Streaming; /// /// A job posted to 's inbox. Either a load /// (fetch this landblock from the dats and build its CPU-side mesh data) /// or an unload (release any state tied to this landblock on the render /// thread's next Tick drain). /// public abstract record LandblockStreamJob(uint LandblockId) { public sealed record Load(uint LandblockId, LandblockStreamJobKind Kind) : LandblockStreamJob(LandblockId); public sealed record Unload(uint LandblockId) : LandblockStreamJob(LandblockId); } /// /// Outbox record the render thread drains. Either a successful load, a /// failed load (logged and ignored until region recenters off/back), or /// an unload notification (tells the render thread to release GPU state /// for this landblock id). /// public abstract record LandblockStreamResult(uint LandblockId) { /// /// A landblock load completed. distinguishes Far /// (terrain only) from Near (terrain + entities). /// is built off the render thread on the streaming worker. /// public sealed record Loaded( uint LandblockId, LandblockStreamTier Tier, LoadedLandblock Landblock, LandblockMeshData MeshData ) : LandblockStreamResult(LandblockId); /// /// A previously-Far-resident landblock was promoted to Near. The result /// carries the full near landblock plus mesh data so the render thread can /// run the same near-tier side effects as a fresh LoadNear: cell visibility, /// building registries, EnvCell finalization, lighting, and static collision. /// GpuWorldState still merges only the entity layer so live entities already /// attached to the landblock are preserved. /// public sealed record Promoted( uint LandblockId, LoadedLandblock Landblock, LandblockMeshData MeshData ) : LandblockStreamResult(LandblockId) { public IReadOnlyList Entities => Landblock.Entities; } public sealed record Failed(uint LandblockId, string Error) : LandblockStreamResult(LandblockId); public sealed record Unloaded(uint LandblockId) : LandblockStreamResult(LandblockId); /// /// The worker loop itself crashed with an unhandled exception. Not tied /// to a specific landblock — distinguished from /// because consumers typically route this to a fatal-log path rather /// than retrying a single landblock later. LandblockId is 0 by /// convention; readers should pattern-match on the type, not the id. /// public sealed record WorkerCrashed(string Error) : LandblockStreamResult(0); }