Complete universe model migration

This commit is contained in:
2026-04-07 14:16:59 -04:00
parent d0c6e30304
commit 6c92ab50c8
76 changed files with 2061 additions and 1072 deletions

View File

@@ -20,10 +20,17 @@ export function describeSelectable(world: WorldState | undefined, item: Selectab
return world.stations.get(item.id)?.label ?? item.id;
}
if (item.kind === "node") {
return item.id;
const node = world.nodes.get(item.id);
return node ? `${node.itemId} source` : item.id;
}
if (item.kind === "celestial") {
return `${world.celestials.get(item.id)?.kind ?? "celestial"} ${item.id}`;
const celestial = world.celestials.get(item.id);
if (!celestial) {
return item.id;
}
return describeCelestialPathWithinSystem(world, celestial.systemId, celestial.id)
?? `${world.systems.get(celestial.systemId)?.label ?? celestial.systemId} / ${celestial.kind}`;
}
if (item.kind === "claim") {
return `claim ${item.id}`;
@@ -113,9 +120,7 @@ export function describeHoverLabel(world: WorldState | undefined, item: Selectab
return item.id;
}
const anchorPath = node.celestialId
? describeCelestialPathWithinSystem(world, node.systemId, node.celestialId)
: undefined;
const anchorPath = describeAnchorPathWithinSystem(world, node.systemId, node.anchorId);
return anchorPath ? `${anchorPath} / ${node.itemId}` : `${node.systemId} / ${node.itemId}`;
}
@@ -135,16 +140,16 @@ export function describeHoverLabel(world: WorldState | undefined, item: Selectab
if (item.kind === "claim") {
const claim = world.claims.get(item.id);
const anchorPath = claim?.celestialId
? describeCelestialPathWithinSystem(world, claim.systemId, claim.celestialId)
const anchorPath = claim
? describeAnchorPathWithinSystem(world, claim.systemId, claim.anchorId)
: undefined;
return anchorPath ? `${anchorPath} claim` : `Claim ${item.id}`;
}
if (item.kind === "construction-site") {
const site = world.constructionSites.get(item.id);
const anchorPath = site?.celestialId
? describeCelestialPathWithinSystem(world, site.systemId, site.celestialId)
const anchorPath = site
? describeAnchorPathWithinSystem(world, site.systemId, site.anchorId)
: undefined;
const siteLabel = site ? (site.blueprintId ?? site.targetDefinitionId) : item.id;
return anchorPath ? `${anchorPath} / ${siteLabel}` : `Construction ${siteLabel}`;
@@ -210,20 +215,74 @@ export function resolveFocusedCelestialId(world: WorldState | undefined, selecte
return selected.id;
}
if (selected.kind === "ship") {
return world.ships.get(selected.id)?.spatialState.currentCelestialId ?? world.ships.get(selected.id)?.celestialId ?? undefined;
const ship = world.ships.get(selected.id);
return ship?.spatialState.currentAnchorId && world.celestials.has(ship.spatialState.currentAnchorId)
? ship.spatialState.currentAnchorId
: (ship?.anchorId && world.celestials.has(ship.anchorId) ? ship.anchorId : undefined);
}
if (selected.kind === "station") {
return world.stations.get(selected.id)?.celestialId ?? undefined;
const station = world.stations.get(selected.id);
return station?.anchorId && world.celestials.has(station.anchorId) ? station.anchorId : undefined;
}
if (selected.kind === "claim") {
return world.claims.get(selected.id)?.celestialId ?? undefined;
const claim = world.claims.get(selected.id);
return claim && world.celestials.has(claim.anchorId) ? claim.anchorId : undefined;
}
if (selected.kind === "construction-site") {
return world.constructionSites.get(selected.id)?.celestialId ?? undefined;
const site = world.constructionSites.get(selected.id);
return site && world.celestials.has(site.anchorId) ? site.anchorId : undefined;
}
return undefined;
}
export function resolveFocusedAnchorId(world: WorldState | undefined, selectedItems: Selectable[]): string | undefined {
if (!world || selectedItems.length !== 1) {
return undefined;
}
const selected = selectedItems[0];
if (selected.kind === "node") {
return world.nodes.get(selected.id)?.anchorId;
}
if (selected.kind === "ship") {
const ship = world.ships.get(selected.id);
return ship?.spatialState.currentAnchorId
?? ship?.anchorId
?? resolveFocusedCelestialId(world, selectedItems);
}
if (selected.kind === "station") {
const station = world.stations.get(selected.id);
return station?.anchorId
?? resolveFocusedCelestialId(world, selectedItems);
}
if (selected.kind === "claim") {
const claim = world.claims.get(selected.id);
return claim?.anchorId
?? resolveFocusedCelestialId(world, selectedItems);
}
if (selected.kind === "construction-site") {
const site = world.constructionSites.get(selected.id);
return site?.anchorId
?? resolveFocusedCelestialId(world, selectedItems);
}
if (selected.kind === "celestial") {
if (world.anchors.has(selected.id)) {
return selected.id;
}
const orbitBackedAnchor = [...world.anchors.values()].find((anchor) => anchor.orbitReferenceId === selected.id);
return orbitBackedAnchor?.id;
}
if (selected.kind === "planet") {
return `${selected.systemId}-planet-${selected.planetIndex + 1}`;
}
if (selected.kind === "moon") {
return `${selected.systemId}-planet-${selected.planetIndex + 1}-moon-${selected.moonIndex + 1}`;
}
return undefined;
}
export function describeOrbitalParent(world: WorldState | undefined, systemId?: string, anchor?: OrbitalAnchor): string {
if (!world || !systemId) {
return "unknown";
@@ -330,23 +389,31 @@ export function describeShipState(world: WorldState | undefined, ship: ShipSnaps
return baseState;
}
const destinationNodeId = ship.spatialState.destinationNodeId ?? ship.spatialState.transit?.destinationNodeId;
if (!destinationNodeId) {
const destinationAnchorId = ship.spatialState.destinationAnchorId ?? ship.spatialState.transit?.destinationAnchorId;
if (!destinationAnchorId) {
return baseState;
}
const destinationCelestial = world.celestials.get(destinationNodeId);
if (!destinationCelestial) {
return `${baseState} -> ${destinationNodeId}`;
}
const destinationAnchor = destinationAnchorId ? world.anchors.get(destinationAnchorId) : undefined;
if (baseState === "warping" || baseState === "spooling-warp") {
const destinationPath = describeCelestialPathWithinSystem(world, destinationCelestial.systemId, destinationNodeId);
return `${baseState} -> ${destinationPath ?? destinationNodeId}`;
const destinationSystemId = destinationAnchor?.systemId ?? ship.spatialState.currentSystemId ?? ship.systemId;
const destinationPath = describeAnchorPathWithinSystem(
world,
destinationSystemId,
destinationAnchorId,
);
return `${baseState} -> ${destinationPath ?? destinationAnchorId}`;
}
const destinationSystem = world.systems.get(destinationCelestial.systemId);
return `${baseState} -> ${destinationSystem?.label ?? destinationCelestial.systemId}`;
const destinationSystemId = destinationAnchor?.systemId
?? ship.spatialState.currentSystemId
?? ship.systemId;
const destinationSystem = world.systems.get(destinationSystemId);
if (!destinationSystem) {
return `${baseState} -> ${destinationAnchorId}`;
}
return `${baseState} -> ${destinationSystem.label}`;
}
export function describeShipObjective(objective: string): string {
@@ -406,8 +473,8 @@ export function describeShipLocation(world: WorldState | undefined, ship: ShipSn
if (ship.dockedStationId) {
const station = world.stations.get(ship.dockedStationId);
if (station) {
const anchorPath = station.celestialId
? describeCelestialPathWithinSystem(world, station.systemId, station.celestialId)
const anchorPath = station.anchorId
? describeAnchorPathWithinSystem(world, station.systemId, station.anchorId)
: undefined;
return {
system: systemLabel,
@@ -416,11 +483,11 @@ export function describeShipLocation(world: WorldState | undefined, ship: ShipSn
}
}
const currentCelestialId = ship.spatialState.currentCelestialId ?? ship.celestialId;
if (currentCelestialId) {
const celestialPath = describeCelestialPathWithinSystem(world, systemId, currentCelestialId);
if (celestialPath) {
return { system: systemLabel, local: celestialPath };
const currentAnchorId = ship.spatialState.currentAnchorId ?? ship.anchorId;
if (currentAnchorId) {
const anchorPath = describeAnchorPathWithinSystem(world, systemId, currentAnchorId);
if (anchorPath) {
return { system: systemLabel, local: anchorPath };
}
}
@@ -446,9 +513,9 @@ export function describeActiveSpace(
return activeSystem.label;
}
const celestialId = resolveFocusedCelestialId(world, selectedItems);
if (celestialId) {
const localPath = describeCelestialPathWithinSystem(world, activeSystem.id, celestialId);
const anchorId = resolveFocusedAnchorId(world, selectedItems);
if (anchorId) {
const localPath = describeAnchorPathWithinSystem(world, activeSystem.id, anchorId);
return localPath
? `${activeSystem.label} / ${localPath}`
: activeSystem.label;
@@ -472,10 +539,9 @@ export function describeCelestialPathWithinSystem(world: WorldState, systemId: s
return undefined;
}
if (celestial.parentNodeId) {
const parentPath = describeCelestialPathWithinSystem(world, systemId, celestial.parentNodeId);
const segment = describeCelestialSegment(system, celestial);
return parentPath ? `${parentPath}/${segment}` : segment;
const anchorId = resolveAnchorIdForCelestial(world, celestialId);
if (anchorId) {
return describeAnchorPathWithinSystem(world, systemId, anchorId);
}
if (celestial.kind === "star") {
@@ -485,6 +551,60 @@ export function describeCelestialPathWithinSystem(world: WorldState, systemId: s
return describeCelestialSegment(system, celestial);
}
export function describeAnchorPathWithinSystem(world: WorldState, systemId: string, anchorId: string, celestialId?: string | null): string | undefined {
const anchor = world.anchors.get(anchorId);
if (anchor?.parentAnchorId) {
const parentPath = describeAnchorPathWithinSystem(world, systemId, anchor.parentAnchorId);
const segment = describeAnchorSegment(anchor);
return parentPath ? `${parentPath}/${segment}` : segment;
}
if (celestialId) {
return describeCelestialPathWithinSystem(world, systemId, celestialId);
}
if (!anchor) {
return undefined;
}
return describeAnchorSegment(anchor);
}
function describeAnchorSegment(anchor: { kind: string; id: string; orbitReferenceId?: string | null }): string {
if (anchor.orbitReferenceId) {
return describeAnchorOrbitReference(anchor.orbitReferenceId);
}
if (anchor.kind === "resource-node") {
return anchor.id;
}
return anchor.kind.replace(/-/g, " ");
}
function resolveAnchorIdForCelestial(world: WorldState, celestialId: string): string | undefined {
return world.anchors.has(celestialId) ? celestialId : undefined;
}
function describeAnchorOrbitReference(referenceId: string): string {
const lagrangeMatch = referenceId.match(/(l[1-5])$/i);
if (lagrangeMatch) {
return lagrangeMatch[1].toUpperCase();
}
const moonMatch = referenceId.match(/moon-(\d+)$/i);
if (moonMatch) {
return `Moon ${moonMatch[1]}`;
}
const planetMatch = referenceId.match(/planet-(\d+)$/i);
if (planetMatch) {
return `Planet ${planetMatch[1]}`;
}
return referenceId;
}
function describeCelestialSegment(system: SystemSnapshot, celestial: CelestialSnapshot): string {
const moonMatch = celestial.id.match(/-planet-(\d+)-moon-(\d+)$/);
if (moonMatch) {