@colyseus/core 0.17.49 → 0.17.50
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/build/MatchMaker.cjs +2 -2
- package/build/MatchMaker.cjs.map +2 -2
- package/build/MatchMaker.d.ts +10 -4
- package/build/MatchMaker.mjs +2 -2
- package/build/MatchMaker.mjs.map +2 -2
- package/build/Room.cjs +3 -2
- package/build/Room.cjs.map +2 -2
- package/build/Room.d.ts +1 -1
- package/build/Room.mjs +3 -2
- package/build/Room.mjs.map +2 -2
- package/build/utils/Utils.cjs.map +2 -2
- package/build/utils/Utils.d.ts +12 -0
- package/build/utils/Utils.mjs.map +2 -2
- package/build/utils/nanoevents.cjs +4 -1
- package/build/utils/nanoevents.cjs.map +2 -2
- package/build/utils/nanoevents.d.ts +3 -1
- package/build/utils/nanoevents.mjs +4 -1
- package/build/utils/nanoevents.mjs.map +2 -2
- package/package.json +7 -6
- package/src/MatchMaker.ts +33 -12
- package/src/Room.ts +3 -2
- package/src/utils/Utils.ts +18 -0
- package/src/utils/nanoevents.ts +4 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/utils/nanoevents.ts"],
|
|
4
|
-
"sourcesContent": ["export const createNanoEvents = () => ({\n emit(event: string, ...args: any[]) {\n for (\n let callbacks = this.events[event] || [],\n i = 0,\n length = callbacks.length;\n i < length;\n i++\n ) {\n callbacks[i](...args)\n }\n },\n events: {},\n on(event: string, cb: (...args: any[]) => void) {\n ;(this.events[event] ||= []).push(cb)\n return () => {\n this.events[event] = this.events[event]?.filter(i => cb !== i)\n }\n }\n })"],
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAO,IAAM,mBAAmB,OAAO;AAAA,EACnC,KAAK,UAAkB,MAAa;AAClC,aACM,YAAY,KAAK,OAAO,KAAK,KAAK,CAAC,GACrC,IAAI,GACJ,SAAS,UAAU,QACrB,IAAI,QACJ,KACA;AACA,gBAAU,CAAC,EAAE,GAAG,IAAI;AAAA,IACtB;AAAA,EACF;AAAA,
|
|
4
|
+
"sourcesContent": ["export const createNanoEvents = () => ({\n emit(event: string, ...args: any[]) {\n for (\n let callbacks = this.events[event] || [],\n i = 0,\n length = callbacks.length;\n i < length;\n i++\n ) {\n callbacks[i](...args)\n }\n },\n // null-prototype: event names are client-supplied (message types), and on a\n // plain object \"__proto__\" / \"constructor\" / \"toString\" resolve to inherited\n // members instead of missing (colyseus/colyseus#951)\n events: Object.create(null) as { [event: string]: Array<(...args: any[]) => void> },\n on(event: string, cb: (...args: any[]) => void) {\n ;(this.events[event] ||= []).push(cb)\n return () => {\n this.events[event] = this.events[event]?.filter(i => cb !== i)\n }\n }\n })"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAO,IAAM,mBAAmB,OAAO;AAAA,EACnC,KAAK,UAAkB,MAAa;AAClC,aACM,YAAY,KAAK,OAAO,KAAK,KAAK,CAAC,GACrC,IAAI,GACJ,SAAS,UAAU,QACrB,IAAI,QACJ,KACA;AACA,gBAAU,CAAC,EAAE,GAAG,IAAI;AAAA,IACtB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAIA,QAAQ,uBAAO,OAAO,IAAI;AAAA,EAC1B,GAAG,OAAe,IAA8B;AAC9C;AAAC,KAAC,KAAK,OAAO,KAAK,MAAM,CAAC,GAAG,KAAK,EAAE;AACpC,WAAO,MAAM;AACX,WAAK,OAAO,KAAK,IAAI,KAAK,OAAO,KAAK,GAAG,OAAO,OAAK,OAAO,CAAC;AAAA,IAC/D;AAAA,EACF;AACF;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -5,7 +5,10 @@ var createNanoEvents = () => ({
|
|
|
5
5
|
callbacks[i](...args);
|
|
6
6
|
}
|
|
7
7
|
},
|
|
8
|
-
|
|
8
|
+
// null-prototype: event names are client-supplied (message types), and on a
|
|
9
|
+
// plain object "__proto__" / "constructor" / "toString" resolve to inherited
|
|
10
|
+
// members instead of missing (colyseus/colyseus#951)
|
|
11
|
+
events: /* @__PURE__ */ Object.create(null),
|
|
9
12
|
on(event, cb) {
|
|
10
13
|
;
|
|
11
14
|
(this.events[event] ||= []).push(cb);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/utils/nanoevents.ts"],
|
|
4
|
-
"sourcesContent": ["export const createNanoEvents = () => ({\n emit(event: string, ...args: any[]) {\n for (\n let callbacks = this.events[event] || [],\n i = 0,\n length = callbacks.length;\n i < length;\n i++\n ) {\n callbacks[i](...args)\n }\n },\n events: {},\n on(event: string, cb: (...args: any[]) => void) {\n ;(this.events[event] ||= []).push(cb)\n return () => {\n this.events[event] = this.events[event]?.filter(i => cb !== i)\n }\n }\n })"],
|
|
5
|
-
"mappings": ";AAAO,IAAM,mBAAmB,OAAO;AAAA,EACnC,KAAK,UAAkB,MAAa;AAClC,aACM,YAAY,KAAK,OAAO,KAAK,KAAK,CAAC,GACrC,IAAI,GACJ,SAAS,UAAU,QACrB,IAAI,QACJ,KACA;AACA,gBAAU,CAAC,EAAE,GAAG,IAAI;AAAA,IACtB;AAAA,EACF;AAAA,
|
|
4
|
+
"sourcesContent": ["export const createNanoEvents = () => ({\n emit(event: string, ...args: any[]) {\n for (\n let callbacks = this.events[event] || [],\n i = 0,\n length = callbacks.length;\n i < length;\n i++\n ) {\n callbacks[i](...args)\n }\n },\n // null-prototype: event names are client-supplied (message types), and on a\n // plain object \"__proto__\" / \"constructor\" / \"toString\" resolve to inherited\n // members instead of missing (colyseus/colyseus#951)\n events: Object.create(null) as { [event: string]: Array<(...args: any[]) => void> },\n on(event: string, cb: (...args: any[]) => void) {\n ;(this.events[event] ||= []).push(cb)\n return () => {\n this.events[event] = this.events[event]?.filter(i => cb !== i)\n }\n }\n })"],
|
|
5
|
+
"mappings": ";AAAO,IAAM,mBAAmB,OAAO;AAAA,EACnC,KAAK,UAAkB,MAAa;AAClC,aACM,YAAY,KAAK,OAAO,KAAK,KAAK,CAAC,GACrC,IAAI,GACJ,SAAS,UAAU,QACrB,IAAI,QACJ,KACA;AACA,gBAAU,CAAC,EAAE,GAAG,IAAI;AAAA,IACtB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAIA,QAAQ,uBAAO,OAAO,IAAI;AAAA,EAC1B,GAAG,OAAe,IAA8B;AAC9C;AAAC,KAAC,KAAK,OAAO,KAAK,MAAM,CAAC,GAAG,KAAK,EAAE;AACpC,WAAO,MAAM;AACX,WAAK,OAAO,KAAK,IAAI,KAAK,OAAO,KAAK,GAAG,OAAO,OAAK,OAAO,CAAC;AAAA,IAC/D;AAAA,EACF;AACF;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@colyseus/core",
|
|
3
|
-
"version": "0.17.
|
|
3
|
+
"version": "0.17.50",
|
|
4
4
|
"description": "Multiplayer Framework for Node.js.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"input": "./src/index.ts",
|
|
@@ -52,15 +52,16 @@
|
|
|
52
52
|
"debug": "^4.3.4",
|
|
53
53
|
"nanoid": "^3.3.11",
|
|
54
54
|
"@colyseus/shared-types": "^0.17.6",
|
|
55
|
-
"@colyseus/
|
|
56
|
-
"@colyseus/
|
|
55
|
+
"@colyseus/better-call": "^1.3.1",
|
|
56
|
+
"@colyseus/greeting-banner": "^3.0.8"
|
|
57
57
|
},
|
|
58
58
|
"devDependencies": {
|
|
59
59
|
"@colyseus/schema": "^4.0.7",
|
|
60
60
|
"express": "^5.0.0",
|
|
61
|
+
"vitest": "^3.1.1",
|
|
62
|
+
"@colyseus/redis-presence": "^0.17.8",
|
|
61
63
|
"@colyseus/redis-driver": "^0.17.7",
|
|
62
|
-
"@colyseus/tools": "^0.17.20"
|
|
63
|
-
"@colyseus/redis-presence": "^0.17.8"
|
|
64
|
+
"@colyseus/tools": "^0.17.20"
|
|
64
65
|
},
|
|
65
66
|
"peerDependencies": {
|
|
66
67
|
"@colyseus/schema": "^4.0.7",
|
|
@@ -94,6 +95,6 @@
|
|
|
94
95
|
},
|
|
95
96
|
"gitHead": "c45b410e99eadffff4b74e701339992e2faa15f8",
|
|
96
97
|
"scripts": {
|
|
97
|
-
"test": "
|
|
98
|
+
"test": "vitest run"
|
|
98
99
|
}
|
|
99
100
|
}
|
package/src/MatchMaker.ts
CHANGED
|
@@ -2,7 +2,7 @@ import { EventEmitter } from 'events';
|
|
|
2
2
|
|
|
3
3
|
import { requestFromIPC, subscribeIPC, subscribeWithTimeout } from './IPC.ts';
|
|
4
4
|
|
|
5
|
-
import { type Type, Deferred, generateId, merge, retry, MAX_CONCURRENT_CREATE_ROOM_WAIT_TIME, REMOTE_ROOM_SHORT_TIMEOUT, type MethodName, type
|
|
5
|
+
import { type Type, Deferred, generateId, merge, retry, MAX_CONCURRENT_CREATE_ROOM_WAIT_TIME, REMOTE_ROOM_SHORT_TIMEOUT, type MethodName, type RemoteRoomCallReturn } from './utils/Utils.ts';
|
|
6
6
|
import { isDevMode, cacheRoomHistory, getPreviousProcessId, getRoomRestoreListKey, reloadFromCache } from './utils/DevMode.ts';
|
|
7
7
|
|
|
8
8
|
import { RegisteredHandler } from './matchmaker/RegisteredHandler.ts';
|
|
@@ -32,7 +32,8 @@ export { controller, stats, type MatchMakerDriver };
|
|
|
32
32
|
export type ClientOptions = any;
|
|
33
33
|
export type SelectProcessIdCallback = (roomName: string, clientOptions: ClientOptions) => Promise<string>;
|
|
34
34
|
|
|
35
|
-
|
|
35
|
+
// null-prototype: keyed by client-supplied room name (colyseus/colyseus#951)
|
|
36
|
+
const handlers: {[id: string]: RegisteredHandler} = Object.create(null);
|
|
36
37
|
const rooms: {[roomId: string]: Room} = {};
|
|
37
38
|
const events = new EventEmitter();
|
|
38
39
|
|
|
@@ -326,7 +327,7 @@ export async function query<T extends Room = any>(
|
|
|
326
327
|
*
|
|
327
328
|
* @param roomName - The Id of the specific room.
|
|
328
329
|
* @param filterOptions - Filter options.
|
|
329
|
-
* @param
|
|
330
|
+
* @param additionalSortOptions - Sorting options, merged over the ones declared on the room handler.
|
|
330
331
|
*
|
|
331
332
|
* @returns Promise<IRoomCache> - A promise contaning an object which includes room metadata and configurations.
|
|
332
333
|
*/
|
|
@@ -353,23 +354,43 @@ export async function findOneRoomAvailable(
|
|
|
353
354
|
/**
|
|
354
355
|
* Call a method or return a property on a remote room.
|
|
355
356
|
*
|
|
357
|
+
* Provide both type arguments for a precisely typed result, e.g.
|
|
358
|
+
* `remoteRoomCall<MyRoom, 'myMethod'>(roomId, 'myMethod')`. With only the
|
|
359
|
+
* room type given, TypeScript cannot infer the method literal
|
|
360
|
+
* (microsoft/TypeScript#26242) and the result is typed `any`.
|
|
361
|
+
*
|
|
356
362
|
* @param roomId - The Id of the specific room instance.
|
|
357
363
|
* @param method - Method or attribute to call or retrive.
|
|
358
364
|
* @param args - Array of arguments for the method
|
|
359
365
|
*
|
|
360
|
-
* @returns Promise
|
|
366
|
+
* @returns Promise - Returned value from the called or retrieved method/attribute.
|
|
361
367
|
*/
|
|
362
|
-
export
|
|
368
|
+
export function remoteRoomCall<TRoom = Room, TMethod extends keyof TRoom = keyof TRoom>(
|
|
369
|
+
roomId: string,
|
|
370
|
+
method: TMethod,
|
|
371
|
+
args?: any[],
|
|
372
|
+
rejectionTimeout?: number,
|
|
373
|
+
): Promise<RemoteRoomCallReturn<TRoom, TMethod>>;
|
|
374
|
+
|
|
375
|
+
// fallback for dynamic method names not present on the room type
|
|
376
|
+
export function remoteRoomCall<TRoom = Room>(
|
|
363
377
|
roomId: string,
|
|
364
378
|
method: keyof TRoom,
|
|
365
379
|
args?: any[],
|
|
380
|
+
rejectionTimeout?: number,
|
|
381
|
+
): Promise<any>;
|
|
382
|
+
|
|
383
|
+
export async function remoteRoomCall(
|
|
384
|
+
roomId: string,
|
|
385
|
+
method: any,
|
|
386
|
+
args?: any[],
|
|
366
387
|
rejectionTimeout = REMOTE_ROOM_SHORT_TIMEOUT,
|
|
367
|
-
): Promise<
|
|
368
|
-
const room = rooms[roomId]
|
|
388
|
+
): Promise<any> {
|
|
389
|
+
const room = rooms[roomId];
|
|
369
390
|
|
|
370
391
|
if (!room) {
|
|
371
392
|
try {
|
|
372
|
-
return await requestFromIPC(presence, getRoomChannel(roomId), method
|
|
393
|
+
return await requestFromIPC(presence, getRoomChannel(roomId), method, args, rejectionTimeout);
|
|
373
394
|
|
|
374
395
|
} catch (e: any) {
|
|
375
396
|
|
|
@@ -384,7 +405,7 @@ export async function remoteRoomCall<TRoom = Room>(
|
|
|
384
405
|
|
|
385
406
|
// TODO: for 1.0, consider always throwing previous error directly.
|
|
386
407
|
|
|
387
|
-
const request = `${
|
|
408
|
+
const request = `${method}${args && ' with args ' + JSON.stringify(args) || ''}`;
|
|
388
409
|
throw new ServerError(
|
|
389
410
|
ErrorCode.MATCHMAKE_UNHANDLED,
|
|
390
411
|
`remote room (${roomId}) timed out, requesting "${request}". (${rejectionTimeout}ms exceeded)`,
|
|
@@ -392,9 +413,9 @@ export async function remoteRoomCall<TRoom = Room>(
|
|
|
392
413
|
}
|
|
393
414
|
|
|
394
415
|
} else {
|
|
395
|
-
return (!args && typeof (room[method]) !== 'function')
|
|
396
|
-
? room
|
|
397
|
-
: (await room
|
|
416
|
+
return (!args && typeof ((room as any)[method]) !== 'function')
|
|
417
|
+
? (room as any)[method]
|
|
418
|
+
: (await (room as any)[method].apply(room, args && JSON.parse(JSON.stringify(args))));
|
|
398
419
|
}
|
|
399
420
|
}
|
|
400
421
|
|
package/src/Room.ts
CHANGED
|
@@ -255,7 +255,8 @@ export class Room<T extends RoomOptions = RoomOptions> {
|
|
|
255
255
|
public messages?: Messages<any>;
|
|
256
256
|
|
|
257
257
|
private onMessageEvents = createNanoEvents();
|
|
258
|
-
|
|
258
|
+
// null-prototype: keyed by client-supplied message type (colyseus/colyseus#951)
|
|
259
|
+
private onMessageValidators: {[message: string]: StandardSchemaV1} = Object.create(null);
|
|
259
260
|
|
|
260
261
|
private onMessageFallbacks = {
|
|
261
262
|
'__no_message_handler': (client: ExtractRoomClient<T>, messageType: string | number, _: unknown) => {
|
|
@@ -1308,7 +1309,7 @@ export class Room<T extends RoomOptions = RoomOptions> {
|
|
|
1308
1309
|
* Allow the specified client to reconnect into the room. Must be used inside `onLeave()` method.
|
|
1309
1310
|
* If seconds is provided, the reconnection is going to be cancelled after the provided amount of seconds.
|
|
1310
1311
|
*
|
|
1311
|
-
* @param
|
|
1312
|
+
* @param previousClient - The client that is allowed to reconnect into the room.
|
|
1312
1313
|
* @param seconds - The time in seconds that the client is allowed to reconnect into the room.
|
|
1313
1314
|
*
|
|
1314
1315
|
* @returns Deferred<Client> - The differed is a promise like type.
|
package/src/utils/Utils.ts
CHANGED
|
@@ -22,6 +22,24 @@ export type ExtractMethodOrPropertyType<
|
|
|
22
22
|
? Awaited<R>
|
|
23
23
|
: TClass[TKey];
|
|
24
24
|
|
|
25
|
+
/**
|
|
26
|
+
* Return type of `remoteRoomCall()`.
|
|
27
|
+
*
|
|
28
|
+
* Resolves to the method's awaited return type (or the property's type) when
|
|
29
|
+
* the method name was captured as a literal type. Falls back to `any` when it
|
|
30
|
+
* wasn't — e.g. `remoteRoomCall<MyRoom>(...)` with only the room type given:
|
|
31
|
+
* TypeScript applies the `TMethod` default instead of inferring the literal
|
|
32
|
+
* once an explicit type argument list is present (microsoft/TypeScript#26242).
|
|
33
|
+
* Pass both type arguments (`remoteRoomCall<MyRoom, 'myMethod'>`) for a
|
|
34
|
+
* precise return type.
|
|
35
|
+
*/
|
|
36
|
+
export type RemoteRoomCallReturn<
|
|
37
|
+
TRoom,
|
|
38
|
+
TMethod extends keyof TRoom
|
|
39
|
+
> = keyof TRoom extends TMethod
|
|
40
|
+
? any
|
|
41
|
+
: ExtractMethodOrPropertyType<TRoom, TMethod>;
|
|
42
|
+
|
|
25
43
|
// remote room call timeouts
|
|
26
44
|
export const REMOTE_ROOM_SHORT_TIMEOUT = Number(process.env.COLYSEUS_PRESENCE_SHORT_TIMEOUT || 2000);
|
|
27
45
|
export const MAX_CONCURRENT_CREATE_ROOM_WAIT_TIME = Number(process.env.COLYSEUS_MAX_CONCURRENT_CREATE_ROOM_WAIT_TIME || 0.5);
|
package/src/utils/nanoevents.ts
CHANGED
|
@@ -10,7 +10,10 @@ export const createNanoEvents = () => ({
|
|
|
10
10
|
callbacks[i](...args)
|
|
11
11
|
}
|
|
12
12
|
},
|
|
13
|
-
|
|
13
|
+
// null-prototype: event names are client-supplied (message types), and on a
|
|
14
|
+
// plain object "__proto__" / "constructor" / "toString" resolve to inherited
|
|
15
|
+
// members instead of missing (colyseus/colyseus#951)
|
|
16
|
+
events: Object.create(null) as { [event: string]: Array<(...args: any[]) => void> },
|
|
14
17
|
on(event: string, cb: (...args: any[]) => void) {
|
|
15
18
|
;(this.events[event] ||= []).push(cb)
|
|
16
19
|
return () => {
|