@bazimazi/partyframe-server 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,9 @@
1
+ # @bazimazi/partyframe-server
2
+
3
+ Server package: Colyseus session room, `defineGame`, and `listen()`.
4
+
5
+ ```ts
6
+ import { defineGame, listen } from "@bazimazi/partyframe-server";
7
+
8
+ await listen({ defaultGameId: "tap", games: [tapAdapter] });
9
+ ```
@@ -0,0 +1,143 @@
1
+ /**
2
+ * The one room type the platform needs.
3
+ *
4
+ * A `PartySessionRoom` owns a `GameSession`: its public code, its lobby, its
5
+ * players (human and bot), its lifecycle and its authoritative clock. The game
6
+ * being played is a plugin resolved at creation time, so this file contains no
7
+ * Bomb Party logic whatsoever - swapping in a different game changes only which
8
+ * adapter is looked up.
9
+ *
10
+ * Authority model, in one sentence: clients send *intentions*, this room decides
11
+ * what actually happened, and the resulting state is what everyone renders.
12
+ */
13
+ import { Room, type Client } from "@colyseus/core";
14
+ import { type ClientRole, type SessionStatus } from "@partyframe/protocol";
15
+ import { SessionSchema } from "./sessionSchema.js";
16
+ /** Options the matchmaker passes when a shared screen creates a session. */
17
+ export interface RoomCreateOptions {
18
+ gameId?: string;
19
+ /** Fixed seed, used only by tests to make a whole match reproducible. */
20
+ seed?: number;
21
+ }
22
+ /** Metadata published to the matchmaker, used by the `/api/rooms/:code` lookup. */
23
+ export interface RoomMetadata {
24
+ publicCode: string;
25
+ gameId: string;
26
+ status: SessionStatus;
27
+ playerCount: number;
28
+ maxPlayers: number;
29
+ }
30
+ interface ClientData {
31
+ role: ClientRole;
32
+ joinedAt: number;
33
+ }
34
+ export declare class PartySessionRoom extends Room<SessionSchema, RoomMetadata> {
35
+ maxClients: number;
36
+ private adapter;
37
+ private gameState;
38
+ private gameOptions;
39
+ private rng;
40
+ private registry;
41
+ /** Presentation cues queued by the game during the current tick. */
42
+ private eventQueue;
43
+ /** Status the game asked for during the current tick, applied once at the end. */
44
+ private requestedStatus;
45
+ /** Bot strategies, one per difficulty, shared by every bot at that level. */
46
+ private botStrategies;
47
+ /** A bot's chosen action and the time it should be submitted. */
48
+ private botPending;
49
+ private readonly gameLimiter;
50
+ private readonly sessionLimiter;
51
+ private readonly clockLimiter;
52
+ private createdAt;
53
+ private lastConnectedAt;
54
+ private lastBeaconAt;
55
+ private nextSeat;
56
+ private controllerRevision;
57
+ /** Last envelope sent to each controller, so unchanged state is not resent. */
58
+ private lastControllerJson;
59
+ private logger;
60
+ onCreate(options: RoomCreateOptions): Promise<void>;
61
+ onAuth(_client: Client, rawOptions: unknown): ClientData;
62
+ onJoin(client: Client, _options: unknown, auth: ClientData): void;
63
+ onLeave(client: Client, consented: boolean): Promise<void>;
64
+ onDispose(): void;
65
+ /** Creates or revives the row for a controller's seat. */
66
+ private ensurePlayerRow;
67
+ private pickFreeColor;
68
+ private pickFreeAvatar;
69
+ private removePlayer;
70
+ /** The longest-seated joined human becomes host when the previous one leaves. */
71
+ private electHostPlayer;
72
+ /** Players the game rules operate on: everyone who has completed joining. */
73
+ private gamePlayers;
74
+ private createRegistry;
75
+ /** Adds or removes bots so the roster matches `settings.botCount`. */
76
+ private reconcileBots;
77
+ private botStrategy;
78
+ /**
79
+ * Drives every bot through the human action path.
80
+ *
81
+ * A bot never mutates game state directly: it produces the same payload a
82
+ * phone would send, and that payload goes through the same validation and the
83
+ * same `handleAction` call.
84
+ */
85
+ private tickBots;
86
+ private registerMessageHandlers;
87
+ /**
88
+ * Rejects payloads that are too large before any parsing work happens.
89
+ *
90
+ * Colyseus has already decoded the message by this point, so this is a guard
91
+ * against a client wasting the rules engine's time, not a transport-level
92
+ * defence - the transport's own frame limit handles that.
93
+ */
94
+ private checkPayload;
95
+ private handleSessionAction;
96
+ private applySettings;
97
+ private startGame;
98
+ private returnToLobby;
99
+ private setStatus;
100
+ /**
101
+ * Applies a status the game asked for, filtered by what the platform allows.
102
+ *
103
+ * The game may move between playing states, but it may not put the session
104
+ * back into the lobby or close it - those are platform decisions.
105
+ */
106
+ private applyRequestedStatus;
107
+ private buildContext;
108
+ /** Runs one validated action through the rules and settles the resulting tick. */
109
+ private applyGameAction;
110
+ private notifyGameOfPlayer;
111
+ /** Broadcasts queued events, applies status requests and republishes state. */
112
+ private finishTick;
113
+ private projectGameState;
114
+ private flushEvents;
115
+ private emitPlatformEvent;
116
+ private controllerMode;
117
+ private buildEnvelope;
118
+ /** Sends a controller its projection, skipping sends that would change nothing. */
119
+ private pushControllerState;
120
+ private pushAllControllerStates;
121
+ private sendWelcome;
122
+ private sendError;
123
+ private tick;
124
+ /**
125
+ * Reclaims sessions nobody is using.
126
+ *
127
+ * Two independent limits: an idle timeout that starts when the last client
128
+ * leaves, and an absolute age cap so a forgotten room on a TV in an empty
129
+ * office cannot live forever.
130
+ */
131
+ private checkExpiry;
132
+ private publishMetadata;
133
+ /**
134
+ * Developer-mode shortcuts.
135
+ *
136
+ * Reachable only when `ENABLE_DEV_TOOLS` is on *and* the build is not
137
+ * production, checked again at the call site. Platform commands are handled
138
+ * here; anything else is delegated to the game plugin.
139
+ */
140
+ private runDevCommand;
141
+ }
142
+ export {};
143
+ //# sourceMappingURL=PartySessionRoom.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PartySessionRoom.d.ts","sourceRoot":"","sources":["../src/PartySessionRoom.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,IAAI,EAA2B,KAAK,MAAM,EAAE,MAAM,gBAAgB,CAAC;AAU5E,OAAO,EAcL,KAAK,UAAU,EAMf,KAAK,aAAa,EAEnB,MAAM,sBAAsB,CAAC;AAW9B,OAAO,EAAgB,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAEjE,4EAA4E;AAC5E,MAAM,WAAW,iBAAiB;IAChC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,yEAAyE;IACzE,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,mFAAmF;AACnF,MAAM,WAAW,YAAY;IAC3B,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,aAAa,CAAC;IACtB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,UAAU,UAAU;IAClB,IAAI,EAAE,UAAU,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAcD,qBAAa,gBAAiB,SAAQ,IAAI,CAAC,aAAa,EAAE,YAAY,CAAC;IAC5D,UAAU,SAA4B;IAE/C,OAAO,CAAC,OAAO,CAAsB;IACrC,OAAO,CAAC,SAAS,CAAU;IAC3B,OAAO,CAAC,WAAW,CAAU;IAC7B,OAAO,CAAC,GAAG,CAAO;IAClB,OAAO,CAAC,QAAQ,CAAkB;IAElC,oEAAoE;IACpE,OAAO,CAAC,UAAU,CAA0B;IAC5C,kFAAkF;IAClF,OAAO,CAAC,eAAe,CAA8B;IAErD,6EAA6E;IAC7E,OAAO,CAAC,aAAa,CAA6D;IAClF,iEAAiE;IACjE,OAAO,CAAC,UAAU,CAAyD;IAE3E,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAuC;IACnE,OAAO,CAAC,QAAQ,CAAC,cAAc,CAA0C;IACzE,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAsC;IAEnE,OAAO,CAAC,SAAS,CAAK;IACtB,OAAO,CAAC,eAAe,CAAK;IAC5B,OAAO,CAAC,YAAY,CAAK;IACzB,OAAO,CAAC,QAAQ,CAAK;IACrB,OAAO,CAAC,kBAAkB,CAAK;IAC/B,+EAA+E;IAC/E,OAAO,CAAC,kBAAkB,CAA6B;IAEvD,OAAO,CAAC,MAAM,CAAU;IAIT,QAAQ,CAAC,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC;IAmDzD,MAAM,CAAC,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,OAAO,GAAG,UAAU;IAsBxD,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE,UAAU,GAAG,IAAI;IAgB3D,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IA6DhE,SAAS,IAAI,IAAI;IAU1B,0DAA0D;IAC1D,OAAO,CAAC,eAAe;IAkBvB,OAAO,CAAC,aAAa;IAKrB,OAAO,CAAC,cAAc;IAKtB,OAAO,CAAC,YAAY;IA0BpB,iFAAiF;IACjF,OAAO,CAAC,eAAe;IAWvB,6EAA6E;IAC7E,OAAO,CAAC,WAAW;IAMnB,OAAO,CAAC,cAAc;IA8BtB,sEAAsE;IACtE,OAAO,CAAC,aAAa;IAsCrB,OAAO,CAAC,WAAW;IAYnB;;;;;;OAMG;IACH,OAAO,CAAC,QAAQ;IA0BhB,OAAO,CAAC,uBAAuB;IAiE/B;;;;;;OAMG;IACH,OAAO,CAAC,YAAY;IAgBpB,OAAO,CAAC,mBAAmB;IA+F3B,OAAO,CAAC,aAAa;IAgCrB,OAAO,CAAC,SAAS;IAkCjB,OAAO,CAAC,aAAa;IAWrB,OAAO,CAAC,SAAS;IAOjB;;;;;OAKG;IACH,OAAO,CAAC,oBAAoB;IAkB5B,OAAO,CAAC,YAAY;IAgBpB,kFAAkF;IAClF,OAAO,CAAC,eAAe;IAiBvB,OAAO,CAAC,kBAAkB;IAkB1B,+EAA+E;IAC/E,OAAO,CAAC,UAAU;IAalB,OAAO,CAAC,gBAAgB;IAYxB,OAAO,CAAC,WAAW;IASnB,OAAO,CAAC,iBAAiB;IAMzB,OAAO,CAAC,cAAc;IAkBtB,OAAO,CAAC,aAAa;IA2BrB,mFAAmF;IACnF,OAAO,CAAC,mBAAmB;IAe3B,OAAO,CAAC,uBAAuB;IAM/B,OAAO,CAAC,WAAW;IAgBnB,OAAO,CAAC,SAAS;IAMjB,OAAO,CAAC,IAAI;IA0BZ;;;;;;OAMG;IACH,OAAO,CAAC,WAAW;YAiBL,eAAe;IAkB7B;;;;;;OAMG;IACH,OAAO,CAAC,aAAa;CA6BtB"}