import { useFrame } from "@react-three/fiber";
import { keepPreviousData } from "@tanstack/react-query";
import OrbitContainer, { OrbitLine } from "@thorium/components/Starmap/OrbitContainer";
import { planetSpriteScale } from "@thorium/components/Starmap/Planet";
import { PlanetSprite } from "@thorium/components/Starmap/Planet";
import { SolarSystemMap } from "@thorium/components/Starmap/SolarSystemMap";
import { StarSprite } from "@thorium/components/Starmap/Star/StarMesh";
import { StarmapShip } from "@thorium/components/Starmap/StarmapShip";
import { useGetStarmapStore } from "@thorium/components/Starmap/starmapStore";
import SystemLabel from "@thorium/components/Starmap/SystemMarker/SystemLabel";
import { WaypointEntity } from "@thorium/components/Starmap/WaypointEntity";
import { q } from "@thorium/context/AppContext";
import { useStation } from "@thorium/routes/station/useStation";
import { setCursor } from "@thorium/utils/setCursor";
import { getOrbitPosition } from "@thorium/utils/starmap/getOrbitPosition";
import { Coordinates, degToRad, solarRadiusToKilometers } from "@thorium/utils/unitTypes";
import { useEffect, useMemo, useRef } from "react";
import { Suspense } from "react";
import { ErrorBoundary } from "react-error-boundary";
import { Color, type Group } from "three";
export function SolarSystemWrapper() {
const { shipId } = useStation();
const useStarmapStore = useGetStarmapStore();
const currentSystem = useStarmapStore((store) => store.currentSystem);
const [system] = q.starmapCore.system.useNetRequest(
{
systemId: currentSystem!,
},
{ placeholderData: keepPreviousData, enabled: currentSystem !== null },
);
const [starmapEntities] = q.starmapCore.entities.useNetRequest({
systemId: currentSystem,
});
const [ship] = q.navigation.ship.useNetRequest({ shipId });
const [waypoints] = q.waypoints.all.useNetRequest({
shipId,
active: false,
systemId: currentSystem,
});
const [autopilot] = q.pilot.autopilot.get.useNetRequest({ shipId });
useEffect(() => {
useStarmapStore.getState().currentSystemSet?.(currentSystem);
}, [useStarmapStore, currentSystem]);
if (currentSystem === null) return null;
return (
{starmapEntities.map((entity) => {
if (entity.components.isStar) {
if (!entity.components.satellite) return null;
const size = solarRadiusToKilometers(entity.components.isStar.radius);
const color = new Color(
`hsl(${entity.components.isStar.hue}, 100%, ${
entity.components.isStar.isWhite ? 100 : 50
}%)`,
);
return (
{
setCursor("pointer");
}}
onPointerOut={() => {
setCursor("auto");
}}
onClick={() => {
if (entity.components.satellite) {
const position = getOrbitPosition(entity.components.satellite);
useStarmapStore.getState().setCameraFocus(position);
}
useStarmapStore.setState({ selectedObjectIds: [entity.id] });
}}
>
);
}
if (entity.components.isPlanet) {
if (!entity.components.satellite) return null;
return (
) => {
useStarmapStore.setState({ selectedObjectIds: [entity.id] });
useStarmapStore.getState().setCameraFocus(position);
}}
/>
);
}
return null;
})}
{ship.position?.parentId === currentSystem && (
<>>} onError={(err) => console.error(err)}>
)}
{waypoints.map((waypoint) => (
<>>} onError={(err) => console.error(err)}>
))}
);
}
function PlanetRenderer({
name,
satellite,
onClick,
}: {
name?: string;
satellite: {
axialTilt: number;
semiMajorAxis: number;
eccentricity: number;
inclination: number;
orbitalArc: number;
parentId: number | null;
};
onClick: (position: Coordinates) => void;
}) {
const useStarmapStore = useGetStarmapStore();
const currentSystem = useStarmapStore((store) => store.currentSystem);
const [starmapEntities] = q.starmapCore.entities.useNetRequest({
systemId: currentSystem,
});
const labelRef = useRef(null);
const origin = useMemo(() => {
const parent = starmapEntities.find((s) => s.id === satellite.parentId)?.components.satellite;
if (!parent) return undefined;
return getOrbitPosition(parent);
}, [starmapEntities, satellite.parentId]);
const position = getOrbitPosition({ ...satellite, origin });
const { semiMajorAxis, eccentricity, inclination } = satellite;
const radiusY = semiMajorAxis - semiMajorAxis * eccentricity;
useFrame(({ camera }) => {
if (labelRef.current) {
const zoom = camera.position.distanceTo(position) + 500;
const zoomedScale = (zoom / 2) * 0.01;
labelRef.current.scale.set(zoomedScale, zoomedScale, zoomedScale);
labelRef.current.quaternion.copy(camera.quaternion);
}
});
return (
{
setCursor("pointer");
}}
onPointerOut={() => {
setCursor("auto");
}}
onClick={onClick}
>
{name && (
)}
);
}