Something went wrong. Try again.
Starship Simulator Controls thoriumsim.com
Something went wrong. Try again.
5.8 kB · 202 lines
TSX
at develop
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203import type { FlightStartingPoint } from "@thorium/.server/spawners/flight";import { q } from "@thorium/context/AppContext";import { useLocalStorageReducer } from "@thorium/hooks/useLocalStorage";import uniqid from "@thorium/utils/uniqid";import { produce } from "immer";import { createContext, useContext, useEffect, type ReactNode } from "react";import { useSearchParams } from "react-router";
export interface FlightConfigState { hasFlightDirector: boolean; flightName: string; ships: { id: string; shipId: { pluginId: string; shipId: string }; name: string; crewCount: number; }[]; missionId?: { pluginId: string; missionId: string }; startingPointId?: FlightStartingPoint; mode: "nova" | "legacy";}
export type FlightConfigAction = | { type: "increaseCrewCount"; id: string; availableCrewSizes: number[] } | { type: "decreaseCrewCount"; id: string; availableCrewSizes: number[] } | { type: "hasFlightDirector"; hasFlightDirector: boolean } | { type: "flightName"; name: string } | { type: "shipId"; id: string; shipId: { pluginId: string; shipId: string } } | { type: "shipName"; id: string; name: string } | { type: "addShip"; name: string; shipId?: { pluginId: string; shipId: string }; } | { type: "removeShip"; id: string } | { type: "missionId"; missionId: { pluginId: string; missionId: string } | undefined; } | { type: "startingPointId"; startingPointId: FlightStartingPoint | undefined; } | { type: "mode"; mode: "nova" | "legacy"; };
function quickStartReducer( state: FlightConfigState, action: FlightConfigAction,): FlightConfigState { switch (action.type) { case "increaseCrewCount": { return produce(state, (draft) => { const ship = draft.ships.find((ship) => ship.id === action.id); if (!ship) return; const currentIndex = action.availableCrewSizes.indexOf(ship.crewCount); if (currentIndex < action.availableCrewSizes.length - 1) { ship.crewCount = action.availableCrewSizes[currentIndex + 1]; } }); } case "decreaseCrewCount": { return produce(state, (draft) => { const ship = draft.ships.find((ship) => ship.id === action.id); if (!ship) return; const currentIndex = action.availableCrewSizes.indexOf(ship.crewCount); if (currentIndex > 0) { ship.crewCount = action.availableCrewSizes[currentIndex - 1]; } }); } case "hasFlightDirector": return { ...state, hasFlightDirector: action.hasFlightDirector }; case "shipId": return produce(state, (draft) => { for (const ship of draft.ships) { if (ship.id === action.id) { ship.shipId = action.shipId; } } }); case "shipName": return produce(state, (draft) => { for (const ship of draft.ships) { if (ship.id === action.id) { ship.name = action.name; } } }); case "addShip": return { ...state, ships: [ ...(state.ships || []), { id: uniqid(), name: action.name, shipId: action.shipId || (state.ships || []).at(-1)!.shipId, crewCount: (state.ships || []).at(-1)?.crewCount || 1, }, ], }; case "removeShip": return { ...state, ships: state.ships.filter((ship) => ship.id !== action.id), }; case "missionId": return { ...state, missionId: action.missionId }; case "startingPointId": return { ...state, startingPointId: action.startingPointId }; case "flightName": return { ...state, flightName: action.name }; case "mode": return { ...state, mode: action.mode, hasFlightDirector: action.mode === "legacy" ? true : state.hasFlightDirector, missionId: undefined, }; default: return state; }}
const QuickStartContext = createContext<[FlightConfigState, React.Dispatch<FlightConfigAction>]>( null!,);
export function FlightQuickStartProvider({ children }: { children: ReactNode }) { const [settings] = q.thorium.settings.useNetRequest(); const [defaultFlightName] = q.textPattern.interpolate.useNetRequest({ string: settings.flightNameTemplate, }); const value = useLocalStorageReducer< typeof quickStartReducer, FlightConfigState, FlightConfigAction >( quickStartReducer, { flightName: defaultFlightName.output, hasFlightDirector: true, mode: "nova", ships: [ { id: uniqid(), name: "Voyager", crewCount: 1, shipId: { pluginId: "Thorium Default", shipId: "Astra Frigate" }, }, ], missionId: { pluginId: "Thorium Default", missionId: "Sandbox" }, }, "flightConfig", ); const set = value[1]; const ships = value[0].ships || [];
useEffect(() => { if (ships.length === 0) { set({ type: "addShip", name: "Voyager", shipId: { pluginId: "Thorium Default", shipId: "Astra Frigate" }, }); } }, [ships, set]);
// New flight name every time the browser opens, overriding the stored one useEffect(() => { set({ type: "flightName", name: defaultFlightName.output, }); }, [set]);
const [searchParams, setSearchParams] = useSearchParams(); const missionId = searchParams.get("missionId"); const missionPluginId = searchParams.get("missionPluginId"); useEffect(() => { if (missionId && missionPluginId) { set({ type: "missionId", missionId: { missionId, pluginId: missionPluginId } }); setSearchParams((params) => { params.delete("missionId"); params.delete("missionPluginId"); return params; }); } }, [set, missionId, missionPluginId]);
console.log(value[0].missionId); return <QuickStartContext.Provider value={value}>{children}</QuickStartContext.Provider>;}
export const useFlightQuickStart = () => { const returnVal = useContext(QuickStartContext); if (!returnVal) throw new Error("useFlightQuickStart must be used within a QuickStartProvider"); return returnVal;};