Restructure into pnpm monorepo with game shell, docs, and SpacetimeDB backend
- Restructure flat static prototype into pnpm workspace monorepo - apps/game: playable shell with R3F 3D scene, HUD, SpacetimeDB connection - apps/docs: design docs and prototypes - apps/site: landing page - packages/ui: shared Button and Panel primitives - services/spacetimedb: backend module (9 tables, 11 reducers) - Archive legacy static files to archive/legacy-static/ - Game loop: connect, undock, target, approach, dock, mine, sell - Add pnpm-workspace.yaml, tsconfig.base.json, spacetime.json
This commit is contained in:
60
apps/game/src/spacetime/useSpacetimeConnection.ts
Normal file
60
apps/game/src/spacetime/useSpacetimeConnection.ts
Normal file
@@ -0,0 +1,60 @@
|
||||
import { useEffect, useMemo, useState } from "react";
|
||||
import type { DbConnection } from "../module_bindings";
|
||||
import { createSpacetimeConnection, type ConnectionStatus, type IdentityLike } from "./client";
|
||||
|
||||
const defaultUri = import.meta.env.VITE_SPACETIME_URI ?? import.meta.env.VITE_SPACETIMEDB_HOST ?? "http://localhost:3000";
|
||||
const defaultDatabase =
|
||||
import.meta.env.VITE_SPACETIME_DATABASE ?? import.meta.env.VITE_SPACETIMEDB_DB_NAME ?? "void-nav-dev";
|
||||
|
||||
export function useSpacetimeConnection(displayName: string) {
|
||||
const [status, setStatus] = useState<ConnectionStatus>("idle");
|
||||
const [message, setMessage] = useState<string>();
|
||||
const [identity, setIdentity] = useState<IdentityLike>();
|
||||
const [connection, setConnection] = useState<DbConnection | null>(null);
|
||||
const [revision, setRevision] = useState(0);
|
||||
const [reducerStatus, setReducerStatus] = useState<{ message: string; isError: boolean }>();
|
||||
|
||||
const config = useMemo(
|
||||
() => ({
|
||||
uri: defaultUri,
|
||||
database: defaultDatabase,
|
||||
}),
|
||||
[],
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
const conn = createSpacetimeConnection({
|
||||
...config,
|
||||
displayName,
|
||||
onStatus: (nextStatus, nextMessage) => {
|
||||
setStatus(nextStatus);
|
||||
setMessage(nextMessage);
|
||||
},
|
||||
onIdentity: setIdentity,
|
||||
onDataChanged: () => setRevision((value) => value + 1),
|
||||
onReducerStatus: (nextMessage, isError = false) => setReducerStatus({ message: nextMessage, isError }),
|
||||
});
|
||||
|
||||
setConnection(conn);
|
||||
|
||||
const refresh = window.setInterval(() => {
|
||||
if (conn) setRevision((value) => value + 1);
|
||||
}, 1500);
|
||||
|
||||
return () => {
|
||||
window.clearInterval(refresh);
|
||||
conn?.disconnect?.();
|
||||
};
|
||||
}, [config, displayName]);
|
||||
|
||||
return {
|
||||
connection,
|
||||
status,
|
||||
message,
|
||||
identity,
|
||||
revision,
|
||||
reducerStatus,
|
||||
uri: config.uri,
|
||||
database: config.database,
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user