From c43d7b8f67284aa1156130dfab75d67aed2fa3b0 Mon Sep 17 00:00:00 2001 From: Meta Vens Date: Sat, 13 Jun 2026 13:24:36 +0100 Subject: [PATCH] Resolve runtime factions through typed galaxy projection --- .voidbot/state/aetheria.cc | Bin 30029 -> 30260 bytes .../Scripts/ServerShared/EntitySerializer.cs | 2 +- Assets/Scripts/ServerShared/Galaxy.cs | 16 ++++++++++++ .../Scripts/ServerShared/LoadoutGenerator.cs | 15 +++++++++++- docs/aetheria-perfect-machine-map.md | 23 ++++++++++++------ 5 files changed, 47 insertions(+), 9 deletions(-) diff --git a/.voidbot/state/aetheria.cc b/.voidbot/state/aetheria.cc index 5ff6f3078bd94f98b17c8fd7481f59a1776b3b62..eb32b008672b84688348c3cd54b9e3a5fc5557ce 100644 GIT binary patch delta 1324 zcmZux&1=*^6n9&Zwt^QGTNHgD)~_~byY-{gqG-E*BXvDk6`3Y)lWDUv>&&Eeds$Tc z17!XLQNfe2-bFl$;GvhQ7d?vqfCs@hNjA3XB_uC1Z+>5IK722|{!x1MysK|yWPI$X zR~|hw`=qqpHuxs{zUy&OJ)Tx&_j0FF&erv8++F(F-oG*0)2hrQ!tgpmjroR40kM<| zNkfB>^eRGBkZ6Pp2J2UtVD3A{koisUnPIUEK_LsY_sowOuYW3Cnxb~5c^wsJF<++T z3bm2+fb7pT<}Y~D`C+CNDVc;3%u0b?g~jZC)0;sp<3-HZ3;`1XT$U`5iK(DK#i$+B znMfSuM4=iExHe4q2usMr$Z!!l&>H^R5V+8WFoUeY1 zUcRi8V!^uYQ}+_yXt22$ox6WE>Mi`XU+Y_2pGrMf@xB2+F`y%v!~qzlLNs8S4GdBa z!-1?bEoAaX?N;$TUe%{;@LU?-M#sA|Mpoz(`UA-3j*fnXN6-)+ge$gn?j6 z$)z=iLqo}VlG8=lM9k1PYE+Aqf*LnzB<3(;i=4VF5gH0ps-nwE9_T`aPO>qx*Lz9X zie!(P!J7WE;dJ}m;7YemrngU&vq%@SlSkb}-X&Of3|$xRM^6>jR`*-BZC88q;g7rQ z?L&KQ*NJ}D@!};KvLe^;pIjHMUHBc@NYd~w)A;;3Esecht=ybEbuCkc#-%~1e5nGr z4C&oj<;XkrJI>`oxOAb?p8a*O+E z^x(-;nY$-{peH4I6!9b?f(I{(7q8-_XD@y;Nz;J0?EJj<=Dqjj&7ahl->FwGy81Fx za}%@POeSOUJHzI4*W>oeG_ItL=-xY7$=Wk%)7x`7)!!KH39szWt=B6wAij_lAwe_2 ziPE4c;i5)-kdjeFib)g^h$32Iz9v?nl7lAE|Vn>X1qX3mqV_s3NQu1X`P3 z2ZdM7k{Z(?$eMLY0CNT?M~PVyKWZtt-Mf5-e>L z770oNzfKB^YMe+K;{#BSy&aHDZqj^QzBD~ffTJSh*x*dpNd=)05syQFd~~-W6q4bA z*y>(_2zKkE${a3T&3Z32gZoM|G%m5Q zErCoUx(^y6Q6iLUXRp;&Y{7Q895BZO?o2IY5hdD%4tE0&3*tW51VV;a!n#j0I zh*?xOPsgTGqXq_s8_C$$Ve{+W=KaE|6g$+{u2mdj+cy`j)m6Z_R)AwoWIG{icoI{o z2s)=&KwDMu48NXh92JHJrk0!KK{Fk+9V%Z`>?Hl?s2e3$WGq_R{C#+9t4HkXqJJ-U>O>O-H^~RD| diff --git a/Assets/Scripts/ServerShared/EntitySerializer.cs b/Assets/Scripts/ServerShared/EntitySerializer.cs index 2401da934..a9679f7c9 100644 --- a/Assets/Scripts/ServerShared/EntitySerializer.cs +++ b/Assets/Scripts/ServerShared/EntitySerializer.cs @@ -90,7 +90,7 @@ public static class EntitySerializer private static void Restore(ItemManager itemManager, Zone zone, EntityPack pack, Entity entity, bool instantiate = false) { entity.Name = pack.Name; - entity.Faction = itemManager.GetCatalogEntry(pack.Faction); + entity.Faction = zone?.Galaxy?.ResolveFaction(pack.Faction); entity.Children = pack.Children.Select(c => { var child = Unpack(itemManager, zone, c, instantiate); diff --git a/Assets/Scripts/ServerShared/Galaxy.cs b/Assets/Scripts/ServerShared/Galaxy.cs index 62012b925..ab249f924 100644 --- a/Assets/Scripts/ServerShared/Galaxy.cs +++ b/Assets/Scripts/ServerShared/Galaxy.cs @@ -467,6 +467,22 @@ public class Galaxy return _containedFactions.Contains(factionID); } + 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); + } + class DijkstraVertex { public float Cost; diff --git a/Assets/Scripts/ServerShared/LoadoutGenerator.cs b/Assets/Scripts/ServerShared/LoadoutGenerator.cs index 667cf6426..3d01e4e61 100644 --- a/Assets/Scripts/ServerShared/LoadoutGenerator.cs +++ b/Assets/Scripts/ServerShared/LoadoutGenerator.cs @@ -137,13 +137,26 @@ public class LoadoutGenerator .WeightedRandomElements(ref Random, item => Faction == null ? 1 : (item.Manufacturer == Faction.ID ? 1 : Faction.Allegiance.ContainsKey(item.Manufacturer) ? Faction.Allegiance[item.Manufacturer] : 0.0f / // Prioritize items from allied manufacturers - (Galaxy?.ContainsFaction(item.Manufacturer) ?? false ? Zone?.Distance[Galaxy.HomeZones[ItemManager.GetCatalogEntry(item.Manufacturer)]] ?? 1 : 1)) * // Penalize distance to manufacturer headquarters + ManufacturerDistancePenalty(item.Manufacturer)) * // Penalize distance to manufacturer headquarters pow(item.Shape.Coordinates.Length, sizeExponent) / // Prioritize larger items pow(item.Price, PriceExponent), // Penalize item price to a controllable degree count ); } + private float ManufacturerDistancePenalty(Guid manufacturer) + { + if (Galaxy == null || Zone == null || !Galaxy.ContainsFaction(manufacturer)) + { + return 1; + } + + var faction = Galaxy.ResolveFaction(manufacturer); + return faction != null && Galaxy.HomeZones.TryGetValue(faction, out var homeZone) + ? Zone.Distance[homeZone] + : 1; + } + public T RandomItem(float sizeExponent, Predicate filter = null) where T : EquippableItemData { return RandomItems(1, sizeExponent, filter).FirstOrDefault(); diff --git a/docs/aetheria-perfect-machine-map.md b/docs/aetheria-perfect-machine-map.md index 8881ed3ba..341b2da57 100644 --- a/docs/aetheria-perfect-machine-map.md +++ b/docs/aetheria-perfect-machine-map.md @@ -85,13 +85,16 @@ legacy catalog cache, and legacy UI paths should be migration-only or deleted. deserialization only. UI code no longer reaches into `LegacyCatalogBoundary.GetCatalog` directly. - `ItemManager` no longer exposes the raw `ILegacyCatalogReader` as public - gameplay/UI API. Item, faction, loadout, trade, and entity restore consumers + gameplay/UI API. Item, loadout item selection, trade, and give-command consumers now go through narrow `ItemManager.GetCatalogEntry` and `GetCatalogEntries` methods. This does not remove the legacy reader under the hood; it prevents old catalog authority from leaking into every caller that only needs a domain lookup. The item properties UI no longer uses `ItemManager` for manufacturer display; it resolves the manufacturer through - the package-owned `ActionGameManager.RuntimeCatalog` typed snapshot. + the package-owned `ActionGameManager.RuntimeCatalog` typed snapshot. Entity + restore and loadout manufacturer-distance weighting no longer use `ItemManager` + for faction lookup; they resolve factions through the `Galaxy` typed + corporation projection. - `Galaxy` generation no longer accepts `ILegacyCatalogReader` or `ItemManager`. Sector and tutorial generation receive the package-owned typed runtime catalog. `Galaxy` projects typed corporation v2 records into temporary legacy @@ -186,6 +189,9 @@ legacy catalog cache, and legacy UI paths should be migration-only or deleted. - Galaxy generation no longer reads legacy `Faction` or `NameFile` entries through `ItemManager`; it requires the typed runtime catalog opened from `GameData/aetheria-world.cc`. +- Entity restore and loadout manufacturer-distance weighting no longer read + legacy `Faction` entries through `ItemManager`; they use `Galaxy.ResolveFaction` + over the typed corporation projection. - MessagePack is no longer used as a runtime object-cloning shortcut for `EntitySettings`, and UI/player-settings startup no longer registers the old MessagePack resolver. Resolver registration is confined to legacy catalog @@ -234,8 +240,9 @@ legacy catalog cache, and legacy UI paths should be migration-only or deleted. `ActionGameManager` has a private boot helper that calls it only to construct `ItemManager`. Runtime code receives narrow `ItemManager` catalog methods where gameplay only needs lookups. `ItemManager` still receives - `ILegacyCatalogReader` until typed runtime catalog boot replaces it; `Galaxy` - has been moved off the legacy reader and now consumes `ItemManager`. + `ILegacyCatalogReader` until typed runtime catalog boot replaces it; `Galaxy`, + entity restore, and faction-distance loadout weighting have been moved off + legacy faction catalog reads. The embedded Unity state package owns the read-only runtime catalog model contract and the read-only known-schema `.cc` catalog opener. `ActionGameManager` now exposes that typed package snapshot at boot. The SDK-style @@ -243,9 +250,8 @@ legacy catalog cache, and legacy UI paths should be migration-only or deleted. contract for full .NET smokes and Eve surface reads. Neither writes state or owns simulation. The legacy cache no longer has a public mutation surface, but it still materializes `ItemManager`. Item properties manufacturer display is - a typed snapshot consumer; trade debug, galaxy generation, loadout generation, - entity restore, and the give console command still use `ItemManager` legacy - domain materialization. + a typed snapshot consumer; trade debug, loadout item selection, and the give + console command still use `ItemManager` legacy item-domain materialization. - Inputs: Unity gameplay code, legacy catalog files, typed state documents, and CultMesh server state. - Outputs: `Aetheria.State` emits `.cc` state and CultMesh documents. Legacy @@ -397,6 +403,9 @@ First Aetheria surfaces to publish: - Done: move `Galaxy` faction selection and name generation to the typed runtime catalog; legacy `Faction`/`NameFile` catalog entries no longer decide generated sector factions or zone names. + - Done: move entity faction restore and loadout manufacturer-distance + weighting to `Galaxy.ResolveFaction`, so legacy `Faction` catalog entries + no longer decide runtime faction references after generation. - Replace `ActionGameManager` cache bootstrap with the new state runtime. - Convert domain references from GUID/base-class patterns to typed record refs.