we did it

This commit is contained in:
2025-08-30 22:30:31 -04:00
parent 01a12ec58a
commit 11f21221ee
8 changed files with 61 additions and 72 deletions

View File

@@ -80,14 +80,13 @@ const api = new Elysia({ prefix: "/api" })
body: WsIn,
response: WsOut,
open: ({
open({
data: {
params: { tableKey },
humanKey,
},
send,
}) => {
console.log("websocket opened");
}) {
const table = liveTable(tableKey);
table.inputs.connectionChanges.emit({
@@ -103,7 +102,7 @@ const api = new Elysia({ prefix: "/api" })
);
},
message: (
message(
{
data: {
humanKey,
@@ -111,20 +110,25 @@ const api = new Elysia({ prefix: "/api" })
},
},
body
) => liveTable(tableKey).inputs.messages.emit({ ...body, humanKey }),
) {
liveTable(tableKey).inputs.messages.emit({ ...body, humanKey });
},
close: ({
close({
data: {
params: { tableKey },
humanKey,
},
}) =>
}) {
liveTable(tableKey).inputs.connectionChanges.emit({
humanKey,
presence: "left",
}),
});
},
error: (error) => err(error),
error(error) {
err(error);
},
});
export default api;

View File

@@ -16,7 +16,6 @@ new Elysia()
})
)
.onRequest(({ request }) => console.log(request.url))
.onError(({ error }) => console.error(error))
.get("/ping", () => "pong")
@@ -25,4 +24,4 @@ new Elysia()
.listen(port);
log.log(`server started on ${port}`);
console.log(`server started on ${port}`);

View File

@@ -13,8 +13,9 @@ import Bus, { type Bus as TBus } from "kefir-bus";
import { log } from "./logging";
export const WsOut = t.Object({
players: t.Optional(t.Array(t.String())),
playersPresent: t.Optional(t.Array(t.String())),
playersReady: t.Optional(t.Nullable(t.Record(t.String(), t.Boolean()))),
gameConfig: t.Optional(t.Any()),
view: t.Optional(t.Any()),
});
export type TWsOut = typeof WsOut.static;
@@ -53,7 +54,7 @@ type TablePayload<
};
player: {
[key: string]: {
view: Property<GameView, any>;
view: Property<GameView | null, any>;
};
};
};
@@ -69,7 +70,8 @@ export const liveTable = <
players: string[];
},
GameState,
GameAction extends Attributed
GameAction extends Attributed,
GameView
>(
key: string
) => {
@@ -98,11 +100,9 @@ export const liveTable = <
.map((counts) => Object.keys(counts))
.toProperty();
const playerStreams: TablePayload<
GameConfig,
GameState,
GameAction
>["outputs"]["player"] = {};
const playerStreams: {
[key: string]: { view: Property<GameView | null, any> };
} = {};
playersPresent
.map(set)
.slidingWindow(2, 2)
@@ -110,7 +110,12 @@ export const liveTable = <
.onValue(({ added, removed }) => {
added.forEach((p) => {
playerStreams[p] = {
view: Bus(),
view: combine([gameState], [gameImpl], (a, b) => [a, b] as const)
.map(
([state, game]) =>
state && (game.getView({ state, humanKey: p }) as GameView)
)
.toProperty(),
};
});
removed.forEach((p) => {
@@ -135,12 +140,12 @@ export const liveTable = <
[key: string]: boolean;
} | null,
[
playersPresent,
playersPresent, // TODO: filter to only outside active games
(prev, players: ValueWithin<typeof playersPresent>) =>
Object.fromEntries(players.map((p) => [p, prev?.[p] ?? false])),
],
[
ready,
ready, // TODO: filter to only outside active games
(prev, evt: ValueWithin<typeof ready>) =>
prev?.[evt.humanKey] != null
? {
@@ -155,9 +160,7 @@ export const liveTable = <
(_, players: ValueWithin<typeof playersPresent>) =>
Object.fromEntries(players.map((p) => [p, false])),
]
)
.toProperty()
.log("playersReady");
).toProperty();
const gameStarts = playersReady
.filter(
@@ -165,16 +168,9 @@ export const liveTable = <
Object.values(pr ?? {}).length > 0 &&
Object.values(pr!).every((ready) => ready)
)
.map((_) => null)
.log("gameStarts");
.map((_) => null);
const gameConfigPool = pool<
{
game: GameKey;
players: string[];
},
any
>();
const gameConfigPool = pool<GameConfig, any>();
const gameConfig = gameConfigPool.toProperty();
const gameImpl = gameConfig
@@ -191,24 +187,19 @@ export const liveTable = <
prev || (game.init() as GameState),
],
[
combine([action], [gameImpl], (action, impl) => ({
action,
...impl,
})),
combine([action], [gameImpl], (act, game) => [act, game] as const),
(
prev,
{
game,
action,
}: {
game: Game;
action: Attributed & GameAction;
}
[{ action, humanKey }, game]: [
Attributed & { action: GameAction },
Game
]
) =>
prev &&
(game.resolveAction({
state: prev,
action,
humanKey,
}) as GameState),
],
[quit, () => null]
@@ -233,7 +224,7 @@ export const liveTable = <
}),
]
// TODO: Add player defined config changes
)
) as unknown as Observable<GameConfig, any>
);
tables[key] = {
@@ -241,10 +232,10 @@ export const liveTable = <
outputs: {
global: {
playersPresent,
playersReady: playersReady.toProperty(),
gameConfig: gameConfig as Property<unknown, any>,
playersReady,
gameConfig,
},
player: {},
player: playerStreams,
},
};