Cut GUID sidecars from zone runtime

This commit is contained in:
Meta Vens 2026-06-16 20:51:26 +01:00
commit bd4a51f923
9 changed files with 110 additions and 90 deletions

View file

@ -16,6 +16,7 @@ RequireTypedGalaxyFactionRelationships(root);
RequireRuntimeCatalogKeyOnlyLookups(root);
RequireTypedBehaviorBodyKeys(root);
RequireTypedOrbitTaskKeys(root);
RequireTypedAgentTaskKeys(root);
RequireTypedOrbitalEntityOrbitKeys(root);
RequireTypedOrbitConsumerKeys(root);
RequireKeyedOrbitRuntimeWrappers(root);
@ -490,6 +491,7 @@ Console.WriteLine("Live gameplay source purity: no serializer or legacy database
Console.WriteLine("Package serializer boundary: MessagePack symbols remain in named CultCache transport files only");
Console.WriteLine("Shared Eve package ownership: generic Unity Eve packages import from the neighboring Eve repo instead of local staged copies");
Console.WriteLine("Typed runtime behavior coverage: live behavior kinds have typed factory plus progress/state restore coverage");
Console.WriteLine("Zone construction/runtime key authority: body/orbit wrappers and task shells retain typed keys instead of GUID sidecars");
Console.WriteLine("Eve runtime bootstrap: operations surface mounts through UI Toolkit presenter");
Console.WriteLine("Renderer-local console authority: deleted; UI commands flow through Eve command documents");
Console.WriteLine("Renderer-local debug panels: obsolete uGUI field tester authority is deleted");
@ -903,7 +905,6 @@ static void RequireTypedBehaviorBodyKeys(string root)
"public string BodyKey { get; }",
"public string OrbitKey { get; }",
"public string ParentOrbitKey { get; }",
"public string GetBodyKey(Guid bodyId)",
"public bool TryGetPlanet(string bodyKey, out Planet planet)",
"public bool TryGetAsteroidBelt(string bodyKey, out AsteroidBelt belt)"
};
@ -1162,6 +1163,69 @@ static void RequireTypedOrbitTaskKeys(string root)
}
}
static void RequireTypedAgentTaskKeys(string root)
{
var checkedFiles = new[]
{
Path.Combine(root, "Assets", "Scripts", "ServerShared", "Agents", "Tasks", "AgentTask.cs"),
Path.Combine(root, "Assets", "Scripts", "ServerShared", "Agents", "Tasks", "Survey.cs"),
Path.Combine(root, "Assets", "Scripts", "ServerShared", "Agents", "Tasks", "Mining.cs")
};
var forbiddenSymbols = new[]
{
"public Guid Zone",
"List<Guid> Planets",
"public Guid Asteroids"
};
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(
"Agent task shells must retain typed zone/body keys rather than raw GUID fields: " +
string.Join("; ", hits));
}
var requiredSymbols = new Dictionary<string, string[]>
{
[Path.Combine(root, "Assets", "Scripts", "ServerShared", "Agents", "Tasks", "AgentTask.cs")] = new[]
{
"public string ZoneKey = \"\";"
},
[Path.Combine(root, "Assets", "Scripts", "ServerShared", "Agents", "Tasks", "Survey.cs")] = new[]
{
"public List<string> PlanetBodyKeys;"
},
[Path.Combine(root, "Assets", "Scripts", "ServerShared", "Agents", "Tasks", "Mining.cs")] = new[]
{
"public string AsteroidBeltBodyKey = \"\";"
}
};
var missing = requiredSymbols
.Where(entry => !File.Exists(entry.Key) ||
entry.Value.Any(symbol => !File.ReadAllText(entry.Key).Contains(symbol, StringComparison.Ordinal)))
.SelectMany(entry => entry.Value
.Where(symbol => !File.Exists(entry.Key) || !File.ReadAllText(entry.Key).Contains(symbol, StringComparison.Ordinal))
.Select(symbol => $"{Path.GetRelativePath(root, entry.Key)}: missing {symbol}"))
.ToArray();
if (missing.Length > 0)
{
throw new InvalidOperationException(
"Agent task shells must keep typed key placeholders on zone/body references: " +
string.Join("; ", missing));
}
}
static void RequireTypedOrbitalEntityOrbitKeys(string root)
{
var checkedFiles = new[]
@ -1344,6 +1408,7 @@ static void RequireKeyedOrbitRuntimeWrappers(string root)
{
"public Guid OrbitId { get; }",
"public Guid Orbit { get; }",
"public Guid ID { get; }",
"OrbitId = data.Orbit;",
"Orbit = data.Orbit;",
"AsteroidBelts[belt.ID] = new AsteroidBelt(belt);",
@ -1437,7 +1502,10 @@ static void RequireNativeZoneKeyResolution(string root)
"return GetOrbitPosition(ParseOrbitGuid(orbitKey));",
"return GetOrbitVelocity(ParseOrbitGuid(orbitKey));",
"public float2 GetOrbitPosition(Guid orbitID)",
"public float2 GetOrbitVelocity(Guid orbit)"
"public float2 GetOrbitVelocity(Guid orbit)",
"public string GetBodyKey(Guid bodyId)",
"private readonly Dictionary<Guid, Planet> _planetsById = new Dictionary<Guid, Planet>();",
"private readonly Dictionary<Guid, AsteroidBelt> _asteroidBeltsById = new Dictionary<Guid, AsteroidBelt>();"
};
var hits = forbiddenSymbols
.Where(symbol => zoneSource.Contains(symbol, StringComparison.Ordinal))
@ -1455,22 +1523,14 @@ static void RequireNativeZoneKeyResolution(string root)
"public Dictionary<string, Planet> PlanetInstances = new Dictionary<string, Planet>(StringComparer.Ordinal);",
"public Dictionary<string, Orbit> Orbits = new Dictionary<string, Orbit>(StringComparer.Ordinal);",
"public Dictionary<string, AsteroidBelt> AsteroidBelts = new Dictionary<string, AsteroidBelt>(StringComparer.Ordinal);",
"private readonly Dictionary<Guid, Planet> _planetsById = new Dictionary<Guid, Planet>();",
"private readonly Dictionary<Guid, AsteroidBelt> _asteroidBeltsById = new Dictionary<Guid, AsteroidBelt>();",
"PlanetInstances[runtimeSun.BodyKey] = runtimeSun;",
"_planetsById[runtimeSun.ID] = runtimeSun;",
"PlanetInstances[runtimeGas.BodyKey] = runtimeGas;",
"_planetsById[runtimeGas.ID] = runtimeGas;",
"PlanetInstances[runtimePlanet.BodyKey] = runtimePlanet;",
"_planetsById[runtimePlanet.ID] = runtimePlanet;",
"AsteroidBelts[runtimeBelt.BodyKey] = runtimeBelt;",
"_asteroidBeltsById[runtimeBelt.ID] = runtimeBelt;",
"Orbits[runtimeOrbit.OrbitKey] = runtimeOrbit;",
"return PlanetInstances.TryGetValue(bodyKey ?? \"\", out planet);",
"return AsteroidBelts.TryGetValue(bodyKey ?? \"\", out belt);",
"return Orbits.TryGetValue(orbitKey ?? \"\", out orbit);",
"if (_planetsById.TryGetValue(bodyId, out var planet))",
"if (_asteroidBeltsById.TryGetValue(bodyId, out var belt))",
"var parentPosition = string.IsNullOrWhiteSpace(orbit.ParentOrbitKey)",
": GetOrbitPosition(orbit.ParentOrbitKey);",
"return TryGetOrbit(orbitKey, out var orbit) ? orbit.Velocity : float2.zero;",
@ -1590,7 +1650,14 @@ static void RequireTypedZoneConstructionKeys(string root)
"var runtimeGas = new GasGiant(settings, gas, Orbits[OrbitKey(planet.Orbit)]);",
"var runtimePlanet = new Planet(settings, planet, Orbits[OrbitKey(planet.Orbit)]);",
"turret.OrbitKey = Zone.OrbitKey(turretOrbit.ID);",
"station.OrbitKey = Zone.OrbitKey(lagrangeOrbit.ID);"
"station.OrbitKey = Zone.OrbitKey(lagrangeOrbit.ID);",
"public Guid ID = Guid.NewGuid();",
"public Guid Orbit;",
"public Guid Parent;",
"data.OrbitKey = Zone.OrbitKey(data.ID);",
"planetData.BodyKey = Zone.BodyKey(planetData.ID);",
"lagrangeOrbit.OrbitKey = Zone.OrbitKey(lagrangeOrbit.ID);",
"turretOrbit.OrbitKey = Zone.OrbitKey(turretOrbit.ID);"
};
var hits = checkedFiles
@ -1618,13 +1685,14 @@ static void RequireTypedZoneConstructionKeys(string root)
},
[Path.Combine(root, "Assets", "Scripts", "ServerShared", "ZoneGenerator.cs")] = new[]
{
"data.OrbitKey = Zone.OrbitKey(data.ID);",
"OrbitKey = Zone.OrbitKey(Guid.NewGuid()),",
"data.ParentOrbitKey = orbitInverseMap[data].Parent != null",
"planetData.BodyKey = Zone.BodyKey(planetData.ID);",
"planetData.BodyKey = Zone.BodyKey(Guid.NewGuid());",
"planetData.OrbitKey = orbitMap[planet].OrbitKey;",
"lagrangeOrbit.OrbitKey = Zone.OrbitKey(lagrangeOrbit.ID);",
"planetData.Name = bodyName.Substring(0, Math.Min(8, bodyName.Length));",
"var bodyName = planetData.BodyKey.Substring(planetData.BodyKey.LastIndexOf(':') + 1);",
"OrbitKey = Zone.OrbitKey(Guid.NewGuid()),",
"ParentOrbitKey = baseOrbit.ParentOrbitKey,",
"turretOrbit.OrbitKey = Zone.OrbitKey(turretOrbit.ID);",
"ParentOrbitKey = orbit.ParentOrbitKey,",
"turret.OrbitKey = turretOrbit.OrbitKey;",
"station.OrbitKey = lagrangeOrbit.OrbitKey;"

View file

@ -960,7 +960,7 @@ public class ActionGameManager : MonoBehaviour
private static AetheriaRuntimeOrbitSnapshotCommit[] ProjectZoneOrbits(Zone zone)
{
return zone?.Orbits?.Values
.OrderBy(orbit => orbit.ID)
.OrderBy(orbit => orbit.OrbitKey, StringComparer.Ordinal)
.Select(orbit => new AetheriaRuntimeOrbitSnapshotCommit
{
OrbitKey = orbit.OrbitKey,

View file

@ -2,13 +2,11 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
using System;
public abstract class AgentTask
{
public int Priority;
public Guid Zone;
public string ZoneKey = "";
public bool Reserved;

View file

@ -2,11 +2,9 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
using System;
public class Mining : AgentTask
{
public override TaskType Type => TaskType.Mine;
public Guid Asteroids;
public string AsteroidBeltBodyKey = "";
}

View file

@ -2,12 +2,11 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
using System;
using System.Collections.Generic;
public class Survey : AgentTask
{
public override TaskType Type => TaskType.Explore;
public List<Guid> Planets;
public List<string> PlanetBodyKeys;
}

View file

@ -27,9 +27,6 @@ public class Zone
public Dictionary<string, AsteroidBelt> AsteroidBelts = new Dictionary<string, AsteroidBelt>(StringComparer.Ordinal);
public PlanetSettings Settings;
private readonly Dictionary<Guid, Planet> _planetsById = new Dictionary<Guid, Planet>();
private readonly Dictionary<Guid, AsteroidBelt> _asteroidBeltsById = new Dictionary<Guid, AsteroidBelt>();
private HashSet<string> _updatedOrbits = new HashSet<string>(StringComparer.Ordinal);
private ItemManager _itemManager;
@ -72,22 +69,18 @@ public class Zone
case AsteroidBeltConstructionData belt:
var runtimeBelt = new AsteroidBelt(belt, Orbits[belt.OrbitKey]);
AsteroidBelts[runtimeBelt.BodyKey] = runtimeBelt;
_asteroidBeltsById[runtimeBelt.ID] = runtimeBelt;
break;
case SunConstructionData sun:
var runtimeSun = new Sun(settings, sun, Orbits[planet.OrbitKey]);
PlanetInstances[runtimeSun.BodyKey] = runtimeSun;
_planetsById[runtimeSun.ID] = runtimeSun;
break;
case GasGiantConstructionData gas:
var runtimeGas = new GasGiant(settings, gas, Orbits[planet.OrbitKey]);
PlanetInstances[runtimeGas.BodyKey] = runtimeGas;
_planetsById[runtimeGas.ID] = runtimeGas;
break;
default:
var runtimePlanet = new Planet(settings, planet, Orbits[planet.OrbitKey]);
PlanetInstances[runtimePlanet.BodyKey] = runtimePlanet;
_planetsById[runtimePlanet.ID] = runtimePlanet;
break;
}
}
@ -131,17 +124,6 @@ public class Zone
return id == Guid.Empty ? "" : $"{BodyKeyPrefix}{id:D}";
}
public string GetBodyKey(Guid bodyId)
{
if (bodyId == Guid.Empty)
return "";
if (_planetsById.TryGetValue(bodyId, out var planet))
return planet.BodyKey;
if (_asteroidBeltsById.TryGetValue(bodyId, out var belt))
return belt.BodyKey;
return BodyKey(bodyId);
}
public bool TryGetPlanet(string bodyKey, out Planet planet)
{
return PlanetInstances.TryGetValue(bodyKey ?? "", out planet);
@ -420,7 +402,6 @@ public class Planet
{
public Orbit Orbit;
protected readonly PlanetSettings Settings;
public Guid ID { get; }
public string BodyKey { get; }
public string Name { get; }
public string OrbitKey { get; }
@ -438,7 +419,6 @@ public class Planet
{
Settings = settings;
Orbit = orbit;
ID = data.ID;
BodyKey = data.BodyKey ?? "";
Name = data.Name ?? "";
OrbitKey = data.OrbitKey ?? "";
@ -528,7 +508,6 @@ public class AsteroidBelt
{
private readonly Asteroid[] _asteroids;
public Orbit Orbit { get; }
public Guid ID { get; }
public string BodyKey { get; }
public string Name { get; }
public string OrbitKey { get; }
@ -551,7 +530,6 @@ public class AsteroidBelt
{
_asteroids = data.Asteroids;
Orbit = orbit;
ID = data.ID;
BodyKey = data.BodyKey ?? "";
Name = data.Name ?? "";
OrbitKey = data.OrbitKey ?? "";
@ -576,7 +554,6 @@ public class AsteroidBelt
public class Orbit
{
public Guid ID { get; }
public string OrbitKey { get; }
public string ParentOrbitKey { get; }
public float Distance { get; }
@ -595,7 +572,6 @@ public class Orbit
public Orbit(PlanetSettings settings, OrbitConstructionData data)
{
ID = data.ID;
OrbitKey = data.OrbitKey ?? "";
ParentOrbitKey = data.ParentOrbitKey ?? "";
Distance = data.Distance;

View file

@ -2,7 +2,6 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
using System;
using System.Collections;
using System.Collections.Generic;
using UniRx;
@ -23,14 +22,10 @@ public class ZoneConstructionBlueprint
public abstract class BodyConstructionData : INamedEntry
{
public Guid ID = Guid.NewGuid();
public string BodyKey = "";
public string Name = "";
public Guid Orbit;
public string OrbitKey = "";
public float Mass = 0;
@ -109,12 +104,8 @@ public class Asteroid
public class OrbitConstructionData
{
public Guid ID = Guid.NewGuid();
public string OrbitKey = "";
public Guid Parent;
public string ParentOrbitKey = "";
public float Distance;

View file

@ -102,25 +102,21 @@ public static class ZoneGenerator
{
var data = new OrbitConstructionData
{
OrbitKey = "",
OrbitKey = Zone.OrbitKey(Guid.NewGuid()),
ParentOrbitKey = "",
FixedPosition = planet.FixedPosition,
Distance = planet.Distance,
//Period = planet.Period,
Phase = planet.Phase
};
data.OrbitKey = Zone.OrbitKey(data.ID);
orbitMap[planet] = data;
orbitInverseMap[data] = planet;
return data;
}).ToList();
// Link orbit construction parents to generated orbit IDs.
// Link orbit construction parents to generated orbit keys.
foreach (var data in blueprint.Orbits)
{
data.Parent = orbitInverseMap[data].Parent != null
? orbitMap[orbitInverseMap[data].Parent].ID
: Guid.Empty;
data.ParentOrbitKey = orbitInverseMap[data].Parent != null
? orbitMap[orbitInverseMap[data].Parent].OrbitKey
: "";
@ -167,12 +163,12 @@ public static class ZoneGenerator
throw new ArgumentOutOfRangeException();
}
planetData.BodyKey = Zone.BodyKey(planetData.ID);
planetData.BodyKey = Zone.BodyKey(Guid.NewGuid());
planetData.Mass = planet.Mass;
planetData.Orbit = orbitMap[planet].ID;
planetData.OrbitKey = orbitMap[planet].OrbitKey;
// planetData.Resources = planetResources;
planetData.Name = planetData.ID.ToString().Substring(0, 8);
var bodyName = planetData.BodyKey.Substring(planetData.BodyKey.LastIndexOf(':') + 1);
planetData.Name = bodyName.Substring(0, Math.Min(8, bodyName.Length));
if (planetData is AsteroidBeltConstructionData beltData)
{
beltData.Asteroids =
@ -264,14 +260,11 @@ public static class ZoneGenerator
{
var lagrangeOrbit = new OrbitConstructionData
{
ID = Guid.NewGuid(),
OrbitKey = "",
Parent = baseOrbit.Parent,
OrbitKey = Zone.OrbitKey(Guid.NewGuid()),
ParentOrbitKey = baseOrbit.ParentOrbitKey,
Distance = baseOrbit.Distance,
Phase = baseOrbit.Phase + PI / 3 * sign(random.NextFloat() - .5f)
};
lagrangeOrbit.OrbitKey = Zone.OrbitKey(lagrangeOrbit.ID);
blueprint.Orbits.Add(lagrangeOrbit);
return lagrangeOrbit;
}
@ -282,14 +275,11 @@ public static class ZoneGenerator
var turretOrbit = new OrbitConstructionData
{
ID = Guid.NewGuid(),
OrbitKey = "",
Parent = orbit.Parent,
OrbitKey = Zone.OrbitKey(Guid.NewGuid()),
ParentOrbitKey = orbit.ParentOrbitKey,
Distance = orbit.Distance,
Phase = orbit.Phase + phase
};
turretOrbit.OrbitKey = Zone.OrbitKey(turretOrbit.ID);
blueprint.Orbits.Add(turretOrbit);
var turret = loadoutGenerator.GenerateTurretLoadout();
if (turret == null) return;

View file

@ -1381,27 +1381,27 @@ First Aetheria surfaces to publish:
- Done: remove the stale `MessagePack` assembly reference from
`Aetheria.Shared.Unity`; the remaining MessagePack reference is contained
in the typed state package's `.cc` reader.
- In progress: convert domain references from GUID/base-class patterns to
- Done: convert domain references from GUID/base-class patterns to
typed record refs. Item instances, cargo inventory indexes, weapon ammo
references, item-use behavior references, and runtime commit item/hull
surfaces now carry typed item keys. Runtime behavior resource-scanner and
mining-tool body references are named and serialized as typed body keys
through commit/readback state, with the behaviors retaining keyed runtime
state directly and `Zone` owning GUID parsing/resolution at the current
Unity body runtime boundary. Patrol/tow orbit task targets now also retain
typed orbit keys with `Zone` owning orbit-key resolution. Orbital runtime
entities and runtime construction blueprints now also retain typed
`OrbitKey` values, with `Zone` owning orbital movement and dock-camera
parent-orbit resolution for that seam. Renderer, intro-cutscene, and
`ResourceScanner` orbit readers now also consume the wrapper `OrbitKey`
edge instead of wrapper GUID orbit fields. `Planet` and `AsteroidBelt`
runtime wrappers no longer publish separate wrapper orbit GUID fields
either; they retain `OrbitKey` plus their runtime `Orbit` object. `Zone`'s
key-facing lookup surface also resolves through native key-indexed runtime
dictionaries instead of reparsing GUIDs from key strings. Zone asteroid
helpers now also route through typed body keys or runtime `AsteroidBelt`
objects instead of Guid overloads. Remaining broader simulation paths still
derive legacy GUIDs until those structures move to typed keys.
state directly and `Zone` owning key-indexed runtime lookup. Patrol/tow
orbit task targets now also retain typed orbit keys with `Zone` owning
orbit-key resolution. Orbital runtime entities and runtime construction
blueprints now also retain typed `OrbitKey` values, with `Zone` owning
orbital movement and dock-camera parent-orbit resolution for that seam.
Renderer, intro-cutscene, and `ResourceScanner` orbit readers now also
consume the wrapper `OrbitKey` edge instead of wrapper GUID orbit fields.
`Planet`, `AsteroidBelt`, and `Orbit` runtime wrappers no longer retain
GUID identity sidecars; they keep `BodyKey`/`OrbitKey`/`ParentOrbitKey`
plus their runtime object links. `Zone` no longer keeps GUID-to-body
lookup dictionaries or the `GetBodyKey(Guid)` bridge. Zone construction
data and generator handoff now carry typed orbit/body keys directly, and
the remaining agent-task shell placeholders also retain typed string keys
rather than raw GUID fields. The only surviving GUID use in this lane is
local key minting during zone generation, not runtime reference authority.
- Done: delete the `ItemInstance.ItemId` legacy-GUID projection; diagnostics
now report `ItemKey` so item instances expose only typed item-key identity.
- Done: delete `Entity`/`EquippedCargoBay` cargo and consumable GUID lookup