From 1fd8a9f2266a464deedd581cf939e3f5502561fe Mon Sep 17 00:00:00 2001 From: Meta Vens Date: Sat, 30 May 2026 00:04:05 +0100 Subject: [PATCH] Verify Rust geometry payload interop --- .../CultGeometryDocuments.cs | 8 +++- .../vg-csg-ragnarok/ragnarok-domain.msgpack | Bin 0 -> 18824 bytes .../ragnarok-first-chunk.msgpack | Bin 0 -> 8186 bytes .../GameCult.Geometry.Tests.csproj | 4 ++ .../GeometryDocumentTests.cs | 43 ++++++++++++++++-- 5 files changed, 50 insertions(+), 5 deletions(-) create mode 100644 tests/GameCult.Geometry.Tests/Fixtures/vg-csg-ragnarok/ragnarok-domain.msgpack create mode 100644 tests/GameCult.Geometry.Tests/Fixtures/vg-csg-ragnarok/ragnarok-first-chunk.msgpack diff --git a/src/GameCult.Geometry/CultGeometryDocuments.cs b/src/GameCult.Geometry/CultGeometryDocuments.cs index 7a1677b3..306b5849 100644 --- a/src/GameCult.Geometry/CultGeometryDocuments.cs +++ b/src/GameCult.Geometry/CultGeometryDocuments.cs @@ -411,7 +411,13 @@ namespace GameCult.Geometry public static string StableVector(float[] values) { - return string.Join(",", values.Select(value => value.ToString("R", CultureInfo.InvariantCulture))); + return string.Join(",", values.Select(StableFloat)); + } + + public static string StableFloat(float value) + { + return BitConverter.ToUInt32(BitConverter.GetBytes(value), 0) + .ToString("x8", CultureInfo.InvariantCulture); } public static string StableArray(string[] values) diff --git a/tests/GameCult.Geometry.Tests/Fixtures/vg-csg-ragnarok/ragnarok-domain.msgpack b/tests/GameCult.Geometry.Tests/Fixtures/vg-csg-ragnarok/ragnarok-domain.msgpack new file mode 100644 index 0000000000000000000000000000000000000000..79c5f5b6cccb6a45a81747fe634becbfb9fd4b81 GIT binary patch literal 18824 zcmeHNO>7%Q6yAg%p*B4r+Hm6xh^^eDMJk2(rxy;D8WO~zNFc{v$Dw97THA$k%7v=O z78m05R0I?VEdfe7Alft%hjvM$3b=4U>IsPhP^l7U-rKcj_Gi{RGoD=ps#R^hQD(k* z^S*iCzHjsHnq8hZ%eHk?uUL)t>t^`={IPkx(wtuo|NO%l%W8ET4L{LTc_S^FD_bkOK;X;UakrJ zzf{_*X&t9{3Rdr4O4l^)!mKytEY7&?%NfJ08g|jF!WtV3@U?rn2VJpjL$5Rph{miK z{%LVLn494LB@erB8?fC=>AI$^9qdo{67Gnht(7bbeql{VOYR*Ggj~QJls?Q&+sf8%5rlYHs%?<@FJXos%FfPQ+PX6xX-sJ3jCY}}wxqiZh{AJ~=ldsik zPX5y5-ar95!U*(pC_rv0(id&(&Es5Y>9`s9HhAjN4}pya?x3pfWL@?g6J55lKZ#e*Eja{c8YGak@b2@m1~TpbT6DB*#$fOBjt@?cDY z2UK4&t_Ku2GagV#!h<*gSH}YiN_fC6;H$RPHml`1tKC|iAz#DIy3)ETR_;~YV#buF~-{KkHg!Z2-$n$!9DvMj5x%ME=I>7atq-oE zQ?M=Q6cm$30mp9pDGXH^pDkkL@`>oeS!S{rutKLmFytQDhPC>W!^O^^8te?XmP+k! zEH#iV_wjEDQj{-5t^OC(WrqTLHDE}qKY54zt_bN2;+z6Lt6vP1bOzE+0Y^rW2ZjU> z!lyJd9#G)Sct9Zu58|8xbv&S;ga^`20VfY?5p0R<&I z;C2cIS^Z}pIq7UX@aGQ^0SE2A;#{3>{)Ga*Jt*KC$)nN{a6w>&0xpQGM!-2hv2dHg z1IsbWFKX%ztRS$811ktg4s4u&^I3a5^rsIhW{2@m1~TpbT6DB%IOfDdW)kHFtr`poup zt^Vg2yIdI~-%-YM(#il-oY>-<&4YTpN)!I{bNFjS%MRTF9|YE3=1~p#IPWTN{p!0ze6Z7ECU?QW8%xP z;YyiH-}TTNhLjV-ic~H!A*+8P-s*oZSlMu6z1Q+!^^Yc5{c(dut^V<->I}B}cc0(k z6c0T0YQ!m+LjOMxrY1TCJA+O^F?p1zQ}AST;Vi3P3|OI4AQ-Y5r+@<#JH+e3&VXZ- zs8cYbE<3b?R?!&<#!5PaIH!Qm+T&p%jgxc+(oO+Kl*oe{5Grw{vxK`~(X4uAqQ#B#%l*zy*O73b-J$8Ug13#lrn#@W676N=Lv2fmIw> zK}d37;{=?~+T)?WN&)AH5_#~G1P`dbs4LtY%k`Is%y>X!B|L}|aCJPOprmk13pmHd zA`gC+-~rW_jCnwTGvfh;Bs_={aCJPOpo9n90zRbGKboc0KgHp%C-%RX%RS@%+nw`1NB#ls C7tehF literal 0 HcmV?d00001 diff --git a/tests/GameCult.Geometry.Tests/Fixtures/vg-csg-ragnarok/ragnarok-first-chunk.msgpack b/tests/GameCult.Geometry.Tests/Fixtures/vg-csg-ragnarok/ragnarok-first-chunk.msgpack new file mode 100644 index 0000000000000000000000000000000000000000..4cfcf493aea56a4d6329be620d1714b149a68617 GIT binary patch literal 8186 zcmeHLM|0Ca6jlhm_udH|VL5UQ;5gLKLx<3^YKe(rXB3-(TTXC=fgIq#5qdF7gDuJK=8aMy@(KB%$*1?}d*6H7**xv1nq&5r^8FFBR8*s>v~63hu>^|8 z(yggf#6!J#ZCQt(saX$$1G$yiFDFP8F52T zCT%l?Vn{cPsHVq~x@kpY-~9Z(t9GCdAFHDa9j96uQxuH9=z29vaQ2L@zpY&ku%h?1 zhXJZZOc&(_BD85kE;4Gk&4D$4T)eOF+{Q1?wXt^Iv}=!pPcc*)94vT6)yo;Rp5W#2 zI&^auE@IFtym&cMSAJDHEJdk~D)>^yR|c~Je#ZAC2*@BxAQq9OD9qq%wSz|m%n~w# zTzSfQXB1R^zq`bUdUowbtD5S94DVhTk@otD`B^#W~qP(#JQZj%U zoLzbg(?=PZYzO7v45hhTfSoDs?}@Ou3Nuh zY*?-{Rp~FXx9#fA;v}mgyizkw)blZuOr!wu?j?-t(o;!b` zu59j-e%;bK8H}?&GbkNN#Z(O@RKKVoXT;|UpNz$@OQXJIpV=2k(Y%#0vg&vV zKuSPBo<6Tc<~CR&4n+xmWDpfL=+RC_*JI2xJ=tN9C`*u3B#}XsKq<<}?c}70esR&L zfK-`5A2NsnNTq~HKM0fo8AJu7i9k14l-KJ^22l=$lw=arOCZfFlmQt;DFhV>2%^%n z;2m+3qQFt|wg@EuR`6yOe#;F{^ni9_=70NA*JewuOwJJ?oUMbuuZ=!IF9F&GQVnqr zas&uNyYlxzxHjZ&glmI!WAYJUL%QAZO9 z@|COCu6NzIdF%F_yZ7!t=zjR<@sp=L$S^J2>Fvus>#r*<(veG-bmY=adOq=MR_6U& NliPj?y?*uM`ya$EiiH3G literal 0 HcmV?d00001 diff --git a/tests/GameCult.Geometry.Tests/GameCult.Geometry.Tests.csproj b/tests/GameCult.Geometry.Tests/GameCult.Geometry.Tests.csproj index fe7fd8c1..407f5305 100644 --- a/tests/GameCult.Geometry.Tests/GameCult.Geometry.Tests.csproj +++ b/tests/GameCult.Geometry.Tests/GameCult.Geometry.Tests.csproj @@ -12,6 +12,10 @@ + + + + diff --git a/tests/GameCult.Geometry.Tests/GeometryDocumentTests.cs b/tests/GameCult.Geometry.Tests/GeometryDocumentTests.cs index e3938284..1723b852 100644 --- a/tests/GameCult.Geometry.Tests/GeometryDocumentTests.cs +++ b/tests/GameCult.Geometry.Tests/GeometryDocumentTests.cs @@ -82,15 +82,41 @@ namespace GameCult.Geometry.Tests claim.StableFingerprint().Should().Be(string.Join('\u001e', "column-support-shell", - "0,0,0", - "0,0,0,1", - "0,0,45", - "18,18,96", + "00000000,00000000,00000000", + "00000000,00000000,00000000,3f800000", + "00000000,00000000,42340000", + "41900000,41900000,42c00000", "SupportShell", "10", "RenderAndCollider")); } + [Test] + public void RustExportedDomainDocument_DecodesWithStableCultCacheKey() + { + var payload = File.ReadAllBytes(FixturePath("ragnarok-domain.msgpack")); + var domain = CultDocumentMessagePackSerialization.Deserialize(payload); + + domain.DomainId.Should().Be("ragnarok-column"); + domain.Root.Children.Should().NotBeEmpty(); + domain.Root.Children[0].Name.Should().Be("stellarator-column-00"); + CultGeometryDomainDocument.CreateRecordKey(domain).Value + .Should().Be("geometry:domain:02c9b5810977406b0c206f3a3494327a423abb9448192be1b9a1863cd0f2ed95"); + } + + [Test] + public void RustExportedChunkArtifact_DecodesWithStableCultCacheKey() + { + var payload = File.ReadAllBytes(FixturePath("ragnarok-first-chunk.msgpack")); + var chunk = CultDocumentMessagePackSerialization.Deserialize(payload); + + chunk.ChunkId.Should().StartWith("chunk/"); + chunk.RenderMesh.TriangleCount.Should().BeGreaterThan(0); + chunk.SourceDomainKeys.Should().NotBeEmpty(); + CultGeometryChunkArtifact.CreateRecordKey(chunk).Value + .Should().Be("geometry:chunk:b94dcd7d6776df15d0fa5fcf7f4b24f1384876b13b2d38cc57c4468136521af5"); + } + [Test] public async Task ChunkArtifact_Replicates_ThroughCultNetRawDocumentLane() { @@ -273,6 +299,15 @@ namespace GameCult.Geometry.Tests }; } + private static string FixturePath(string fileName) + { + return Path.Combine( + TestContext.CurrentContext.TestDirectory, + "Fixtures", + "vg-csg-ragnarok", + fileName); + } + private static CultGeometryChunkArtifact SampleChunk() { return new CultGeometryChunkArtifact