Persist thruster state in typed snapshots

This commit is contained in:
Meta Vens 2026-06-14 16:13:32 +01:00
commit 21d5cbdf79
10 changed files with 86 additions and 8 deletions

Binary file not shown.

View file

@ -294,6 +294,16 @@ await using (var node = await AetheriaStateNode.OpenAsync(statePath, "aetheria-s
MiningToolAsteroidBeltId = "smoke:body",
MiningToolAsteroidIndex = 3,
MiningToolRange = 275.0
},
new AetheriaBehaviorStateSnapshot
{
OwnerKind = "equipment",
OwnerIndex = 0,
BehaviorIndex = 3,
BehaviorKind = "Thruster",
ThrusterAxis = 0.8,
ThrusterThrust = 125.0,
ThrusterTorque = -0.4
}
],
StatGrids =
@ -557,7 +567,7 @@ await using (var reopened = await AetheriaStateNode.OpenAsync(statePath, "aether
entitySnapshot.WeaponStates[0].BehaviorKind != "LockWeapon" ||
entitySnapshot.WeaponStates[0].LockProgress != 0.65 ||
entitySnapshot.WeaponStates[0].LockTargetEntityKey != entityKey.ToString() ||
entitySnapshot.BehaviorStates.Length != 3 ||
entitySnapshot.BehaviorStates.Length != 4 ||
entitySnapshot.BehaviorStates[0].BehaviorKind != "AetherDrive" ||
entitySnapshot.BehaviorStates[0].AetherDriveAxisX != 0.5 ||
entitySnapshot.BehaviorStates[0].AetherDriveRpmY != 900.0 ||
@ -571,6 +581,10 @@ await using (var reopened = await AetheriaStateNode.OpenAsync(statePath, "aether
entitySnapshot.BehaviorStates[2].MiningToolAsteroidBeltId != "smoke:body" ||
entitySnapshot.BehaviorStates[2].MiningToolAsteroidIndex != 3 ||
entitySnapshot.BehaviorStates[2].MiningToolRange != 275.0 ||
entitySnapshot.BehaviorStates[3].BehaviorKind != "Thruster" ||
entitySnapshot.BehaviorStates[3].ThrusterAxis != 0.8 ||
entitySnapshot.BehaviorStates[3].ThrusterThrust != 125.0 ||
entitySnapshot.BehaviorStates[3].ThrusterTorque != -0.4 ||
entitySnapshot.StatGrids.Length != 1 ||
entitySnapshot.StatGrids[0].Values.Length != 4)
{

View file

@ -523,6 +523,16 @@ try
MiningToolAsteroidBeltId = "smoke:body",
MiningToolAsteroidIndex = 3,
MiningToolRange = 275.0
},
new AetheriaRuntimeBehaviorStateCommit
{
OwnerKind = "equipment",
OwnerIndex = 7,
BehaviorIndex = 0,
BehaviorKind = "Thruster",
ThrusterAxis = 0.8,
ThrusterThrust = 125.0,
ThrusterTorque = -0.4
}
},
StatGrids = new[]
@ -643,7 +653,7 @@ try
entity.WeaponStates[3].BehaviorKind == "LockWeapon" &&
entity.WeaponStates[3].LockProgress == 0.65 &&
entity.WeaponStates[3].LockTargetEntityKey == "global:aetheria.run_state.smoke-run.zone.0.entity.0.v1" &&
entity.BehaviorStates.Length == 7 &&
entity.BehaviorStates.Length == 8 &&
entity.BehaviorStates[0].BehaviorKind == "Sensor" &&
entity.BehaviorStates[0].Pinging &&
entity.BehaviorStates[0].PingRadius == 1200.0 &&
@ -669,6 +679,10 @@ try
entity.BehaviorStates[6].MiningToolAsteroidBeltId == "smoke:body" &&
entity.BehaviorStates[6].MiningToolAsteroidIndex == 3 &&
entity.BehaviorStates[6].MiningToolRange == 275.0 &&
entity.BehaviorStates[7].BehaviorKind == "Thruster" &&
entity.BehaviorStates[7].ThrusterAxis == 0.8 &&
entity.BehaviorStates[7].ThrusterThrust == 125.0 &&
entity.BehaviorStates[7].ThrusterTorque == -0.4 &&
entity.WeaponGroups.Length == 1 &&
entity.StatGrids.Length == 2 &&
entity.StatGrids.Any(grid => grid.Name == "temperature" && grid.Values.Length == 2 && grid.Values[1] == 281.0) &&
@ -724,7 +738,7 @@ try
packageEntities[0].WeaponStates[2].AmmoIntervalProgress != 0.6 ||
packageEntities[0].WeaponStates[3].LockProgress != 0.65 ||
packageEntities[0].WeaponStates[3].LockTargetEntityKey != "global:aetheria.run_state.smoke-run.zone.0.entity.0.v1" ||
packageEntities[0].BehaviorStates.Count != 7 ||
packageEntities[0].BehaviorStates.Count != 8 ||
packageEntities[0].BehaviorStates[3].CapacitorCharge != 7.5 ||
packageEntities[0].BehaviorStates[4].AetherDriveRpmY != 900.0 ||
packageEntities[0].BehaviorStates[4].AetherDriveMaximumRpm != 2400.0 ||
@ -732,6 +746,8 @@ try
packageEntities[0].BehaviorStates[5].ResourceScannerScanDuration != 3.5 ||
packageEntities[0].BehaviorStates[6].MiningToolAsteroidBeltId != "smoke:body" ||
packageEntities[0].BehaviorStates[6].MiningToolRange != 275.0 ||
packageEntities[0].BehaviorStates[7].ThrusterAxis != 0.8 ||
packageEntities[0].BehaviorStates[7].ThrusterThrust != 125.0 ||
packageEntities[0].StatGrids.Count != 2 ||
packageEntities[0].StatGrids.All(grid => grid.Name != "temperature" || grid.Values.Count != 2 || grid.Values[1] != 281.0))
{

View file

@ -507,7 +507,10 @@ public static class AetheriaRuntimeCommitLogApplier
ResourceScannerScanDuration = state.ResourceScannerScanDuration,
MiningToolAsteroidBeltId = state.MiningToolAsteroidBeltId ?? "",
MiningToolAsteroidIndex = state.MiningToolAsteroidIndex,
MiningToolRange = state.MiningToolRange
MiningToolRange = state.MiningToolRange,
ThrusterAxis = state.ThrusterAxis,
ThrusterThrust = state.ThrusterThrust,
ThrusterTorque = state.ThrusterTorque
})
.ToArray();
}

