bug fixes

This commit is contained in:
2025-08-25 18:36:59 -04:00
parent a117f6703f
commit 6c45e7b114
5 changed files with 78 additions and 39 deletions

View File

@@ -1,10 +1,20 @@
import { Accessor, createContext, For, onCleanup, Show } from "solid-js"; import {
Accessor,
createContext,
createEffect,
createResource,
createSignal,
For,
onCleanup,
Show,
} from "solid-js";
import { TWsIn, TWsOut } from "../../../server/src/table"; import { TWsIn, TWsOut } from "../../../server/src/table";
import api, { fromWebsocket } from "../api"; import api, { fromWebsocket } from "../api";
import { createObservable, createObservableWithInit, cx } from "../fn"; import { createObservable, createObservableWithInit, cx } from "../fn";
import { me } from "../profile"; import { me } from "../profile";
import Game from "./Game"; import Game from "./Game";
import Player from "./Player"; import Player from "./Player";
import { fromPromise } from "kefir";
export const TableContext = createContext<{ export const TableContext = createContext<{
players: Accessor<string[]>; players: Accessor<string[]>;
@@ -13,9 +23,20 @@ export const TableContext = createContext<{
}>(); }>();
export default (props: { tableKey: string }) => { export default (props: { tableKey: string }) => {
const wsPromise = new Promise<
ReturnType<ReturnType<typeof api.ws>["subscribe"]>
>((res) => {
const ws = api.ws(props).subscribe(); const ws = api.ws(props).subscribe();
const wsEvents = fromWebsocket<TWsOut>(ws); ws.on("open", () => res(ws));
onCleanup(() => ws.close()); ws.on("error", () => res(ws));
ws.on("close", () => res(ws));
});
const sendWs = (msg: TWsIn) => wsPromise.then((ws) => ws.send(msg));
const wsEvents = fromPromise(wsPromise).flatMap((ws) =>
fromWebsocket<TWsOut>(ws)
);
onCleanup(() => wsPromise.then((ws) => ws.close()));
const presenceEvents = wsEvents.filter((evt) => evt.players != null); const presenceEvents = wsEvents.filter((evt) => evt.players != null);
@@ -26,12 +47,14 @@ export default (props: { tableKey: string }) => {
[] []
); );
const [ready, setReady] = createSignal(false);
createEffect(() => sendWs({ ready: ready() }));
const view = createObservable(gameEvents.map((evt) => evt.view)); const view = createObservable(gameEvents.map((evt) => evt.view));
return ( return (
<TableContext.Provider <TableContext.Provider
value={{ value={{
sendWs: (evt) => ws.send(evt), sendWs,
view, view,
players, players,
}} }}
@@ -83,10 +106,10 @@ export default (props: { tableKey: string }) => {
<Show when={view() == null}> <Show when={view() == null}>
<div class="absolute center"> <div class="absolute center">
<button <button
onClick={() => ws.send({ ready: true })} onClick={() => setReady((prev) => !prev)}
class="button p-1 " class="button p-1 "
> >
Ready {ready() ? "Not Ready" : "Ready"}
</button> </button>
</div> </div>
</Show> </Show>

View File

@@ -1,16 +1,18 @@
import { A, useParams } from "@solidjs/router"; import { A, useParams } from "@solidjs/router";
import Table from "../components/Table"; import Table from "../components/Table";
import { Show } from "solid-js";
import { me } from "../profile";
export default () => { export default () => {
const { tableKey } = useParams(); const { tableKey } = useParams();
return ( return (
<> <Show when={me() != null}>
<Table tableKey={tableKey} /> <Table tableKey={tableKey} />
<A href={"/"} class="fixed tl m-4 px-2 py-1.5 button"> <A href={"/"} class="fixed tl m-4 px-2 py-1.5 button">
Back Back
</A> </A>
</> </Show>
); );
}; };

View File

@@ -74,6 +74,8 @@ const api = new Elysia({ prefix: "/api" })
}, },
send, send,
}) { }) {
console.log(humanKey, "connected");
try {
const table = liveTable< const table = liveTable<
SimpleConfiguration, SimpleConfiguration,
SimpleGameState, SimpleGameState,
@@ -101,6 +103,9 @@ const api = new Elysia({ prefix: "/api" })
humanKey, humanKey,
presence: "joined", presence: "joined",
}); });
} catch (err) {
console.error(err);
}
}, },
response: WsOut, response: WsOut,
@@ -139,6 +144,10 @@ const api = new Elysia({ prefix: "/api" })
presence: "left", presence: "left",
}); });
}, },
// error(err) {
// console.error("ERROR IN WEBSOCKET", JSON.stringify(err, null, 2));
// },
}); });
export default api; export default api;

View File

@@ -11,9 +11,9 @@ const app = new Elysia()
origin: ["http://localhost:3000", "https://games.drm.dev"], origin: ["http://localhost:3000", "https://games.drm.dev"],
}) })
) )
.onRequest(({ request }) => { // .onRequest(({ request }) => {
console.log(request.method, request.url); // console.log(request.method, request.url);
}) // })
.onError(({ error }) => { .onError(({ error }) => {
console.error(error); console.error(error);
return error; return error;

View File

@@ -12,7 +12,7 @@ import { transform } from "./kefir-extension";
export const WsOut = t.Object({ export const WsOut = t.Object({
players: t.Optional(t.Array(t.String())), players: t.Optional(t.Array(t.String())),
playersReady: t.Optional(t.Record(t.String(), t.String())), playersReady: t.Optional(t.Record(t.String(), t.Boolean())),
view: t.Optional(t.Any()), view: t.Optional(t.Any()),
}); });
export type TWsOut = typeof WsOut.static; export type TWsOut = typeof WsOut.static;
@@ -60,7 +60,6 @@ export const liveTable = <GameConfig, GameState, GameAction>(key: string) => {
quits: Bus(), quits: Bus(),
}; };
const { connectionChanges, readys, actions, quits } = inputs; const { connectionChanges, readys, actions, quits } = inputs;
// ======= // =======
const playersPresent = connectionChanges const playersPresent = connectionChanges
@@ -97,7 +96,11 @@ export const liveTable = <GameConfig, GameState, GameAction>(key: string) => {
); );
const gameStarts = playersReady const gameStarts = playersReady
.filter((pr) => Object.values(pr).every((ready) => ready)) .filter(
(pr) =>
Object.values(pr).length > 0 &&
Object.values(pr).every((ready) => ready)
)
.map((_) => null); .map((_) => null);
const gameConfig = playersPresent.map((players) => ({ const gameConfig = playersPresent.map((players) => ({
@@ -147,9 +150,11 @@ export const liveTable = <GameConfig, GameState, GameAction>(key: string) => {
// cleanup // cleanup
tables[key].outputs.playersPresent tables[key].outputs.playersPresent
.debounce(30000) .debounce(30000, { immediate: false })
.filter((players) => players.length === 0) .filter((players) => players.length === 0)
.skip(1)
.onValue((_) => { .onValue((_) => {
console.log("DELETING LIVE TABLE");
delete tables[key]; delete tables[key];
}); });
} }