Use typed faction keys for galaxy allegiance

This commit is contained in:
Meta Vens 2026-06-16 10:20:36 +01:00
commit a29794232d
6 changed files with 58 additions and 36 deletions

Binary file not shown.

View file

@ -11,6 +11,7 @@ RequireGameplaySourcePurity(root);
RequirePackageSerializerBoundary(root);
RequireTypedPendingCommitKeys(root);
RequireTypedRuntimeFactionKeys(root);
RequireTypedGalaxyFactionRelationships(root);
RequireEveRuntimeBootstrap(root);
RequireNoRendererLocalConsole(root);
RequireNoRendererLocalDebugPanels(root);
@ -662,6 +663,42 @@ static void RequireTypedRuntimeFactionKeys(string root)
}
}
static void RequireTypedGalaxyFactionRelationships(string root)
{
var checkedFiles = new[]
{
Path.Combine(root, "Assets", "Scripts", "ServerShared", "Corporations.cs"),
Path.Combine(root, "Assets", "Scripts", "ServerShared", "Galaxy.cs"),
Path.Combine(root, "Assets", "Scripts", "ServerShared", "LoadoutGenerator.cs")
};
var forbiddenSymbols = new[]
{
"Dictionary<Guid, float> 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(

View file

@ -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

View file

@ -40,8 +40,6 @@ public class Faction : INamedEntry
[Inspectable]
public int InfluenceDistance = 4;
[InspectableRangedFloat(0, 1)]
public Dictionary<Guid, float> Allegiance = new Dictionary<Guid, float>();
public Dictionary<string, float> AllegianceByKey = new Dictionary<string, float>();
[InspectableSoundBank]

View file

@ -31,7 +31,6 @@ public class Galaxy
private Action<string> Log { get; }
public bool IsPrelude { get; }
private HashSet<Guid> _containedFactions;
private HashSet<string> _containedFactionKeys;
private GalaxyZone[] _exitPath;
private Dictionary<Faction, MarkovNameGenerator> _nameGenerators = new Dictionary<Faction, MarkovNameGenerator>();
@ -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<string>(
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<Guid>(Factions.Select(f => f.ID));
return _containedFactions.Contains(factionID);
}
public bool ContainsFaction(string factionKey)
{
_containedFactionKeys ??= new HashSet<string>(
@ -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))

View file

@ -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