Skip to content

Commit

Permalink
Merge pull request #344 from Thorium-Sim/fd-starmap
Browse files Browse the repository at this point in the history
Flight Director Interstellar Starmap
  • Loading branch information
alexanderson1993 authored Jun 17, 2022
2 parents f94f407 + 245f263 commit e914335
Show file tree
Hide file tree
Showing 31 changed files with 597 additions and 248 deletions.
1 change: 1 addition & 0 deletions client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@
"roman-numerals": "^0.3.2",
"three": "^0.135.0",
"three-stdlib": "^2.9.1",
"use-asset": "^1.0.4",
"valtio": "^1.2.7",
"vite-plugin-mdx": "^3.5.10",
"vite-tsconfig-paths": "^3.3.17",
Expand Down
8 changes: 8 additions & 0 deletions client/src/components/FlightDirector/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,14 @@ export default function FlightDirectorLayout() {
<ErrorBoundary fallback={<></>}>
<CoreFlexLayoutDropdown />
</ErrorBoundary>
<Button
className="btn-xs btn-info btn-outline"
onClick={() => {
netSend("spawnShip");
}}
>
Spawn Ship
</Button>
<div className="flex-1"></div>
<LoginButton size="sm" />
</Menubar>
Expand Down
72 changes: 26 additions & 46 deletions client/src/components/Starmap/InterstellarMap.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,12 @@ import {useRef, Suspense, useEffect} from "react";
import {Box3, Camera, Vector3} from "three";
import {useStarmapStore} from "client/src/components/Starmap/starmapStore";
import {useNetRequest} from "client/src/context/useNetRequest";
import SystemMarker from "client/src/components/Starmap/SystemMarker";
import Starfield from "client/src/components/Starmap/Starfield";
import {LightYear, lightYearToLightMinute} from "server/src/utils/unitTypes";
import {
LightMinute,
LightYear,
lightYearToLightMinute,
} from "server/src/utils/unitTypes";
import {toast} from "client/src/context/ToastContext";
import {netSend} from "client/src/context/netSend";
import {useConfirm} from "@thorium/ui/AlertDialog";
Expand All @@ -22,12 +25,7 @@ const ACTION = CameraControlsClass.ACTION;

const INTERSTELLAR_MAX_DISTANCE: LightYear = 2000;

export function InterstellarMap() {
const {pluginId} = useParams() as {
pluginId: string;
};

const stars = useNetRequest("pluginSolarSystems", {pluginId});
export function InterstellarMap({children}: {children: React.ReactNode}) {
const controlsEnabled = useStarmapStore(s => s.cameraControlsEnabled);
const cameraView = useStarmapStore(s => s.cameraView);
const orbitControls = useRef<CameraControlsClass>(null);
Expand Down Expand Up @@ -85,15 +83,7 @@ export function InterstellarMap() {
0xffffff,
]}
/>
{stars.map(star => (
<SystemMarker
key={star.name}
systemId={star.name}
position={Object.values(star.position) as [number, number, number]}
name={star.name}
draggable
/>
))}
{children}
</Suspense>
);
}
Expand All @@ -116,7 +106,7 @@ export function InterstellarMenuButtons({
const confirm = useConfirm();
async function deleteObject() {
const selectedObjectId = useStarmapStore.getState().selectedObjectId;
if (!selectedObjectId) return;
if (!selectedObjectId || typeof selectedObjectId === "number") return;

const doRemove = await confirm({
header: "Are you sure you want to remove this object?",
Expand Down Expand Up @@ -193,15 +183,20 @@ export function InterstellarMenuButtons({
);
}

export const InterstellarPalette = () => {
const {pluginId} = useParams() as {
pluginId: string;
export const InterstellarPalette = ({
selectedStar,
update,
}: {
selectedStar: {
name: string;
position: Record<"x" | "y" | "z", LightMinute>;
description: string;
};
const selectedObjectId = useStarmapStore(store => store.selectedObjectId);
const stars = useNetRequest("pluginSolarSystems", {pluginId});

const selectedStar = stars.find(s => s.name === selectedObjectId);

update: (params: {
name?: string | undefined;
description?: string | undefined;
}) => Promise<void>;
}) => {
useEffect(() => {
if (!selectedStar) {
useStarmapStore.setState({selectedObjectId: null});
Expand All @@ -213,24 +208,9 @@ export const InterstellarPalette = () => {
selectedStar?.description || ""
);

const update = React.useMemo(
() =>
debounce(
async (params: {name?: string; description?: string}) => {
if (!selectedObjectId) return;
const result = await netSend("pluginSolarSystemUpdate", {
pluginId,
solarSystemId: selectedObjectId,
...params,
});
if (params.name) {
useStarmapStore.setState({selectedObjectId: result.solarSystemId});
}
},
500,
{maxWait: 2000, trailing: true}
),
[pluginId, selectedObjectId]
const debouncedUpdate = React.useMemo(
() => debounce(update, 500, {maxWait: 2000, trailing: true}),
[update]
);

useEffect(() => {
Expand All @@ -246,7 +226,7 @@ export const InterstellarPalette = () => {
value={name}
onChange={e => {
setName(e.target.value);
update({name: e.target.value});
debouncedUpdate({name: e.target.value});
}}
name="name"
/>
Expand All @@ -258,7 +238,7 @@ export const InterstellarPalette = () => {
value={description}
onChange={e => {
setDescription(e.target.value);
update({description: e.target.value});
debouncedUpdate({description: e.target.value});
}}
name="description"
/>
Expand Down
14 changes: 9 additions & 5 deletions client/src/components/Starmap/SolarSystemMap.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -147,11 +147,15 @@ export function SolarSystemMenuButtons({
});
if (!doRemove) return;

await netSend("pluginStarDelete", {
pluginId,
solarSystemId,
starId: selectedObjectId,
});
if (typeof selectedObjectId === "string") {
await netSend("pluginStarDelete", {
pluginId,
solarSystemId,
starId: selectedObjectId,
});
} else {
// TODO: Delete objects from the flight director menubar? Maybe not...
}

useStarmapStore.setState({
selectedObjectId: null,
Expand Down
46 changes: 46 additions & 0 deletions client/src/components/Starmap/StarmapCanvas.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import {ReactNode} from "react";
import {
UNSAFE_LocationContext,
UNSAFE_NavigationContext,
UNSAFE_RouteContext,
} from "react-router-dom";
import {Canvas} from "@react-three/fiber";

import {useContextBridge} from "@react-three/drei";

import {useQueryClient, QueryClientProvider} from "react-query";
import {ThoriumContext} from "client/src/context/ThoriumContext";

const FAR = 1e27;

export default function StarmapCanvas({children}: {children: ReactNode}) {
const client = useQueryClient();

const ContextBridge = useContextBridge(ThoriumContext);
const Location = useContextBridge(UNSAFE_LocationContext);
const Navigation = useContextBridge(UNSAFE_NavigationContext);
const RouteContext = useContextBridge(UNSAFE_RouteContext);

return (
<Canvas
onContextMenu={e => {
e.preventDefault();
}}
gl={{antialias: true, logarithmicDepthBuffer: true}}
camera={{fov: 45, far: FAR}}
mode="concurrent"
>
<Navigation>
<Location>
<RouteContext>
<ContextBridge>
<QueryClientProvider client={client}>
{children}
</QueryClientProvider>
</ContextBridge>
</RouteContext>
</Location>
</Navigation>
</Canvas>
);
}
12 changes: 6 additions & 6 deletions client/src/components/Starmap/SystemMarker/SystemCircle.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ const lineWidth = 0.1;
export const DraggableSystemCircle: React.FC<
{
hoveringDirection: React.MutableRefObject<number>;
systemId: string;
systemId: string | number;
parentObject: React.MutableRefObject<Group>;
} & MeshProps
> = ({
Expand All @@ -36,7 +36,7 @@ export const DraggableSystemCircle: React.FC<
newPosition.setY(position[1]);
}
}
if (!pluginId) return;
if (!pluginId || typeof systemId === "number") return;
netSend("pluginSolarSystemUpdate", {
pluginId,
solarSystemId: systemId,
Expand Down Expand Up @@ -64,6 +64,9 @@ export const DraggableSystemCircle: React.FC<
systemId={systemId}
hoveringDirection={hoveringDirection}
{...(bind() as any)}
onDoubleClick={() => {
navigate(systemId.toString());
}}
{...props}
onPointerOver={e => {
props?.onPointerOver?.(e);
Expand All @@ -78,16 +81,13 @@ export const DraggableSystemCircle: React.FC<
hoveredPosition: null,
});
}}
onDoubleClick={() => {
navigate(systemId);
}}
/>
);
};

const SystemCircle: React.FC<
{
systemId: string;
systemId: string | number;
hoveringDirection: React.MutableRefObject<number>;
} & MeshProps
> = ({systemId, hoveringDirection, ...props}) => {
Expand Down
2 changes: 1 addition & 1 deletion client/src/components/Starmap/SystemMarker/SystemLabel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import {useFrame} from "@react-three/fiber";
import {useStarmapStore} from "../starmapStore";

const SystemLabel: React.FC<{
systemId: string;
systemId: string | number;
name: string;
color?: string;
scale?: number;
Expand Down
2 changes: 1 addition & 1 deletion client/src/components/Starmap/SystemMarker/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import {MeshProps, useFrame} from "@react-three/fiber";
import {useStarmapStore} from "../starmapStore";
const SystemMarker: React.FC<
{
systemId: string;
systemId: string | number;
name: string;
position: [number, number, number];
draggable?: boolean;
Expand Down
2 changes: 1 addition & 1 deletion client/src/components/Starmap/starmapStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import create from "zustand";
interface StarmapStore {
viewingMode: "editor" | "core" | "station" | "viewscreen";
skyboxKey: string;
selectedObjectId: string | null;
selectedObjectId: string | number | null;
cameraControlsEnabled: boolean;
setCameraControlsEnabled: (enabled: boolean) => void;
hoveredPosition: [number, number, number] | null;
Expand Down
40 changes: 37 additions & 3 deletions client/src/context/ThoriumContext.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
import {createContext, ReactNode, useContext, useMemo} from "react";
import {useDataConnection} from "../hooks/useDataConnection";
import {SnapshotInterpolation} from "@geckos.io/snapshot-interpolation";
import {ClientSocket} from "../utils/clientSocket";
import {ThoriumAccountContextProvider} from "./ThoriumAccountContext";
import {SI} from "../utils/clientSocket";
import {QueryClient, QueryClientProvider} from "react-query";
import {ReactQueryDevtools} from "react-query/devtools";
import {SocketHandler} from "./SocketHandler";
import {InterpolatedSnapshot} from "@geckos.io/snapshot-interpolation/lib/types";

export const ThoriumContext = createContext<IThoriumContext | null>(null);

interface IThoriumContext {
SI: SnapshotInterpolation;
interpolate: (entityId: number) => null | {x: number; y: number; z: number};
socket: ClientSocket;
reconnectionState: ReturnType<typeof useDataConnection>["reconnectionState"];
}
Expand All @@ -23,12 +24,45 @@ const queryClient = new QueryClient({
},
});

type EntityValues = {
x: number;
y: number;
z: number;
};

let interpolationCache: Record<string, EntityValues> = {};

export function processInterpolation(
snapshot: InterpolatedSnapshot | undefined
) {
if (!snapshot) return {};
return snapshot.state.forEach(entity => {
interpolationCache[entity.id] = {
x: entity.x,
y: entity.y,
z: entity.z,
} as EntityValues;
});
}

function updateInterpolation() {
processInterpolation(SI.calcInterpolation("x y z"));
requestAnimationFrame(updateInterpolation);
}

updateInterpolation();

export function ThoriumProvider({children}: {children: ReactNode}) {
const {socket, reconnectionState} = useDataConnection();

const value: IThoriumContext = useMemo(() => {
return {
SI,
interpolate: (entityId: number) => {
let state = interpolationCache?.[entityId.toString()];

if (!state) return null;
return state;
},
socket,
reconnectionState,
};
Expand Down
6 changes: 5 additions & 1 deletion client/src/context/useNetRequest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,12 @@ export function useNetRequest<
return (data as any) || null;
},
{
cacheTime: Infinity,
refetchOnMount: false,
refetchOnReconnect: false,
refetchOnWindowFocus: false,
networkMode: "always",
staleTime: Infinity,
cacheTime: Infinity,
}
);
useRequestSub({requestName, params});
Expand Down
Loading

0 comments on commit e914335

Please sign in to comment.