2026-06-13 09:15:59 +01:00
using Aetheria.State ;
using Aetheria.State.Unity ;
2026-06-13 12:04:11 +01:00
using GameCult.Aetheria.State.Unity ;
2026-06-13 16:44:24 +01:00
using GameCult.Eve.Surface ;
2026-06-13 09:15:59 +01:00
var root = args . Length > 0 ? Path . GetFullPath ( args [ 0 ] ) : Directory . GetCurrentDirectory ( ) ;
var statePath = args . Length > 1
? Path . GetFullPath ( args [ 1 ] )
: AetheriaStatePaths . ResolveDefaultStatePath ( root ) ;
await using var client = await AetheriaRuntimeCatalogClient . OpenAsync ( statePath ) ;
var catalog = client . ReadCatalog ( ) ;
2026-06-13 12:24:27 +01:00
var packageCatalog = AetheriaRuntimeCatalogStore . OpenReadOnly ( statePath ) ;
2026-06-13 16:15:03 +01:00
var packageSurfaces = AetheriaRuntimeCatalogStore . ReadEveSurfaces ( statePath ) ;
2026-06-13 09:15:59 +01:00
var surface = await client . ReadCatalogSurfaceAsync ( ) ;
2026-06-13 15:27:12 +01:00
var commitSmokeDirectory = Path . Combine ( Path . GetTempPath ( ) , "aetheria-state-unity-smoke" , Guid . NewGuid ( ) . ToString ( "N" ) ) ;
var commitSmokeStatePath = Path . Combine ( commitSmokeDirectory , "aetheria-world.cc" ) ;
Directory . CreateDirectory ( commitSmokeDirectory ) ;
2026-06-13 09:15:59 +01:00
if ( catalog . Items . Count ! = 115 )
{
throw new InvalidOperationException ( $"Expected 115 runtime catalog items, found {catalog.Items.Count}." ) ;
}
2026-06-13 12:24:27 +01:00
if ( packageCatalog . Items . Count ! = catalog . Items . Count | |
packageCatalog . Corporations . Count ! = catalog . Corporations . Count | |
packageCatalog . NameFiles . Count ! = catalog . NameFiles . Count )
{
throw new InvalidOperationException (
$"Package catalog store mismatch: {packageCatalog.Items.Count}/{packageCatalog.Corporations.Count}/{packageCatalog.NameFiles.Count} " +
$"!= {catalog.Items.Count}/{catalog.Corporations.Count}/{catalog.NameFiles.Count}." ) ;
}
2026-06-13 09:15:59 +01:00
if ( catalog . TradeItems . Count = = 0 )
{
throw new InvalidOperationException ( "Runtime catalog has no trade items." ) ;
}
if ( catalog . EquipmentItems . Count = = 0 )
{
throw new InvalidOperationException ( "Runtime catalog has no equipment items." ) ;
}
2026-06-13 09:32:24 +01:00
var shaped = catalog . Items . FirstOrDefault ( item = > item . ShapeCells . Count > 0 )
? ? throw new InvalidOperationException ( "Runtime catalog has no typed shape masks." ) ;
2026-06-13 12:24:27 +01:00
var packageShaped = packageCatalog . FindItemByLegacyId ( shaped . LegacyId ) ;
if ( packageShaped = = null | |
packageShaped . Name ! = shaped . Name | |
packageShaped . ShapeCells . Count ! = shaped . ShapeCells . Count )
{
throw new InvalidOperationException ( $"Package catalog store did not read the expected typed item payload for {shaped.Name}." ) ;
}
2026-06-13 09:32:24 +01:00
if ( shaped . ShapeCells . Count ! = shaped . OccupiedCells )
{
throw new InvalidOperationException (
$"Runtime shape mask count mismatch for {shaped.Name}: cells={shaped.ShapeCells.Count}, occupied={shaped.OccupiedCells}." ) ;
}
if ( shaped . ShapeCells . Any ( cell = > cell . X < 0 | | cell . Y < 0 | | cell . X > = shaped . ShapeWidth | | cell . Y > = shaped . ShapeHeight ) )
{
throw new InvalidOperationException ( $"Runtime shape mask has out-of-bounds cells for {shaped.Name}." ) ;
}
2026-06-13 09:47:25 +01:00
var interior = catalog . Items . FirstOrDefault ( item = > item . InteriorShapeCells . Count > 0 )
? ? throw new InvalidOperationException ( "Runtime catalog has no typed interior shape masks." ) ;
if ( interior . InteriorShapeCells . Count ! = interior . InteriorOccupiedCells )
{
throw new InvalidOperationException (
$"Runtime interior shape mask count mismatch for {interior.Name}: cells={interior.InteriorShapeCells.Count}, occupied={interior.InteriorOccupiedCells}." ) ;
}
var hardpointHost = catalog . Items . FirstOrDefault ( item = > item . Hardpoints . Count > 0 )
? ? throw new InvalidOperationException ( "Runtime catalog has no typed hardpoints." ) ;
var hardpoint = hardpointHost . Hardpoints . First ( ) ;
if ( hardpoint . ShapeCells . Count ! = hardpoint . OccupiedCells )
{
throw new InvalidOperationException (
$"Runtime hardpoint shape count mismatch for {hardpointHost.Name}: cells={hardpoint.ShapeCells.Count}, occupied={hardpoint.OccupiedCells}." ) ;
}
2026-06-13 09:15:59 +01:00
var behaviorKind = catalog . Items . SelectMany ( item = > item . BehaviorKinds ) . FirstOrDefault ( )
? ? throw new InvalidOperationException ( "Runtime catalog has no behavior kind fingerprints." ) ;
if ( ! catalog . FindItemsByBehavior ( behaviorKind ) . Any ( ) )
{
throw new InvalidOperationException ( $"Runtime catalog behavior lookup failed for {behaviorKind}." ) ;
}
2026-06-13 10:01:20 +01:00
var behaviorHost = catalog . Items . FirstOrDefault ( item = > item . BehaviorPayloads . Count > 0 )
? ? throw new InvalidOperationException ( "Runtime catalog has no typed behavior payloads." ) ;
if ( ! behaviorHost . BehaviorPayloads . All ( payload = > behaviorHost . BehaviorKinds . Contains ( payload . Kind ) ) )
{
throw new InvalidOperationException (
$"Runtime behavior payload kind index mismatch for {behaviorHost.Name}." ) ;
}
var behaviorPayload = behaviorHost . BehaviorPayloads . First ( ) ;
if ( behaviorPayload . Fields . Count = = 0 )
{
throw new InvalidOperationException ( $"Runtime behavior payload has no fields for {behaviorHost.Name}." ) ;
}
2026-06-13 09:15:59 +01:00
var equipment = catalog . EquipmentItems . First ( ) ;
if ( ! catalog . FindItemsByHardpoint ( equipment . HardpointType ) . Any ( ) )
{
throw new InvalidOperationException ( $"Runtime catalog hardpoint lookup failed for {equipment.HardpointType}." ) ;
}
var manufactured = catalog . Items . FirstOrDefault ( item = > ! string . IsNullOrWhiteSpace ( item . ManufacturerLegacyId ) )
? ? throw new InvalidOperationException ( "Runtime catalog has no manufactured item." ) ;
if ( catalog . GetManufacturer ( manufactured ) = = null )
{
throw new InvalidOperationException ( $"Runtime catalog manufacturer lookup failed for {manufactured.Name}." ) ;
}
2026-06-13 12:24:27 +01:00
var packageCorporation = packageCatalog . Corporations . FirstOrDefault ( corporation = > ! string . IsNullOrWhiteSpace ( corporation . GeonameFileLegacyId ) ) ;
2026-06-13 13:18:03 +01:00
if ( packageCorporation = = null )
{
throw new InvalidOperationException ( "Package catalog store did not read any corporation name-file links." ) ;
}
var packageNameFile = packageCatalog . GetNameFile ( packageCorporation ) ;
2026-06-13 12:46:34 +01:00
if ( packageNameFile = = null | | packageNameFile . Names . Count = = 0 | | packageNameFile . Names . Count ! = packageNameFile . NameCount )
2026-06-13 12:24:27 +01:00
{
2026-06-13 12:46:34 +01:00
throw new InvalidOperationException ( "Package catalog store did not read corporation/name-file links with full names." ) ;
2026-06-13 12:24:27 +01:00
}
2026-06-13 13:18:03 +01:00
if ( packageCorporation . Allegiances . Count = = 0 | | packageCorporation . Allegiances . Count ! = packageCorporation . AllegianceCount )
{
throw new InvalidOperationException ( "Package catalog store did not read corporation allegiance edges." ) ;
}
2026-06-13 09:15:59 +01:00
if ( surface ? . Schema ! = "gamecult.eve.surface.v1" | |
surface . Surface . Id ! = AetheriaCatalogSurfaceProjector . SurfaceId )
{
throw new InvalidOperationException ( "Runtime catalog client did not read the typed Eve surface." ) ;
}
2026-06-13 16:15:03 +01:00
var packageSurface = packageSurfaces . FirstOrDefault ( candidate = > candidate . Surface . Id = = AetheriaCatalogSurfaceProjector . SurfaceId ) ;
if ( packageSurface = = null | |
packageSurface . Schema ! = "gamecult.eve.surface.v1" | |
packageSurface . ProviderId ! = "aetheria" | |
packageSurface . Surface . Root . Kind ! = "surface" | |
packageSurface . Surface . Root . Children . Count = = 0 | |
packageSurface . Commands . All ( command = > command . Command ! = "aetheria.catalog.refresh" ) )
{
throw new InvalidOperationException ( "Package runtime store did not read the typed Eve surface contract from CultCache." ) ;
}
2026-06-13 15:27:12 +01:00
try
{
var commit = AetheriaRuntimeStateCommitLog . QueuePlayerSettings (
commitSmokeStatePath ,
new AetheriaRuntimePlayerSettingsCommit
{
PlayerName = "Unity smoke" ,
TutorialPassed = true ,
ActionBarInputs = new [ ] { "<Keyboard>/1" }
} ) ;
2026-06-13 15:37:05 +01:00
AetheriaRuntimeStateCommitLog . QueueRunCheckpoint (
commitSmokeStatePath ,
new AetheriaRuntimeRunCheckpointCommit
{
RunId = "smoke-run" ,
CurrentZoneIndex = 0 ,
CurrentZoneEntityIndex = 0 ,
DiscoveredZoneIndices = new [ ] { 0 } ,
2026-06-14 11:53:55 +01:00
ActionBarBindings = new [ ]
{
new AetheriaRuntimeActionBarBindingCommit
{
ControlPath = "<Keyboard>/1" ,
Kind = "weapon_group" ,
WeaponGroup = 0
} ,
new AetheriaRuntimeActionBarBindingCommit
{
ControlPath = "<Keyboard>/2" ,
Kind = "gear" ,
ItemDefinitionLegacyId = "smoke:weapon" ,
EquipmentIndex = 0 ,
BehaviorIndex = 1
}
} ,
2026-06-14 12:02:47 +01:00
FactionRelationships = new [ ]
{
new AetheriaRuntimeFactionRelationshipCommit
{
CorporationLegacyId = "smoke:faction" ,
Relationship = "Friendly" ,
Standing = 3
}
} ,
2026-06-13 15:37:05 +01:00
Zones = new [ ]
{
new AetheriaRuntimeZoneSnapshotCommit
{
ZoneIndex = 0 ,
Name = "Unity Smoke Zone" ,
PositionX = 12.0 ,
PositionY = - 4.0 ,
AdjacentZoneIndices = new [ ] { 1 } ,
OwnerFactionIndex = 0 ,
Entities = new [ ]
{
new AetheriaRuntimeEntitySnapshotCommit
{
EntityIndex = 0 ,
Name = "Unity Smoke Ship" ,
Kind = "ship" ,
PositionX = 1.0 ,
PositionY = 2.0 ,
PositionZ = 3.0 ,
DirectionX = 0.0 ,
DirectionY = 1.0 ,
2026-06-13 21:30:42 +01:00
HullItemDefinitionLegacyId = "smoke:hull" ,
2026-06-13 15:37:05 +01:00
Equipment = new [ ]
{
new AetheriaRuntimeLoadoutItemSlotCommit
{
X = 0 ,
Y = 0 ,
Item = new AetheriaRuntimeLoadoutItemCommit
{
2026-06-13 21:30:42 +01:00
ItemDefinitionLegacyId = "smoke:weapon" ,
2026-06-13 15:37:05 +01:00
Quality = 0.9 ,
Durability = 0.8
}
}
} ,
WeaponGroups = new [ ] { new [ ] { 0 } }
}
}
}
}
} ) ;
2026-06-13 15:27:12 +01:00
var pending = AetheriaRuntimeStateCommitLog . ReadPending ( commitSmokeStatePath ) ;
2026-06-13 15:37:05 +01:00
if ( pending . Count ! = 2 | |
2026-06-13 15:27:12 +01:00
pending [ 0 ] . Kind ! = AetheriaRuntimeCommitKind . PlayerSettings | |
pending [ 0 ] . Schema ! = AetheriaRuntimeStateCommitLog . CommitSchema | |
pending [ 0 ] . Path ! = commit . Path )
{
throw new InvalidOperationException ( "Runtime state commit log did not read the queued player settings command." ) ;
}
2026-06-13 22:26:43 +01:00
var typedNodeApplied = false ;
await using ( var commitNode = await AetheriaStateNode . OpenAsync ( commitSmokeStatePath , "aetheria-unity-runtime-commit-smoke" ) )
{
var report = await AetheriaRuntimeCommitLogApplier . ApplyPendingAsync ( commitNode ) ;
var settings = await commitNode . GetPlayerSettingsAsync ( ) ;
var run = await commitNode . GetRunStateAsync ( new ( "global:aetheria.run_state.smoke-run.v1" ) ) ;
var zone = await commitNode . GetZoneStateAsync ( new ( "global:aetheria.run_state.smoke-run.zone.0.v1" ) ) ;
var entity = await commitNode . GetEntitySnapshotAsync ( new ( "global:aetheria.run_state.smoke-run.zone.0.entity.0.v1" ) ) ;
typedNodeApplied = report . AppliedPlayerSettings = = 1 & &
report . AppliedRunCheckpoints = = 1 & &
settings ? . PlayerName = = "Unity smoke" & &
settings . Input . ActionBarInputs . Length = = 1 & &
run ? . ZoneKeys . Length = = 1 & &
2026-06-14 11:53:55 +01:00
run . ActionBarBindings . Length = = 2 & &
run . ActionBarBindings [ 0 ] . ControlPath = = "<Keyboard>/1" & &
run . ActionBarBindings [ 0 ] . Kind = = "weapon_group" & &
run . ActionBarBindings [ 0 ] . WeaponGroup = = 0 & &
run . ActionBarBindings [ 1 ] . ControlPath = = "<Keyboard>/2" & &
run . ActionBarBindings [ 1 ] . Kind = = "gear" & &
run . ActionBarBindings [ 1 ] . TargetKey = = "aetheria.item_definition:legacy:smoke:weapon" & &
run . ActionBarBindings [ 1 ] . EquipmentIndex = = 0 & &
run . ActionBarBindings [ 1 ] . BehaviorIndex = = 1 & &
2026-06-14 12:02:47 +01:00
run . FactionRelationships . Length = = 1 & &
run . FactionRelationships [ 0 ] . FactionKey = = "aetheria.corporation:legacy:smoke:faction" & &
run . FactionRelationships [ 0 ] . Relationship = = "Friendly" & &
run . FactionRelationships [ 0 ] . Standing = = 3 & &
2026-06-13 22:26:43 +01:00
zone ? . EntityKeys . Length = = 1 & &
entity ? . Equipment . Length = = 1 & &
entity . WeaponGroups . Length = = 1 & &
AetheriaRuntimeStateCommitLog . ReadPending ( commitSmokeStatePath ) . Count = = 0 ;
}
var packageSettings = AetheriaRuntimeCatalogStore . ReadPlayerSettings ( commitSmokeStatePath ) ;
if ( ! typedNodeApplied | |
packageSettings ? . PlayerName ! = "Unity smoke" | |
packageSettings . TutorialPassed ! = true | |
packageSettings . ActionBarInputs . Count ! = 1 )
2026-06-13 15:27:12 +01:00
{
2026-06-13 22:26:43 +01:00
throw new InvalidOperationException (
"Runtime state commit log did not apply queued settings/run snapshots through the typed state node. " +
$"typedNodeApplied={typedNodeApplied}, packageSettings={(packageSettings == null ? " null " : $" { packageSettings . PlayerName } / { packageSettings . TutorialPassed } / { packageSettings . ActionBarInputs . Count } ")}" ) ;
2026-06-13 15:27:12 +01:00
}
2026-06-13 16:44:24 +01:00
var eveCommand = AetheriaRuntimeEveCommandLog . QueueCommand (
commitSmokeStatePath ,
new EveSurfaceCommandRequest (
"aetheria" ,
"aetheria.catalog.operator" ,
"aetheria.catalog.refresh" ,
new Dictionary < string , string > { [ "source" ] = "unity-smoke" } ,
DateTimeOffset . UtcNow ,
"aetheria-state-unity-smoke" ) ) ;
var evePending = AetheriaRuntimeEveCommandLog . ReadPending ( commitSmokeStatePath ) ;
if ( evePending . Count ! = 1 | |
evePending [ 0 ] . Schema ! = AetheriaRuntimeEveCommandLog . CommandSchema | |
evePending [ 0 ] . CommandId ! = eveCommand . CommandId | |
evePending [ 0 ] . ProviderId ! = "aetheria" | |
evePending [ 0 ] . SurfaceId ! = "aetheria.catalog.operator" | |
evePending [ 0 ] . Command ! = "aetheria.catalog.refresh" | |
evePending [ 0 ] . Payload [ "source" ] ! = "unity-smoke" | |
AetheriaRuntimeStateCommitLog . ReadPending ( commitSmokeStatePath ) . Count ! = 0 )
{
throw new InvalidOperationException ( "Runtime Eve command log did not preserve typed command envelopes separately from state commits." ) ;
}
2026-06-13 15:27:12 +01:00
}
finally
{
2026-06-13 22:26:43 +01:00
if ( Environment . GetEnvironmentVariable ( "AETHERIA_KEEP_SMOKE_STATE" ) = = "1" )
Console . Error . WriteLine ( $"Kept smoke state: {commitSmokeDirectory}" ) ;
else
Directory . Delete ( commitSmokeDirectory , true ) ;
2026-06-13 15:27:12 +01:00
}
2026-06-13 09:15:59 +01:00
Console . WriteLine ( $"Aetheria Unity runtime catalog smoke passed: {statePath}" ) ;
Console . WriteLine ( $"Items/trade/equipment: {catalog.Items.Count}/{catalog.TradeItems.Count}/{catalog.EquipmentItems.Count}" ) ;
2026-06-13 09:32:24 +01:00
Console . WriteLine ( $"Shape mask sample: {shaped.Name} {shaped.ShapeWidth}x{shaped.ShapeHeight}/{shaped.ShapeCells.Count}" ) ;
2026-06-13 09:47:25 +01:00
Console . WriteLine ( $"Interior/hardpoint sample: {interior.Name} {interior.InteriorShapeCells.Count}; {hardpointHost.Name} {hardpoint.Type} {hardpoint.ShapeCells.Count}" ) ;
2026-06-13 10:01:20 +01:00
Console . WriteLine ( $"Behavior payload sample: {behaviorHost.Name} {behaviorPayload.Kind}/{behaviorPayload.Fields.Count}" ) ;
2026-06-13 09:15:59 +01:00
Console . WriteLine ( $"Behavior sample: {behaviorKind}" ) ;
Console . WriteLine ( $"Eve surface: {surface.Surface.Id}" ) ;
2026-06-13 16:15:03 +01:00
Console . WriteLine ( $"Package Eve surfaces: {packageSurfaces.Count}" ) ;
2026-06-14 12:02:47 +01:00
Console . WriteLine ( "Runtime state commit log smoke: settings, action-bar bindings, faction relationships, and run zone/entity snapshots queued, applied, and cleared" ) ;
2026-06-13 16:44:24 +01:00
Console . WriteLine ( "Runtime Eve command log smoke: surface command queued separately from state commits" ) ;