View file

@ -766,6 +766,15 @@ public sealed class AetheriaBehaviorStateSnapshot
[Key(39)]
public double MiningToolRange { get; set; }
[Key(40)]
public double ThrusterAxis { get; set; }
[Key(41)]
public double ThrusterThrust { get; set; }
[Key(42)]
public double ThrusterTorque { get; set; }
}
[MessagePackObject]

View file

@ -927,6 +927,15 @@ public class ActionGameManager : MonoBehaviour
MiningToolRange = miningTool.Range
};
}
else if (behavior is Thruster thruster)
{
state = new AetheriaRuntimeBehaviorStateCommit
{
ThrusterAxis = thruster.Axis,
ThrusterThrust = thruster.Thrust,
ThrusterTorque = thruster.Torque
};
}
if (state == null)
continue;

View file

@ -1107,7 +1107,10 @@ namespace GameCult.Aetheria.State.Unity
double resourceScannerScanDuration,
string miningToolAsteroidBeltId,
int miningToolAsteroidIndex,
double miningToolRange)
double miningToolRange,
double thrusterAxis,
double thrusterThrust,
double thrusterTorque)
{
OwnerKind = ownerKind;
OwnerIndex = ownerIndex;
@ -1149,6 +1152,9 @@ namespace GameCult.Aetheria.State.Unity
MiningToolAsteroidBeltId = miningToolAsteroidBeltId;
MiningToolAsteroidIndex = miningToolAsteroidIndex;
MiningToolRange = miningToolRange;
ThrusterAxis = thrusterAxis;
ThrusterThrust = thrusterThrust;
ThrusterTorque = thrusterTorque;
}
public string OwnerKind { get; }
@ -1191,5 +1197,8 @@ namespace GameCult.Aetheria.State.Unity
public string MiningToolAsteroidBeltId { get; }
public int MiningToolAsteroidIndex { get; }
public double MiningToolRange { get; }
public double ThrusterAxis { get; }
public double ThrusterThrust { get; }
public double ThrusterTorque { get; }
}
}

View file

@ -897,7 +897,10 @@ namespace GameCult.Aetheria.State.Unity
var miningToolAsteroidBeltId = ReadFieldString(ref reader, behaviorFields, 37);
var miningToolAsteroidIndex = ReadFieldInt32(ref reader, behaviorFields, 38);
var miningToolRange = ReadFieldDouble(ref reader, behaviorFields, 39);
SkipRemaining(ref reader, behaviorFields, 40);
var thrusterAxis = ReadFieldDouble(ref reader, behaviorFields, 40);
var thrusterThrust = ReadFieldDouble(ref reader, behaviorFields, 41);
var thrusterTorque = ReadFieldDouble(ref reader, behaviorFields, 42);
SkipRemaining(ref reader, behaviorFields, 43);
behaviorStates[behavior] = new AetheriaRuntimeBehaviorStateSnapshot(
ownerKind,
ownerIndex,
@ -938,7 +941,10 @@ namespace GameCult.Aetheria.State.Unity
resourceScannerScanDuration,
miningToolAsteroidBeltId,
miningToolAsteroidIndex,
miningToolRange);
miningToolRange,
thrusterAxis,
thrusterThrust,
thrusterTorque);
}
return behaviorStates;

View file

@ -815,5 +815,14 @@ namespace GameCult.Aetheria.State.Unity
[Key(39)]
public double MiningToolRange { get; set; }
[Key(40)]
public double ThrusterAxis { get; set; }
[Key(41)]
public double ThrusterThrust { get; set; }
[Key(42)]
public double ThrusterTorque { get; set; }
}
}

View file

@ -174,7 +174,8 @@ legacy catalog cache, and legacy UI paths should be migration-only or deleted.
state is no longer trapped inside live behavior memory. Resource scanners
publish target body id, asteroid index, scan timer, range, minimum density,
and scan duration rows. Mining tools publish asteroid belt id, asteroid
index, and evaluated range rows.
index, and evaluated range rows. Thrusters publish analog axis input,
evaluated thrust, and torque rows.
`RuntimeEntityBlueprint` still exists for construction/loadout projection,
but those live hull grids and session scalars are not blueprint fields and
cannot be restored by the old blueprint projector path.
@ -815,6 +816,8 @@ First Aetheria surfaces to publish:
- Done: extend behavior state rows for MiningTool asteroid belt id,
asteroid index, and range, so active mining target state is typed
snapshot/readback state.
- Done: extend behavior state rows for Thruster axis, thrust, and torque,
so analog propulsion state is typed snapshot/readback state.
- Done: cut live simulation grids out of `RuntimeEntityBlueprint`; loadout
and construction templates no longer capture or restore temperature,
armor, max-armor, or hull-conductivity state.