@colyseus/core 0.18.3 → 0.18.5
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/Debug.cjs +1 -0
- package/build/Debug.cjs.map +1 -1
- package/build/IPC.cjs +1 -0
- package/build/IPC.cjs.map +1 -1
- package/build/Logger.cjs +1 -0
- package/build/Logger.cjs.map +1 -1
- package/build/MatchMaker.cjs +13 -5
- package/build/MatchMaker.cjs.map +2 -2
- package/build/MatchMaker.d.ts +10 -4
- package/build/MatchMaker.mjs +12 -5
- package/build/MatchMaker.mjs.map +2 -2
- package/build/Protocol.cjs +1 -0
- package/build/Protocol.cjs.map +1 -1
- package/build/Rewind.cjs +1 -0
- package/build/Rewind.cjs.map +1 -1
- package/build/Room.cjs +113 -3
- package/build/Room.cjs.map +2 -2
- package/build/Room.d.ts +58 -1
- package/build/Room.mjs +112 -3
- package/build/Room.mjs.map +2 -2
- package/build/RoomMessages.cjs +3 -1
- package/build/RoomMessages.cjs.map +2 -2
- package/build/RoomMessages.d.ts +3 -1
- package/build/RoomMessages.mjs +2 -1
- package/build/RoomMessages.mjs.map +2 -2
- package/build/RoomPlugin.cjs +1 -0
- package/build/RoomPlugin.cjs.map +1 -1
- package/build/Server.cjs +1 -0
- package/build/Server.cjs.map +1 -1
- package/build/Stats.cjs +1 -0
- package/build/Stats.cjs.map +1 -1
- package/build/Transport.cjs +39 -0
- package/build/Transport.cjs.map +2 -2
- package/build/Transport.d.ts +66 -1
- package/build/Transport.mjs +37 -1
- package/build/Transport.mjs.map +2 -2
- package/build/errors/RoomExceptions.cjs +1 -0
- package/build/errors/RoomExceptions.cjs.map +1 -1
- package/build/errors/SeatReservationError.cjs +1 -0
- package/build/errors/SeatReservationError.cjs.map +1 -1
- package/build/errors/ServerError.cjs +1 -0
- package/build/errors/ServerError.cjs.map +1 -1
- package/build/index.cjs +5 -0
- package/build/index.cjs.map +2 -2
- package/build/index.d.ts +1 -1
- package/build/index.mjs +3 -1
- package/build/index.mjs.map +2 -2
- package/build/input/InputBuffer.cjs +1 -0
- package/build/input/InputBuffer.cjs.map +1 -1
- package/build/input/RoomInput.cjs +64 -3
- package/build/input/RoomInput.cjs.map +2 -2
- package/build/input/RoomInput.d.ts +16 -2
- package/build/input/RoomInput.mjs +63 -3
- package/build/input/RoomInput.mjs.map +2 -2
- package/build/input/types.cjs +1 -0
- package/build/input/types.cjs.map +1 -1
- package/build/internal.cjs +1 -0
- package/build/internal.cjs.map +1 -1
- package/build/matchmaker/Lobby.cjs +1 -0
- package/build/matchmaker/Lobby.cjs.map +1 -1
- package/build/matchmaker/LocalDriver/LocalDriver.cjs +1 -0
- package/build/matchmaker/LocalDriver/LocalDriver.cjs.map +1 -1
- package/build/matchmaker/LocalDriver/Query.cjs +1 -0
- package/build/matchmaker/LocalDriver/Query.cjs.map +1 -1
- package/build/matchmaker/RegisteredHandler.cjs +1 -0
- package/build/matchmaker/RegisteredHandler.cjs.map +1 -1
- package/build/matchmaker/controller.cjs +1 -0
- package/build/matchmaker/controller.cjs.map +1 -1
- package/build/matchmaker/driver.cjs +1 -0
- package/build/matchmaker/driver.cjs.map +2 -2
- package/build/matchmaker/driver.d.ts +4 -2
- package/build/matchmaker/driver.mjs.map +1 -1
- package/build/presence/LocalPresence.cjs +1 -0
- package/build/presence/LocalPresence.cjs.map +1 -1
- package/build/presence/Presence.cjs +1 -0
- package/build/presence/Presence.cjs.map +1 -1
- package/build/rooms/LobbyRoom.cjs +1 -0
- package/build/rooms/LobbyRoom.cjs.map +1 -1
- package/build/rooms/QueueRoom.cjs +1 -0
- package/build/rooms/QueueRoom.cjs.map +1 -1
- package/build/rooms/RelayRoom.cjs +1 -0
- package/build/rooms/RelayRoom.cjs.map +1 -1
- package/build/router/default_routes.cjs +4 -8
- package/build/router/default_routes.cjs.map +2 -2
- package/build/router/default_routes.mjs +4 -9
- package/build/router/default_routes.mjs.map +2 -2
- package/build/router/index.cjs +7 -1
- package/build/router/index.cjs.map +2 -2
- package/build/router/index.mjs +6 -1
- package/build/router/index.mjs.map +2 -2
- package/build/router/node.cjs +23 -2
- package/build/router/node.cjs.map +2 -2
- package/build/router/node.mjs +22 -2
- package/build/router/node.mjs.map +2 -2
- package/build/serializer/NoneSerializer.cjs +1 -0
- package/build/serializer/NoneSerializer.cjs.map +1 -1
- package/build/serializer/SchemaSerializer.cjs +98 -0
- package/build/serializer/SchemaSerializer.cjs.map +2 -2
- package/build/serializer/SchemaSerializer.d.ts +25 -0
- package/build/serializer/SchemaSerializer.mjs +98 -1
- package/build/serializer/SchemaSerializer.mjs.map +2 -2
- package/build/serializer/Serializer.cjs +1 -0
- package/build/serializer/Serializer.cjs.map +2 -2
- package/build/serializer/Serializer.d.ts +15 -0
- package/build/utils/DevMode.cjs +1 -0
- package/build/utils/DevMode.cjs.map +1 -1
- package/build/utils/Env.cjs +1 -0
- package/build/utils/Env.cjs.map +1 -1
- package/build/utils/StandardSchema.cjs +1 -0
- package/build/utils/StandardSchema.cjs.map +1 -1
- package/build/utils/UserSessionIndex.cjs +1 -0
- package/build/utils/UserSessionIndex.cjs.map +1 -1
- package/build/utils/Utils.cjs +1 -0
- 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 +5 -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 +8 -7
- package/src/MatchMaker.ts +53 -15
- package/src/Room.ts +145 -4
- package/src/RoomMessages.ts +2 -1
- package/src/Transport.ts +132 -4
- package/src/index.ts +1 -1
- package/src/input/RoomInput.ts +76 -3
- package/src/matchmaker/driver.ts +4 -2
- package/src/router/default_routes.ts +4 -9
- package/src/router/index.ts +7 -0
- package/src/router/node.ts +26 -2
- package/src/serializer/SchemaSerializer.ts +146 -1
- package/src/serializer/Serializer.ts +17 -0
- package/src/utils/Utils.ts +18 -0
- package/src/utils/nanoevents.ts +4 -1
package/build/Room.cjs
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
const __cjsImportMetaUrl = require('node:url').pathToFileURL(__filename).href;
|
|
1
2
|
"use strict";
|
|
2
3
|
var __create = Object.create;
|
|
3
4
|
var __defProp = Object.defineProperty;
|
|
@@ -64,6 +65,8 @@ var import_RoomPlugin = require("./RoomPlugin.cjs");
|
|
|
64
65
|
var import_RoomPlugin2 = require("./RoomPlugin.cjs");
|
|
65
66
|
var DEFAULT_PATCH_RATE = 1e3 / 20;
|
|
66
67
|
var DEFAULT_SIMULATION_INTERVAL = 1e3 / 60;
|
|
68
|
+
var NOOP = () => {
|
|
69
|
+
};
|
|
67
70
|
var noneSerializer = new import_NoneSerializer.NoneSerializer();
|
|
68
71
|
var AFTER_PATCH_OPTS = Object.freeze({ afterNextPatch: true });
|
|
69
72
|
var DEFAULT_SEAT_RESERVATION_TIME = Number(process.env.COLYSEUS_SEAT_RESERVATION_TIME || 15);
|
|
@@ -103,6 +106,42 @@ var Room = class _Room {
|
|
|
103
106
|
* @default 50ms (20fps)
|
|
104
107
|
*/
|
|
105
108
|
this.patchRate = DEFAULT_PATCH_RATE;
|
|
109
|
+
/**
|
|
110
|
+
* Frequency to flush `@unreliable` state fields, in milliseconds.
|
|
111
|
+
*
|
|
112
|
+
* Those fields never ride a state patch — they go out over the transport's
|
|
113
|
+
* unreliable channel (a WebTransport datagram), so a dropped frame costs one
|
|
114
|
+
* stale value instead of stalling the reliable stream behind a retransmit.
|
|
115
|
+
* Setting this decouples them from {@link patchRate}, which is the point:
|
|
116
|
+
* 60Hz movement over a 20Hz structural patch.
|
|
117
|
+
*
|
|
118
|
+
* KNOWN COST of a rate faster than {@link patchRate}: an entity's ADD travels
|
|
119
|
+
* the reliable channel, so datagrams sent between patches can reference a
|
|
120
|
+
* refId the client hasn't been told about yet. Those frames are skipped by the
|
|
121
|
+
* client's decoder — safe (the ref graph can't desync, since `@unreliable` is
|
|
122
|
+
* primitives-only) but each one logs `"refId" not found`, and that entity's
|
|
123
|
+
* first value lands one mutation later. Measured at `patchRate/this` reports
|
|
124
|
+
* per mid-session spawn. Leave this unset and the flush rides
|
|
125
|
+
* {@link broadcastPatch}, which ships the ADD first and avoids it entirely.
|
|
126
|
+
*
|
|
127
|
+
* Requires a transport with a datagram channel — today only
|
|
128
|
+
* `@colyseus/h3-transport` (WebTransport), which is **experimental**. Every
|
|
129
|
+
* WebSocket transport lacks one, and those clients are skipped entirely (the
|
|
130
|
+
* room warns once), so `@unreliable` fields keep their join-time value there.
|
|
131
|
+
*
|
|
132
|
+
* @default null — flush alongside every {@link broadcastPatch}, and only when
|
|
133
|
+
* the state actually declares an `@unreliable` field.
|
|
134
|
+
*/
|
|
135
|
+
this.unreliablePatchRate = null;
|
|
136
|
+
this.#_unreliablePatchRate = null;
|
|
137
|
+
/**
|
|
138
|
+
* The unreliable flush, called unconditionally at the end of every
|
|
139
|
+
* {@link broadcastPatch}. Stays {@link NOOP} unless the state actually
|
|
140
|
+
* declares an `@unreliable` field, so a room that never uses the channel
|
|
141
|
+
* pays an empty call the engine inlines away — and there is no second
|
|
142
|
+
* entry point that could drift from `broadcastPatch()`.
|
|
143
|
+
*/
|
|
144
|
+
this._flushUnreliable = NOOP;
|
|
106
145
|
/**
|
|
107
146
|
* Maximum number of messages a client can send to the server per second.
|
|
108
147
|
* If a client sends more messages than this, it will be disconnected.
|
|
@@ -197,6 +236,8 @@ var Room = class _Room {
|
|
|
197
236
|
#_autoDispose;
|
|
198
237
|
#_patchRate;
|
|
199
238
|
#_patchInterval;
|
|
239
|
+
#_unreliablePatchRate;
|
|
240
|
+
#_unreliablePatchInterval;
|
|
200
241
|
#_state;
|
|
201
242
|
#_messages;
|
|
202
243
|
// Re-expose the registry for @colyseus/playground introspection and
|
|
@@ -218,6 +259,7 @@ var Room = class _Room {
|
|
|
218
259
|
this.#_state = this.state;
|
|
219
260
|
this.#_autoDispose = this.autoDispose;
|
|
220
261
|
this.#_patchRate = this.patchRate;
|
|
262
|
+
this.#_unreliablePatchRate = this.unreliablePatchRate;
|
|
221
263
|
this.#_maxClients = this.maxClients;
|
|
222
264
|
Object.defineProperties(this, {
|
|
223
265
|
state: {
|
|
@@ -233,6 +275,7 @@ var Room = class _Room {
|
|
|
233
275
|
}
|
|
234
276
|
this._serializer.reset(newState);
|
|
235
277
|
this.#_state = newState;
|
|
278
|
+
this._armUnreliablePatches();
|
|
236
279
|
}
|
|
237
280
|
},
|
|
238
281
|
maxClients: {
|
|
@@ -267,6 +310,14 @@ var Room = class _Room {
|
|
|
267
310
|
this.#_patchInterval = setInterval(() => this.clock.tick(), DEFAULT_SIMULATION_INTERVAL);
|
|
268
311
|
}
|
|
269
312
|
}
|
|
313
|
+
},
|
|
314
|
+
unreliablePatchRate: {
|
|
315
|
+
enumerable: true,
|
|
316
|
+
get: () => this.#_unreliablePatchRate,
|
|
317
|
+
set: (milliseconds) => {
|
|
318
|
+
this.#_unreliablePatchRate = milliseconds;
|
|
319
|
+
this._armUnreliablePatches();
|
|
320
|
+
}
|
|
270
321
|
}
|
|
271
322
|
});
|
|
272
323
|
this.patchRate = this.#_patchRate;
|
|
@@ -826,6 +877,7 @@ var Room = class _Room {
|
|
|
826
877
|
this.state,
|
|
827
878
|
this._inputController !== void 0 ? { sNow } : void 0
|
|
828
879
|
);
|
|
880
|
+
this._flushUnreliable();
|
|
829
881
|
this._flushPendingClientFrames();
|
|
830
882
|
this._flushAfterPatchBroadcasts();
|
|
831
883
|
const rw = this.#rewind;
|
|
@@ -834,6 +886,52 @@ var Room = class _Room {
|
|
|
834
886
|
}
|
|
835
887
|
return hasChanges;
|
|
836
888
|
}
|
|
889
|
+
/**
|
|
890
|
+
* Encode and send the `@unreliable` state fields over each client's
|
|
891
|
+
* unreliable channel. Those fields never appear in a {@link broadcastPatch}
|
|
892
|
+
* frame, and clients on a transport without a datagram channel are skipped.
|
|
893
|
+
*
|
|
894
|
+
* Driven automatically once the state declares an `@unreliable` field — right
|
|
895
|
+
* after each {@link broadcastPatch}, or on its own timer when
|
|
896
|
+
* {@link unreliablePatchRate} is set. Public so a room driving
|
|
897
|
+
* `broadcastPatch()` by hand can drive this by hand too.
|
|
898
|
+
*/
|
|
899
|
+
broadcastUnreliablePatch() {
|
|
900
|
+
if (!this.state) {
|
|
901
|
+
return false;
|
|
902
|
+
}
|
|
903
|
+
return this._serializer.applyUnreliablePatches?.(this.clients) ?? false;
|
|
904
|
+
}
|
|
905
|
+
/**
|
|
906
|
+
* Decide how the unreliable channel is driven — and, for the rooms that never
|
|
907
|
+
* touch it, decide to not drive it at all. Runs when the state is assigned
|
|
908
|
+
* (the serializer knows by then whether any `@unreliable` field exists) and
|
|
909
|
+
* whenever {@link unreliablePatchRate} changes.
|
|
910
|
+
*
|
|
911
|
+
* A room whose state declares no `@unreliable` field leaves
|
|
912
|
+
* {@link _flushUnreliable} at {@link NOOP}, so its patch tick costs exactly
|
|
913
|
+
* what it did before this feature existed.
|
|
914
|
+
*/
|
|
915
|
+
_armUnreliablePatches() {
|
|
916
|
+
if (this.#_unreliablePatchInterval) {
|
|
917
|
+
clearInterval(this.#_unreliablePatchInterval);
|
|
918
|
+
this.#_unreliablePatchInterval = void 0;
|
|
919
|
+
}
|
|
920
|
+
const armed = this._serializer?.hasUnreliableFields === true;
|
|
921
|
+
const rate = this.#_unreliablePatchRate;
|
|
922
|
+
const dedicated = armed && rate !== null && rate !== 0;
|
|
923
|
+
const inline = armed && !dedicated;
|
|
924
|
+
this._flushUnreliable = inline ? () => {
|
|
925
|
+
this.broadcastUnreliablePatch();
|
|
926
|
+
} : NOOP;
|
|
927
|
+
if (dedicated) {
|
|
928
|
+
this.#_unreliablePatchInterval = setInterval(() => this.broadcastUnreliablePatch(), rate);
|
|
929
|
+
} else if (inline && !this.#_patchRate) {
|
|
930
|
+
import_Logger.logger.warn(
|
|
931
|
+
"@colyseus/core: state has @unreliable fields but patchRate is disabled \u2014 set `room.unreliablePatchRate` to flush them, or they will never update."
|
|
932
|
+
);
|
|
933
|
+
}
|
|
934
|
+
}
|
|
837
935
|
onMessage(_messageType, _validationSchema, _callback) {
|
|
838
936
|
return this.#_messages.on(_messageType, _validationSchema, _callback);
|
|
839
937
|
}
|
|
@@ -1093,7 +1191,7 @@ var Room = class _Room {
|
|
|
1093
1191
|
* Allow the specified client to reconnect into the room. Must be used inside `onLeave()` method.
|
|
1094
1192
|
* If seconds is provided, the reconnection is going to be cancelled after the provided amount of seconds.
|
|
1095
1193
|
*
|
|
1096
|
-
* @param
|
|
1194
|
+
* @param previousClient - The client that is allowed to reconnect into the room.
|
|
1097
1195
|
* @param seconds - The time in seconds that the client is allowed to reconnect into the room.
|
|
1098
1196
|
*
|
|
1099
1197
|
* @returns Deferred<Client> - The differed is a promise like type.
|
|
@@ -1300,6 +1398,10 @@ var Room = class _Room {
|
|
|
1300
1398
|
clearInterval(this.#_patchInterval);
|
|
1301
1399
|
this.#_patchInterval = void 0;
|
|
1302
1400
|
}
|
|
1401
|
+
if (this.#_unreliablePatchInterval) {
|
|
1402
|
+
clearInterval(this.#_unreliablePatchInterval);
|
|
1403
|
+
this.#_unreliablePatchInterval = void 0;
|
|
1404
|
+
}
|
|
1303
1405
|
if (this._simulationInterval) {
|
|
1304
1406
|
clearInterval(this._simulationInterval);
|
|
1305
1407
|
this._simulationInterval = void 0;
|
|
@@ -1360,7 +1462,12 @@ var Room = class _Room {
|
|
|
1360
1462
|
#_forciblyCloseClient(client, closeCode, reason) {
|
|
1361
1463
|
client.ref.removeAllListeners("message");
|
|
1362
1464
|
client.ref.removeListener("close", client.ref["onleave"]);
|
|
1363
|
-
|
|
1465
|
+
const ref = client.ref;
|
|
1466
|
+
this._onLeave(client, closeCode).then(() => {
|
|
1467
|
+
if (client.ref === ref) {
|
|
1468
|
+
client.leave(closeCode, reason);
|
|
1469
|
+
}
|
|
1470
|
+
});
|
|
1364
1471
|
}
|
|
1365
1472
|
async _onLeave(client, code) {
|
|
1366
1473
|
const method = code === import_shared_types.CloseCode.CONSENTED || client.state === import_Transport.ClientState.RECONNECTING ? this.onLeave : this.onDrop || this.onLeave;
|
|
@@ -1381,11 +1488,14 @@ var Room = class _Room {
|
|
|
1381
1488
|
this.#_onLeaveConcurrent--;
|
|
1382
1489
|
}
|
|
1383
1490
|
}
|
|
1491
|
+
if (client.state === import_Transport.ClientState.RECONNECTED) {
|
|
1492
|
+
return;
|
|
1493
|
+
}
|
|
1384
1494
|
if (this._reconnections[client.reconnectionToken]) {
|
|
1385
1495
|
this._reconnections[client.reconnectionToken][1].catch(async () => {
|
|
1386
1496
|
await this.#_onAfterLeave(client, code, method === this.onDrop);
|
|
1387
1497
|
});
|
|
1388
|
-
} else
|
|
1498
|
+
} else {
|
|
1389
1499
|
await this.#_onAfterLeave(client, code, method === this.onDrop);
|
|
1390
1500
|
}
|
|
1391
1501
|
}
|