From a29794232d4c6d38d824b7fa67f380bf7e1ec73e Mon Sep 17 00:00:00 2001 From: Meta Vens Date: Tue, 16 Jun 2026 10:20:36 +0100 Subject: [PATCH] Use typed faction keys for galaxy allegiance --- .voidbot/state/aetheria.cc | Bin 157756 -> 160658 bytes Aetheria.State.Verify/Program.cs | 37 +++++++++++++++++++ Aetheria.State/README.md | 3 ++ Assets/Scripts/ServerShared/Corporations.cs | 2 -- Assets/Scripts/ServerShared/Galaxy.cs | 38 ++++---------------- docs/aetheria-perfect-machine-map.md | 14 ++++++-- 6 files changed, 58 insertions(+), 36 deletions(-) diff --git a/.voidbot/state/aetheria.cc b/.voidbot/state/aetheria.cc index 6a64baad98ccdddd62d6e4d99e2975af6bdf5a5f..28f846bf5c1432a8557ad79d04cf1e81b3b6f2f6 100644 GIT binary patch delta 3042 zcmb7`-)|IE6vv&RsWd2{P>9x)8#IK%?)C@i4~l5|!&dx}!b(+YDcqg8yL;`-++pra z+tHGZsnHi6#Az~#gizzp01qTS>Vy6R#&hq??#==Unl#PM zk9+5w@A;n3xtG6bdiS@cOCPHD?d|XE?eFf&^mg@5oK~8{W0PuQa9v%fJ=oJN9t3R7 zT;g7zytlSto2rd3v^A958k8s3mc~Z0f#-ab$C^u-g&bmF@q-tsjW{*E=n`2B8O$mW z2Wi-GDB);y{J=26hCvDxTN**!#V*Nwq#2l+KPbZk#4QqsVx$v;xI{-I(HAlU)g>u3 z`iT5`W{6oXrWTLi**WS_y)6|UUs1M{;tPZ=9l@4ph&eWMWRTC10@nNkdVSOm!8*!2 z%tTRcnS%~{m1u6fInTuR+YN?w=DBywokPa6$m67x{NS_1Z;!WupOCUctpbOz9Oe~@ zsFvEG56@Guv_7wBL0d{DlO>!PGbG+muE>1i5{rZUtA8AZR9#});mr-ogC$-hh5_HB z@Sn_4?sAkP8ix2#&Ve+NrP7#A5ano^_#k`EuPBdLPRPLJ$DwQ>9Xc?~<6U!Dn?~e> zhYjlb?M2Lsi0Z_0;c6c`$SlK87F!gf&MMe*i_C$Sk;!J@vw6>e6)r=rZ^I?T!V$GV zDG1EQJX~H3 z^r!`O6Strr{LFdi2M{Am^8CkpX3Omxm50_GI+O)*sY4D6JtAYqfn^gd$5FwO0+d7n=T7w&B9u42=Q#Qli>t7zNXegRunh=}c>UAlSXeJzmTx$hXt)ic~NM?lA z8i}-dCRo0=qr87i8Be8qUj$m@DF6oS!9i20dg0D=3cr3`ITc=+P%i}ktTcvi52};l z@n4h&!ed9&?(mC6WplXmq_Sfjpt7gGvoF)p*;_txQt4_`TFR#u6k}z_sZUK}G6&$X zx(COoN=IKyLlI-Bh1sl%589Emci{yF4@zOvVD>bdwTQm&w(?0xhD|T1ZKbC~hZ_{E z7+0=h?7F_PF?g>AU%@t>BvKWD;A`1L5tu~`pkZ9L1asjffoU|*Tul~OS_onItHYz5UryvNF=zmSX+b~OBH~{OC?){MnF$q&Kncz?KzZ(IMX}>3fnGPs z2sKFiAmjXLz+DO!NZ?2!gOMu%Mc@JO3D)_q|v=8J5w!4-=>27>mq7S!@6Tall6cb{aG7Xx>T}-hypv%>YcX1#JrX!JtN1(APGw zCbmt|G8z`q3@8b%SMeFuI>&UsojExQ8+gDzkV>8iV8nTv05V4~q~QnvyJB&!NMl_W z9}yA4^v+Q+XlihPBSjLNiwhq(B)__Q09fD#t7o=WVU*gPh0YZ-Ce}CUZW%%XIN{ar zl&)ac+57kJkGrha+zH=DBT)_%1XIE$4wwdNRM9Yaf9bK{#^Mfj?D_DGn@V#Z5LL9I z57}7UGa=a;@Z=922pzV_hc_wr7!c{obGH<;QxDD*Pyf&{5`N`*WMAP0ZpLu2zH>+^2~$m1^omj3(#=j zR38n>F#wZrp6>TLM=Ys$vP&&DnAS@74&=J4kU^_<$-5&rq5f*N`b z!>^5BDJ`2WMAVjG{5To`;q_P4v4+l${*JJ9Qbn~>bWd01$bBVovnM`oH-C;kPBja_a4 delta 1029 zcmZ8g%TE(Q7ge%uZW2Q90;A z6Fo?y6Fta9V`4Pw!StZUlQ#}xVgkfR;)SdJ0Y+!Lv?bnlelz=hzsL72ZPvc~RQu{N ztREWb9~$Wk1$+8JazBMl`H%3{HgLcPS=B-X?C_BI+QU<&bdGMDLy_Za2%>L_dS%-56|L%f&TNBk#xIfj}CIR1nFP7;Fz9W}9x8{1t=4pi6Fag8mw^KpjDC zL#{+%aMs9Rt~&@DnA(m&oFp>T)YWyFsp90IBxe>H_qhkdW5K6_*pAY%{&NDGc)>-g zq-mlwXP1d49Qo)oXqI=Pur0t69wJ{xVP{-1c94}(eRQ8ghB_%^5(8^48jDOJCq+~h zPArzirr#8soM7GU)|izxi6A=S|5>RB=6}?;f=$`81RCXs8Hi*{6t*sw9;#n0s(LEd zveGL98_6n7bwUMWS0my(AegGfFVsMHA8R z7)oRA99J%Osc^lNRLWjl#b};kTT3xMO_I*n9ofR~ec*5vxFC1NVOw{aldKvH)m8<| z6rEzVBsR?i*5-XjI59ZOsp5sXMi4k6H~PTA@$s!3N(uM_g*3)J_MT`JvaKsR$Yi!b z6ltOnnk5bjD~T7djTM+*j&>Bjod(}q8=jM_H=`Qyd4}_=yF!JVQy|(kI6AAGOj1=N zjU7iNf|EiWuwI;-lIx{OSMeZkrn#)U0&c_gpj?fECVBoStjjO2?~yO&;6r)pEvS=! zu7VTZDh+x|H_#g@1h0YK0BA1Y8^BzXlLkB{bC=-W{AyKGU3obNWdntW Allegiance", + ".Allegiance[", + "ContainsFaction(Guid", + "ResolveFaction(Guid", + "CorporationLegacyId", + "factionsByLegacyId", + "_containedFactions" + }; + + var hits = checkedFiles + .Where(File.Exists) + .SelectMany(path => File.ReadLines(path) + .Select((line, index) => new { Path = path, LineNumber = index + 1, Line = line })) + .Where(line => forbiddenSymbols.Any(symbol => line.Line.Contains(symbol, StringComparison.Ordinal))) + .Select(line => $"{Path.GetRelativePath(root, line.Path)}:{line.LineNumber}: {line.Line.Trim()}") + .ToArray(); + + if (hits.Length > 0) + { + throw new InvalidOperationException( + "Galaxy faction relationships must use typed corporation keys, not legacy GUID allegiance state: " + + string.Join("; ", hits)); + } +} + static void RequireEveRuntimeBootstrap(string root) { var bootstrapPath = Path.Combine( diff --git a/Aetheria.State/README.md b/Aetheria.State/README.md index 93f2d7028..c6317494d 100644 --- a/Aetheria.State/README.md +++ b/Aetheria.State/README.md @@ -108,6 +108,9 @@ pending-command `CorporationLegacyId` fallback fields are deleted. `EntityConstructionBlueprint` also carries `FactionKey` only. Loadout restore, entity construction, run entity snapshots, and faction relationship commits no longer rebuild corporation references from legacy `Faction.ID` GUIDs. +Galaxy faction relationship projection is also typed-key-only: the old +`Faction.Allegiance` GUID dictionary, GUID containment helper, and GUID faction +resolver are deleted from the simulation shell. Run checkpoint commit DTOs carry typed `OrbitKey`, `ParentOrbitKey`, and `BodyKey` only for zone orbit/body snapshots. The old pending-command `OrbitLegacyId`, `ParentLegacyId`, and `BodyLegacyId` fallback fields are diff --git a/Assets/Scripts/ServerShared/Corporations.cs b/Assets/Scripts/ServerShared/Corporations.cs index 71c13d3e0..997196abc 100644 --- a/Assets/Scripts/ServerShared/Corporations.cs +++ b/Assets/Scripts/ServerShared/Corporations.cs @@ -40,8 +40,6 @@ public class Faction : INamedEntry [Inspectable] public int InfluenceDistance = 4; - [InspectableRangedFloat(0, 1)] - public Dictionary Allegiance = new Dictionary(); public Dictionary AllegianceByKey = new Dictionary(); [InspectableSoundBank] diff --git a/Assets/Scripts/ServerShared/Galaxy.cs b/Assets/Scripts/ServerShared/Galaxy.cs index 1e6036590..862827f85 100644 --- a/Assets/Scripts/ServerShared/Galaxy.cs +++ b/Assets/Scripts/ServerShared/Galaxy.cs @@ -31,7 +31,6 @@ public class Galaxy private Action Log { get; } public bool IsPrelude { get; } - private HashSet _containedFactions; private HashSet _containedFactionKeys; private GalaxyZone[] _exitPath; private Dictionary _nameGenerators = new Dictionary(); @@ -233,20 +232,17 @@ public class Galaxy throw new InvalidOperationException("Typed catalog has no factions for galaxy generation."); } - var factionsByLegacyId = factions.ToDictionary(faction => faction.ID.ToString("D"), StringComparer.OrdinalIgnoreCase); + var factionKeys = new HashSet( + factions + .Select(faction => faction.FactionKey) + .Where(key => !string.IsNullOrWhiteSpace(key)), + StringComparer.OrdinalIgnoreCase); for (var index = 0; index < corporations.Length; index++) { foreach (var allegiance in corporations[index].Allegiances) { - if (Guid.TryParse(allegiance.CorporationLegacyId, out var corporationId) && - corporationId != Guid.Empty && - factionsByLegacyId.ContainsKey(corporationId.ToString("D"))) - { - factions[index].Allegiance[corporationId] = (float) allegiance.Weight; - } - if (!string.IsNullOrWhiteSpace(allegiance.CorporationKey) && - factionsByLegacyId.ContainsKey(allegiance.CorporationLegacyId)) + factionKeys.Contains(allegiance.CorporationKey)) { factions[index].AllegianceByKey[allegiance.CorporationKey] = (float) allegiance.Weight; } @@ -473,12 +469,6 @@ public class Galaxy } } - public bool ContainsFaction(Guid factionID) - { - _containedFactions ??= new HashSet(Factions.Select(f => f.ID)); - return _containedFactions.Contains(factionID); - } - public bool ContainsFaction(string factionKey) { _containedFactionKeys ??= new HashSet( @@ -489,22 +479,6 @@ public class Galaxy return !string.IsNullOrWhiteSpace(factionKey) && _containedFactionKeys.Contains(factionKey); } - public Faction ResolveFaction(Guid factionID) - { - if (factionID == Guid.Empty) - { - return null; - } - - var faction = Factions.FirstOrDefault(f => f.ID == factionID); - if (faction != null) - { - return faction; - } - - return _allFactions.FirstOrDefault(f => f.ID == factionID); - } - public Faction ResolveFactionByKey(string factionKey) { if (string.IsNullOrWhiteSpace(factionKey)) diff --git a/docs/aetheria-perfect-machine-map.md b/docs/aetheria-perfect-machine-map.md index ed26b833b..0bbe71bbb 100644 --- a/docs/aetheria-perfect-machine-map.md +++ b/docs/aetheria-perfect-machine-map.md @@ -398,8 +398,10 @@ legacy catalog cache, and legacy UI paths should be migration-only or deleted. - `Galaxy` generation no longer accepts a runtime item catalog reader or `ItemManager`. Sector and tutorial generation receive the package-owned typed runtime catalog. `Galaxy` projects typed corporation v2 records into temporary legacy - `Faction` DTOs, including allegiance edges, for the existing simulation shape - and resolves full name arrays from `aetheria.name_file.v2` records. The + `Faction` DTOs for the existing simulation shape, but allegiance edges are + typed-key-only through `AllegianceByKey`; the old GUID allegiance dictionary + and GUID faction lookup helpers are deleted. Galaxy resolves full name arrays + from `aetheria.name_file.v2` records. The runtime no longer opens the old `GameData/NameFile/*.msgpack` directory. - Item instances carry `AetheriaRuntimeItemReference`, a typed item key resolved by `ItemManager` against the typed runtime item catalog projected @@ -1011,6 +1013,10 @@ First Aetheria surfaces to publish: old blueprint `Faction` GUID compatibility field is deleted, and runtime entity/faction-relationship commits no longer rebuild faction keys from legacy `Faction.ID` GUIDs. + - Done: delete `Faction.Allegiance`, `Galaxy.ContainsFaction(Guid)`, and + `Galaxy.ResolveFaction(Guid)`; galaxy/loadout faction relationship logic + now uses `AllegianceByKey`, `ContainsFaction(string)`, and + `ResolveFactionByKey` only. - Done: move package and canonical manufacturer/corporation/name-file lookup to typed keys (`ManufacturerKey`, `CorporationKey`, `GeonameFileKey`, and `NameFileKey`), and move loadout manufacturer-distance weighting to @@ -1735,6 +1741,10 @@ First Aetheria surfaces to publish: - `Aetheria.State.Verify` also guards runtime faction identity ownership: construction blueprints cannot carry a legacy faction GUID, and runtime entity/faction commits cannot rebuild `FactionKey` from `Faction.ID`. +- `Aetheria.State.Verify` guards galaxy faction relationships as typed-key-only: + no `Faction.Allegiance` GUID dictionary, GUID faction containment, GUID + faction resolver, or `CorporationLegacyId` relationship read may return to + the live `Galaxy`/`LoadoutGenerator` path. - Unity batchmode compile returned cleanly after the runtime blueprint rename; live Unity source has no `EntityPack`, `ShipPack`, `OrbitalEntityPack`, `ZonePack`, `PackedContents`, `PackZone`, `EntitySerializer.Pack`, or