diff --git a/Aetheria.State.Freeze/Aetheria.State.Freeze.csproj b/Aetheria.State.Freeze/Aetheria.State.Freeze.csproj index 1e5102696..77ae79ca2 100644 --- a/Aetheria.State.Freeze/Aetheria.State.Freeze.csproj +++ b/Aetheria.State.Freeze/Aetheria.State.Freeze.csproj @@ -9,7 +9,7 @@ - + diff --git a/Aetheria.State.Freeze/Program.cs b/Aetheria.State.Freeze/Program.cs index 249ea460d..be47c0585 100644 --- a/Aetheria.State.Freeze/Program.cs +++ b/Aetheria.State.Freeze/Program.cs @@ -2,11 +2,18 @@ using System.Diagnostics; using System.Text.Json; using System.Text.Json.Serialization; using Aetheria.State; -using GameCult.Geometry; +using CultMath; using GameCult.Aetheria.State.Verse; using MessagePack; +using MessagePack.Formatters; +using MessagePack.Resolvers; +MessagePackSerializer.DefaultOptions = MessagePackSerializerOptions.Standard.WithResolver( + CompositeResolver.Create( + new IMessagePackFormatter[] { new CultMathFloat2Formatter(), new CultMathFloat3Formatter() }, + new IFormatterResolver[] { StandardResolver.Instance })); var options = FreezeOptions.Parse(args); +VerifyCultMathVectorSerializationCompatibility(); Directory.CreateDirectory(options.OutputDirectory); Directory.CreateDirectory(Path.GetDirectoryName(options.StatePath) ?? "."); @@ -841,14 +848,27 @@ static YmirFixtureSphereCastHit[] ToFixtureSphereCastHits(IReadOnlyList +{ + public void Serialize(ref MessagePackWriter writer, float2 value, MessagePackSerializerOptions options) + { + writer.WriteArrayHeader(2); + writer.Write(value.x); + writer.Write(value.y); + } + + public float2 Deserialize(ref MessagePackReader reader, MessagePackSerializerOptions options) + { + var count = reader.ReadArrayHeader(); + if (count != 2) throw new MessagePackSerializationException($"Expected float2 array length 2, got {count}."); + return new float2(reader.ReadSingle(), reader.ReadSingle()); + } +} + +internal sealed class CultMathFloat3Formatter : IMessagePackFormatter +{ + public void Serialize(ref MessagePackWriter writer, float3 value, MessagePackSerializerOptions options) + { + writer.WriteArrayHeader(3); + writer.Write(value.x); + writer.Write(value.y); + writer.Write(value.z); + } + + public float3 Deserialize(ref MessagePackReader reader, MessagePackSerializerOptions options) + { + var count = reader.ReadArrayHeader(); + if (count != 3) throw new MessagePackSerializationException($"Expected float3 array length 3, got {count}."); + return new float3(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle()); + } +} + [MessagePackObject] internal sealed class YmirQueryFixtureSet { @@ -1167,12 +1233,12 @@ internal sealed class YmirQueryFixturePayload [Key(0)] public float? DeltaTime { get; set; } [Key(1)] public float? Radius { get; set; } [Key(2)] public float? Distance { get; set; } - [Key(3)] public CultVec2? Center2 { get; set; } - [Key(4)] public CultVec3? Center3 { get; set; } - [Key(5)] public CultVec2? Origin2 { get; set; } - [Key(6)] public CultVec3? Origin3 { get; set; } - [Key(7)] public CultVec2? Direction2 { get; set; } - [Key(8)] public CultVec3? Direction3 { get; set; } + [Key(3)] public float2? Center2 { get; set; } + [Key(4)] public float3? Center3 { get; set; } + [Key(5)] public float2? Origin2 { get; set; } + [Key(6)] public float3? Origin3 { get; set; } + [Key(7)] public float2? Direction2 { get; set; } + [Key(8)] public float3? Direction3 { get; set; } [Key(9)] public YmirFixtureWorld? World { get; set; } [Key(10)] public YmirFixtureSphereBody[] SphereBodies { get; set; } = Array.Empty(); [Key(11)] public YmirFixtureCircleOverlapHit[] CircleOverlapHits { get; set; } = Array.Empty(); @@ -1194,9 +1260,9 @@ internal sealed class YmirFixtureWorld internal sealed class YmirFixtureBody { [Key(0)] public string Id { get; set; } = ""; - [Key(1)] public CultVec2 Position { get; set; } - [Key(2)] public CultVec2 Velocity { get; set; } - [Key(3)] public CultVec2 Direction { get; set; } + [Key(1)] public float2 Position { get; set; } + [Key(2)] public float2 Velocity { get; set; } + [Key(3)] public float2 Direction { get; set; } [Key(4)] public float AngularVelocity { get; set; } [Key(5)] public float Torque { get; set; } [Key(6)] public float MomentOfInertia { get; set; } @@ -1210,7 +1276,7 @@ internal sealed class YmirFixtureBody internal sealed class YmirFixtureSphereBody { [Key(0)] public string Id { get; set; } = ""; - [Key(1)] public CultVec3 Position { get; set; } + [Key(1)] public float3 Position { get; set; } [Key(2)] public float Radius { get; set; } } @@ -1218,7 +1284,7 @@ internal sealed class YmirFixtureSphereBody internal sealed class YmirFixtureField { [Key(0)] public string Id { get; set; } = ""; - [Key(1)] public CultVec2 Position { get; set; } + [Key(1)] public float2 Position { get; set; } [Key(2)] public float Strength { get; set; } [Key(3)] public float Radius { get; set; } } @@ -1228,8 +1294,8 @@ internal sealed class YmirFixtureContact { [Key(0)] public string BodyA { get; set; } = ""; [Key(1)] public string BodyB { get; set; } = ""; - [Key(2)] public CultVec2 Point { get; set; } - [Key(3)] public CultVec2 Normal { get; set; } + [Key(2)] public float2 Point { get; set; } + [Key(3)] public float2 Normal { get; set; } [Key(4)] public float Penetration { get; set; } [Key(5)] public float RelativeSpeed { get; set; } } @@ -1238,8 +1304,8 @@ internal sealed class YmirFixtureContact internal sealed class YmirFixtureCircleOverlapHit { [Key(0)] public string BodyId { get; set; } = ""; - [Key(1)] public CultVec2 Point { get; set; } - [Key(2)] public CultVec2 Normal { get; set; } + [Key(1)] public float2 Point { get; set; } + [Key(2)] public float2 Normal { get; set; } [Key(3)] public float Penetration { get; set; } [Key(4)] public float Distance { get; set; } } @@ -1248,8 +1314,8 @@ internal sealed class YmirFixtureCircleOverlapHit internal sealed class YmirFixtureSphereOverlapHit { [Key(0)] public string BodyId { get; set; } = ""; - [Key(1)] public CultVec3 Point { get; set; } - [Key(2)] public CultVec3 Normal { get; set; } + [Key(1)] public float3 Point { get; set; } + [Key(2)] public float3 Normal { get; set; } [Key(3)] public float Penetration { get; set; } [Key(4)] public float Distance { get; set; } } @@ -1258,8 +1324,8 @@ internal sealed class YmirFixtureSphereOverlapHit internal sealed class YmirFixtureCircleCastHit { [Key(0)] public string BodyId { get; set; } = ""; - [Key(1)] public CultVec2 Point { get; set; } - [Key(2)] public CultVec2 Normal { get; set; } + [Key(1)] public float2 Point { get; set; } + [Key(2)] public float2 Normal { get; set; } [Key(3)] public float Distance { get; set; } } @@ -1267,8 +1333,8 @@ internal sealed class YmirFixtureCircleCastHit internal sealed class YmirFixtureSphereCastHit { [Key(0)] public string BodyId { get; set; } = ""; - [Key(1)] public CultVec3 Point { get; set; } - [Key(2)] public CultVec3 Normal { get; set; } + [Key(1)] public float3 Point { get; set; } + [Key(2)] public float3 Normal { get; set; } [Key(3)] public float Distance { get; set; } } diff --git a/Aetheria.State/Aetheria.State.csproj b/Aetheria.State/Aetheria.State.csproj index c323cf1fb..4664b628e 100644 --- a/Aetheria.State/Aetheria.State.csproj +++ b/Aetheria.State/Aetheria.State.csproj @@ -19,6 +19,7 @@ + (); QueryGravityInfluences(zone, viewport, brushes); @@ -807,7 +808,7 @@ namespace GameCult.Aetheria.State.Verse public static int QueryGravityInfluences( AetheriaRuntimeZoneSnapshotCommit? zone, - rect viewport, + CultRect viewport, List brushes) { if (brushes == null) throw new ArgumentNullException(nameof(brushes)); @@ -906,7 +907,7 @@ namespace GameCult.Aetheria.State.Verse public static AetheriaRuntimeDaemonBodyView[] QueryBodyViews( AetheriaRuntimeZoneSnapshotCommit? zone, - rect viewport) + CultRect viewport) { var views = new List(); QueryBodyViews(zone, viewport, views); @@ -930,15 +931,15 @@ namespace GameCult.Aetheria.State.Verse public static int QueryBodyViews( AetheriaRuntimeZoneSnapshotCommit? zone, - rect viewport, + CultRect viewport, List views) { - return QueryBodyViews(zone, (rect?)viewport, views); + return QueryBodyViews(zone, (CultRect?)viewport, views); } private static int QueryBodyViews( AetheriaRuntimeZoneSnapshotCommit? zone, - rect? viewport, + CultRect? viewport, List views) { if (views == null) throw new ArgumentNullException(nameof(views)); @@ -1196,7 +1197,7 @@ namespace GameCult.Aetheria.State.Verse AetheriaRuntimeZoneSnapshotCommit? zone, int observerEntityIndex, double minimumInfoGathered, - rect viewport) + CultRect viewport) { var currentEntityIndex = TryParseEntityIndex(run?.CurrentEntityKey); return QueryPresentationEntityIndices( @@ -1223,7 +1224,7 @@ namespace GameCult.Aetheria.State.Verse AetheriaRuntimeZoneSnapshotCommit? zone, int observerEntityIndex, double minimumInfoGathered, - rect viewport, + CultRect viewport, List entityIndices) { var currentEntityIndex = TryParseEntityIndex(run?.CurrentEntityKey); @@ -1251,7 +1252,7 @@ namespace GameCult.Aetheria.State.Verse AetheriaRuntimeZoneSnapshotCommit? zone, int observerEntityIndex, double minimumInfoGathered, - rect viewport) + CultRect viewport) { var entityIndices = new List(); var currentEntityIndex = TryParseEntityIndex(currentEntityKey); @@ -1270,7 +1271,7 @@ namespace GameCult.Aetheria.State.Verse AetheriaRuntimeZoneSnapshotCommit? zone, int observerEntityIndex, double minimumInfoGathered, - rect viewport) + CultRect viewport) { var entityIndices = new List(); QueryPresentationEntityIndices( @@ -1299,7 +1300,7 @@ namespace GameCult.Aetheria.State.Verse AetheriaRuntimeZoneSnapshotCommit? zone, int observerEntityIndex, double minimumInfoGathered, - rect viewport, + CultRect viewport, List entityIndices) { var currentEntityIndex = TryParseEntityIndex(currentEntityKey); @@ -1317,7 +1318,7 @@ namespace GameCult.Aetheria.State.Verse AetheriaRuntimeZoneSnapshotCommit? zone, int observerEntityIndex, double minimumInfoGathered, - rect viewport, + CultRect viewport, List entityIndices) { if (entityIndices == null) throw new ArgumentNullException(nameof(entityIndices)); @@ -1368,7 +1369,7 @@ namespace GameCult.Aetheria.State.Verse AetheriaRuntimeZoneSnapshotCommit? zone, IReadOnlyList? controlledEntityIndices, double minimumInfoGathered, - rect viewport) + CultRect viewport) { var entityIndices = new List(); QueryObjectsViewportEntityIndices(zone, controlledEntityIndices, minimumInfoGathered, viewport, entityIndices); @@ -1379,7 +1380,7 @@ namespace GameCult.Aetheria.State.Verse AetheriaRuntimeZoneSnapshotCommit? zone, IReadOnlyList? controlledEntityIndices, double minimumInfoGathered, - rect viewport, + CultRect viewport, List entityIndices) { if (entityIndices == null) throw new ArgumentNullException(nameof(entityIndices)); @@ -1454,7 +1455,7 @@ namespace GameCult.Aetheria.State.Verse AetheriaRuntimeZoneSnapshotCommit? zone, IReadOnlyList? controlledEntityIndices, double minimumInfoGathered, - rect viewport) + CultRect viewport) { var entities = new List(); QueryObjectsViewport(zone, controlledEntityIndices, minimumInfoGathered, viewport, entities); @@ -1465,7 +1466,7 @@ namespace GameCult.Aetheria.State.Verse AetheriaRuntimeZoneSnapshotCommit? zone, IReadOnlyList? controlledEntityIndices, double minimumInfoGathered, - rect viewport, + CultRect viewport, List entities) { if (entities == null) throw new ArgumentNullException(nameof(entities)); @@ -1761,7 +1762,7 @@ namespace GameCult.Aetheria.State.Verse foreach (var brush in QueryGravityInfluences( zone, - new rect((float)positionX, (float)positionZ, (float)positionX, (float)positionZ))) + new CultRect((float)positionX, (float)positionZ, (float)positionX, (float)positionZ))) { var dx = positionX - brush.CenterX; var dz = positionZ - brush.CenterZ; @@ -1896,7 +1897,7 @@ namespace GameCult.Aetheria.State.Verse return source; } - private static bool IntersectsCircle(rect viewport, double centerX, double centerY, double radius) + private static bool IntersectsCircle(CultRect viewport, double centerX, double centerY, double radius) { if (radius <= 0) return false; @@ -1918,12 +1919,12 @@ namespace GameCult.Aetheria.State.Verse return ContainsPoint(rect.ToAetheriaXyRect(), x, z); } - private static bool ContainsPoint(rect viewport, double x, double y) + private static bool ContainsPoint(CultRect viewport, double x, double y) { return viewport.Contains(new float2((float)x, (float)y)); } - private static rect ToRuntimeRect(AetheriaRuntimeXzRect unityViewport) + private static CultRect ToRuntimeRect(AetheriaRuntimeXzRect unityViewport) { return unityViewport.ToAetheriaXyRect(); } diff --git a/Packages/org.gamecult.aetheria.state/Runtime/GameCult.Aetheria.State.Unity.asmdef b/Packages/org.gamecult.aetheria.state/Runtime/GameCult.Aetheria.State.Unity.asmdef index 5b9752053..4433f1de6 100644 --- a/Packages/org.gamecult.aetheria.state/Runtime/GameCult.Aetheria.State.Unity.asmdef +++ b/Packages/org.gamecult.aetheria.state/Runtime/GameCult.Aetheria.State.Unity.asmdef @@ -5,6 +5,7 @@ "GameCult.Eve.Surface", "GameCult.Eve.PluginFields", "GameCult.Mesh", + "GameCult.Geometry", "CultMath", "MessagePack" ],