@bloopjs/web 0.0.88 → 0.0.89
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/dist/App.d.ts.map +1 -1
- package/dist/mod.js +319 -247
- package/dist/mod.js.map +8 -8
- package/dist/netcode/mod.d.ts +0 -2
- package/dist/netcode/mod.d.ts.map +1 -1
- package/dist/netcode/reconcile.d.ts +3 -0
- package/dist/netcode/reconcile.d.ts.map +1 -0
- package/package.json +3 -3
- package/src/App.ts +8 -0
- package/src/netcode/mod.ts +0 -2
- package/src/netcode/reconcile.ts +171 -0
- package/dist/netcode/scaffold.d.ts +0 -13
- package/dist/netcode/scaffold.d.ts.map +0 -1
- package/src/netcode/scaffold.ts +0 -168
package/dist/mod.js
CHANGED
|
@@ -82,16 +82,21 @@ __export2(exports_engine, {
|
|
|
82
82
|
SNAPSHOT_HEADER_ENGINE_LEN_OFFSET: () => SNAPSHOT_HEADER_ENGINE_LEN_OFFSET,
|
|
83
83
|
PlayerInputContext: () => PlayerInputContext,
|
|
84
84
|
PLAYER_INPUTS_SIZE: () => PLAYER_INPUTS_SIZE,
|
|
85
|
+
PLAYER_INPUTS_MOUSE_CTX_OFFSET: () => PLAYER_INPUTS_MOUSE_CTX_OFFSET,
|
|
86
|
+
PLAYER_INPUTS_KEY_CTX_OFFSET: () => PLAYER_INPUTS_KEY_CTX_OFFSET,
|
|
85
87
|
NetContext: () => NetContext,
|
|
86
88
|
NET_CTX_OFFSET: () => NET_CTX_OFFSET,
|
|
87
89
|
MouseContext: () => MouseContext,
|
|
88
|
-
MOUSE_OFFSET: () =>
|
|
89
|
-
|
|
90
|
+
MOUSE_OFFSET: () => PLAYER_INPUTS_MOUSE_CTX_OFFSET,
|
|
91
|
+
MOUSE_CTX_SIZE: () => MOUSE_CTX_SIZE,
|
|
92
|
+
MOUSE_CTX_BUTTON_STATES_OFFSET: () => MOUSE_CTX_BUTTON_STATES_OFFSET,
|
|
93
|
+
MOUSE_BUTTONS_OFFSET: () => MOUSE_CTX_BUTTON_STATES_OFFSET,
|
|
90
94
|
MAX_ROLLBACK_FRAMES: () => MAX_ROLLBACK_FRAMES,
|
|
91
95
|
MAX_PLAYERS: () => MAX_PLAYERS,
|
|
92
96
|
KeyboardContext: () => KeyboardContext,
|
|
93
|
-
|
|
94
|
-
|
|
97
|
+
KEY_CTX_SIZE: () => KEY_CTX_SIZE,
|
|
98
|
+
KEYBOARD_SIZE: () => KEY_CTX_SIZE,
|
|
99
|
+
KEYBOARD_OFFSET: () => PLAYER_INPUTS_KEY_CTX_OFFSET,
|
|
95
100
|
InputContext: () => InputContext,
|
|
96
101
|
INPUT_CTX_SIZE: () => INPUT_CTX_SIZE,
|
|
97
102
|
INPUT_CTX_OFFSET: () => INPUT_CTX_OFFSET,
|
|
@@ -387,33 +392,38 @@ var NetJoinFailReason;
|
|
|
387
392
|
NetJoinFailReason2[NetJoinFailReason2["room_not_found"] = 3] = "room_not_found";
|
|
388
393
|
NetJoinFailReason2[NetJoinFailReason2["already_in_room"] = 4] = "already_in_room";
|
|
389
394
|
})(NetJoinFailReason ||= {});
|
|
390
|
-
var
|
|
391
|
-
var
|
|
392
|
-
var
|
|
393
|
-
var
|
|
394
|
-
var
|
|
395
|
+
var TIME_CTX_FRAME_OFFSET = 0;
|
|
396
|
+
var TIME_CTX_DT_MS_OFFSET = 4;
|
|
397
|
+
var TIME_CTX_TOTAL_MS_OFFSET = 8;
|
|
398
|
+
var PEER_CTX_CONNECTED_OFFSET = 0;
|
|
399
|
+
var PEER_CTX_SEQ_OFFSET = 2;
|
|
400
|
+
var PEER_CTX_ACK_OFFSET = 4;
|
|
401
|
+
var PEER_CTX_SIZE = 8;
|
|
402
|
+
var NET_CTX_PEER_COUNT_OFFSET = 0;
|
|
403
|
+
var NET_CTX_LOCAL_PEER_ID_OFFSET = 1;
|
|
404
|
+
var NET_CTX_IN_SESSION_OFFSET = 2;
|
|
405
|
+
var NET_CTX_STATUS_OFFSET = 3;
|
|
406
|
+
var NET_CTX_MATCH_FRAME_OFFSET = 4;
|
|
407
|
+
var NET_CTX_SESSION_START_FRAME_OFFSET = 8;
|
|
408
|
+
var NET_CTX_ROOM_CODE_OFFSET = 12;
|
|
409
|
+
var NET_CTX_WANTS_ROOM_CODE_OFFSET = 20;
|
|
410
|
+
var NET_CTX_WANTS_DISCONNECT_OFFSET = 28;
|
|
411
|
+
var NET_CTX_PEERS_OFFSET = 32;
|
|
412
|
+
var NET_CTX_LAST_ROLLBACK_DEPTH_OFFSET = 128;
|
|
413
|
+
var NET_CTX_TOTAL_ROLLBACKS_OFFSET = 132;
|
|
414
|
+
var NET_CTX_FRAMES_RESIMULATED_OFFSET = 136;
|
|
415
|
+
var MOUSE_CTX_X_OFFSET = 0;
|
|
416
|
+
var MOUSE_CTX_Y_OFFSET = 4;
|
|
417
|
+
var MOUSE_CTX_WHEEL_X_OFFSET = 8;
|
|
418
|
+
var MOUSE_CTX_WHEEL_Y_OFFSET = 12;
|
|
419
|
+
var MOUSE_CTX_BUTTON_STATES_OFFSET = 16;
|
|
420
|
+
var MOUSE_CTX_SIZE = 24;
|
|
421
|
+
var KEY_CTX_SIZE = 256;
|
|
422
|
+
var PLAYER_INPUTS_KEY_CTX_OFFSET = 0;
|
|
423
|
+
var PLAYER_INPUTS_MOUSE_CTX_OFFSET = 256;
|
|
395
424
|
var PLAYER_INPUTS_SIZE = 280;
|
|
396
|
-
var INPUT_CTX_SIZE =
|
|
397
|
-
var
|
|
398
|
-
var EVENT_PAYLOAD_ALIGN = 4;
|
|
399
|
-
function keyToKeyCode(key) {
|
|
400
|
-
return Key[key];
|
|
401
|
-
}
|
|
402
|
-
function keyCodeToKey(code) {
|
|
403
|
-
return Key[code];
|
|
404
|
-
}
|
|
405
|
-
function mouseButtonToMouseButtonCode(button) {
|
|
406
|
-
return MouseButton[button];
|
|
407
|
-
}
|
|
408
|
-
function mouseButtonCodeToMouseButton(code) {
|
|
409
|
-
return MouseButton[code];
|
|
410
|
-
}
|
|
411
|
-
function inputSourceToInputSourceCode(source) {
|
|
412
|
-
return InputSource[source];
|
|
413
|
-
}
|
|
414
|
-
function inputSourceCodeToInputSource(code) {
|
|
415
|
-
return InputSource[code];
|
|
416
|
-
}
|
|
425
|
+
var INPUT_CTX_SIZE = 3360;
|
|
426
|
+
var MAX_PLAYERS = 12;
|
|
417
427
|
|
|
418
428
|
class PlayerInputContext {
|
|
419
429
|
#dataView;
|
|
@@ -424,13 +434,13 @@ class PlayerInputContext {
|
|
|
424
434
|
}
|
|
425
435
|
get keys() {
|
|
426
436
|
if (!this.#keys) {
|
|
427
|
-
this.#keys = new KeyboardContext(new DataView(this.#dataView.buffer, this.#dataView.byteOffset +
|
|
437
|
+
this.#keys = new KeyboardContext(new DataView(this.#dataView.buffer, this.#dataView.byteOffset + PLAYER_INPUTS_KEY_CTX_OFFSET));
|
|
428
438
|
}
|
|
429
439
|
return this.#keys;
|
|
430
440
|
}
|
|
431
441
|
get mouse() {
|
|
432
442
|
if (!this.#mouse) {
|
|
433
|
-
this.#mouse = new MouseContext(new DataView(this.#dataView.buffer, this.#dataView.byteOffset +
|
|
443
|
+
this.#mouse = new MouseContext(new DataView(this.#dataView.buffer, this.#dataView.byteOffset + PLAYER_INPUTS_MOUSE_CTX_OFFSET));
|
|
434
444
|
}
|
|
435
445
|
return this.#mouse;
|
|
436
446
|
}
|
|
@@ -455,6 +465,9 @@ class InputContext {
|
|
|
455
465
|
this.#dataView = dataView;
|
|
456
466
|
this.#buildPlayers();
|
|
457
467
|
}
|
|
468
|
+
hasDataView() {
|
|
469
|
+
return !!this.#dataView;
|
|
470
|
+
}
|
|
458
471
|
#buildPlayers() {
|
|
459
472
|
this.#players = [];
|
|
460
473
|
for (let i = 0;i < MAX_PLAYERS; i++) {
|
|
@@ -487,19 +500,19 @@ class MouseContext {
|
|
|
487
500
|
this.#dataView = dataView;
|
|
488
501
|
}
|
|
489
502
|
get x() {
|
|
490
|
-
return this.#dataView.getFloat32(
|
|
503
|
+
return this.#dataView.getFloat32(MOUSE_CTX_X_OFFSET, true);
|
|
491
504
|
}
|
|
492
505
|
get y() {
|
|
493
|
-
return this.#dataView.getFloat32(
|
|
506
|
+
return this.#dataView.getFloat32(MOUSE_CTX_Y_OFFSET, true);
|
|
494
507
|
}
|
|
495
508
|
get wheel() {
|
|
496
509
|
return { x: this.wheelX, y: this.wheelY };
|
|
497
510
|
}
|
|
498
511
|
get wheelX() {
|
|
499
|
-
return this.#dataView.getFloat32(
|
|
512
|
+
return this.#dataView.getFloat32(MOUSE_CTX_WHEEL_X_OFFSET, true);
|
|
500
513
|
}
|
|
501
514
|
get wheelY() {
|
|
502
|
-
return this.#dataView.getFloat32(
|
|
515
|
+
return this.#dataView.getFloat32(MOUSE_CTX_WHEEL_Y_OFFSET, true);
|
|
503
516
|
}
|
|
504
517
|
get left() {
|
|
505
518
|
return this.#buttonState(1);
|
|
@@ -518,7 +531,7 @@ class MouseContext {
|
|
|
518
531
|
state = { down: false, held: false, up: false };
|
|
519
532
|
this.#buttonStates.set(code, state);
|
|
520
533
|
}
|
|
521
|
-
const offset =
|
|
534
|
+
const offset = MOUSE_CTX_BUTTON_STATES_OFFSET;
|
|
522
535
|
state.held = !!(this.#dataView.getUint8(offset + code) & 1);
|
|
523
536
|
state.down = state.held && !(this.#dataView.getUint8(offset + code) & 2);
|
|
524
537
|
state.up = !state.held && !!(this.#dataView.getUint8(offset + code) & 2);
|
|
@@ -1140,15 +1153,6 @@ class KeyboardContext {
|
|
|
1140
1153
|
return state;
|
|
1141
1154
|
}
|
|
1142
1155
|
}
|
|
1143
|
-
var MAX_PEERS = 12;
|
|
1144
|
-
var PEERS_ARRAY_OFFSET = 32;
|
|
1145
|
-
var PEER_CTX_SIZE = 8;
|
|
1146
|
-
var LAST_ROLLBACK_DEPTH_OFFSET = 128;
|
|
1147
|
-
var TOTAL_ROLLBACKS_OFFSET = 132;
|
|
1148
|
-
var FRAMES_RESIMULATED_OFFSET = 136;
|
|
1149
|
-
var PEER_CONNECTED_OFFSET = 0;
|
|
1150
|
-
var PEER_SEQ_OFFSET = 2;
|
|
1151
|
-
var PEER_ACK_OFFSET = 4;
|
|
1152
1156
|
var STATUS_MAP = {
|
|
1153
1157
|
0: "offline",
|
|
1154
1158
|
1: "local",
|
|
@@ -1159,7 +1163,7 @@ var STATUS_MAP = {
|
|
|
1159
1163
|
|
|
1160
1164
|
class NetContext {
|
|
1161
1165
|
dataView;
|
|
1162
|
-
#peers = Array.from({ length:
|
|
1166
|
+
#peers = Array.from({ length: MAX_PLAYERS }, () => ({
|
|
1163
1167
|
isLocal: false,
|
|
1164
1168
|
seq: -1,
|
|
1165
1169
|
ack: -1
|
|
@@ -1177,38 +1181,38 @@ class NetContext {
|
|
|
1177
1181
|
if (!this.#hasValidBuffer()) {
|
|
1178
1182
|
throw new Error("NetContext dataView is not valid");
|
|
1179
1183
|
}
|
|
1180
|
-
return this.dataView.getUint8(
|
|
1184
|
+
return this.dataView.getUint8(NET_CTX_PEER_COUNT_OFFSET);
|
|
1181
1185
|
}
|
|
1182
1186
|
get localPeerId() {
|
|
1183
1187
|
if (!this.#hasValidBuffer()) {
|
|
1184
1188
|
throw new Error("NetContext dataView is not valid");
|
|
1185
1189
|
}
|
|
1186
|
-
return this.dataView.getUint8(
|
|
1190
|
+
return this.dataView.getUint8(NET_CTX_LOCAL_PEER_ID_OFFSET);
|
|
1187
1191
|
}
|
|
1188
1192
|
get isInSession() {
|
|
1189
1193
|
if (!this.#hasValidBuffer()) {
|
|
1190
1194
|
throw new Error("NetContext dataView is not valid");
|
|
1191
1195
|
}
|
|
1192
|
-
return this.dataView.getUint8(
|
|
1196
|
+
return this.dataView.getUint8(NET_CTX_IN_SESSION_OFFSET) !== 0;
|
|
1193
1197
|
}
|
|
1194
1198
|
get status() {
|
|
1195
1199
|
if (!this.#hasValidBuffer()) {
|
|
1196
1200
|
throw new Error("NetContext dataView is not valid");
|
|
1197
1201
|
}
|
|
1198
|
-
const statusByte = this.dataView.getUint8(
|
|
1202
|
+
const statusByte = this.dataView.getUint8(NET_CTX_STATUS_OFFSET);
|
|
1199
1203
|
return STATUS_MAP[statusByte] ?? "local";
|
|
1200
1204
|
}
|
|
1201
1205
|
get matchFrame() {
|
|
1202
1206
|
if (!this.#hasValidBuffer()) {
|
|
1203
1207
|
throw new Error("NetContext dataView is not valid");
|
|
1204
1208
|
}
|
|
1205
|
-
return this.dataView.getUint32(
|
|
1209
|
+
return this.dataView.getUint32(NET_CTX_MATCH_FRAME_OFFSET, true);
|
|
1206
1210
|
}
|
|
1207
1211
|
get sessionStartFrame() {
|
|
1208
1212
|
if (!this.#hasValidBuffer()) {
|
|
1209
1213
|
throw new Error("NetContext dataView is not valid");
|
|
1210
1214
|
}
|
|
1211
|
-
return this.dataView.getUint32(
|
|
1215
|
+
return this.dataView.getUint32(NET_CTX_SESSION_START_FRAME_OFFSET, true);
|
|
1212
1216
|
}
|
|
1213
1217
|
get roomCode() {
|
|
1214
1218
|
if (!this.#hasValidBuffer()) {
|
|
@@ -1216,7 +1220,7 @@ class NetContext {
|
|
|
1216
1220
|
}
|
|
1217
1221
|
const bytes = [];
|
|
1218
1222
|
for (let i = 0;i < 8; i++) {
|
|
1219
|
-
const byte = this.dataView.getUint8(
|
|
1223
|
+
const byte = this.dataView.getUint8(NET_CTX_ROOM_CODE_OFFSET + i);
|
|
1220
1224
|
if (byte === 0)
|
|
1221
1225
|
break;
|
|
1222
1226
|
bytes.push(byte);
|
|
@@ -1229,7 +1233,7 @@ class NetContext {
|
|
|
1229
1233
|
}
|
|
1230
1234
|
const bytes = [];
|
|
1231
1235
|
for (let i = 0;i < 8; i++) {
|
|
1232
|
-
const byte = this.dataView.getUint8(
|
|
1236
|
+
const byte = this.dataView.getUint8(NET_CTX_WANTS_ROOM_CODE_OFFSET + i);
|
|
1233
1237
|
if (byte === 0)
|
|
1234
1238
|
break;
|
|
1235
1239
|
bytes.push(byte);
|
|
@@ -1241,11 +1245,11 @@ class NetContext {
|
|
|
1241
1245
|
throw new Error("NetContext dataView is not valid");
|
|
1242
1246
|
}
|
|
1243
1247
|
for (let i = 0;i < 8; i++) {
|
|
1244
|
-
this.dataView.setUint8(
|
|
1248
|
+
this.dataView.setUint8(NET_CTX_WANTS_ROOM_CODE_OFFSET + i, 0);
|
|
1245
1249
|
}
|
|
1246
1250
|
if (code) {
|
|
1247
1251
|
for (let i = 0;i < Math.min(code.length, 7); i++) {
|
|
1248
|
-
this.dataView.setUint8(
|
|
1252
|
+
this.dataView.setUint8(NET_CTX_WANTS_ROOM_CODE_OFFSET + i, code.charCodeAt(i));
|
|
1249
1253
|
}
|
|
1250
1254
|
}
|
|
1251
1255
|
}
|
|
@@ -1253,13 +1257,13 @@ class NetContext {
|
|
|
1253
1257
|
if (!this.#hasValidBuffer()) {
|
|
1254
1258
|
return false;
|
|
1255
1259
|
}
|
|
1256
|
-
return this.dataView.getUint8(
|
|
1260
|
+
return this.dataView.getUint8(NET_CTX_WANTS_DISCONNECT_OFFSET) !== 0;
|
|
1257
1261
|
}
|
|
1258
1262
|
set wantsDisconnect(value) {
|
|
1259
1263
|
if (!this.#hasValidBuffer()) {
|
|
1260
1264
|
throw new Error("NetContext dataView is not valid");
|
|
1261
1265
|
}
|
|
1262
|
-
this.dataView.setUint8(
|
|
1266
|
+
this.dataView.setUint8(NET_CTX_WANTS_DISCONNECT_OFFSET, value ? 1 : 0);
|
|
1263
1267
|
}
|
|
1264
1268
|
get peers() {
|
|
1265
1269
|
if (!this.#hasValidBuffer()) {
|
|
@@ -1269,13 +1273,13 @@ class NetContext {
|
|
|
1269
1273
|
const localPeerId = this.localPeerId;
|
|
1270
1274
|
const matchFrame = this.matchFrame;
|
|
1271
1275
|
let minRemoteSeq = -1;
|
|
1272
|
-
for (let i = 0;i <
|
|
1276
|
+
for (let i = 0;i < MAX_PLAYERS; i++) {
|
|
1273
1277
|
if (i === localPeerId)
|
|
1274
1278
|
continue;
|
|
1275
|
-
const peerOffset =
|
|
1276
|
-
if (dv.getUint8(peerOffset +
|
|
1279
|
+
const peerOffset = NET_CTX_PEERS_OFFSET + i * PEER_CTX_SIZE;
|
|
1280
|
+
if (dv.getUint8(peerOffset + PEER_CTX_CONNECTED_OFFSET) !== 1)
|
|
1277
1281
|
continue;
|
|
1278
|
-
const seq = dv.getInt16(peerOffset +
|
|
1282
|
+
const seq = dv.getInt16(peerOffset + PEER_CTX_SEQ_OFFSET, true);
|
|
1279
1283
|
if (seq < 0)
|
|
1280
1284
|
continue;
|
|
1281
1285
|
if (minRemoteSeq === -1 || seq < minRemoteSeq) {
|
|
@@ -1283,9 +1287,9 @@ class NetContext {
|
|
|
1283
1287
|
}
|
|
1284
1288
|
}
|
|
1285
1289
|
this.#peersResult.length = 0;
|
|
1286
|
-
for (let i = 0;i <
|
|
1287
|
-
const peerOffset =
|
|
1288
|
-
if (dv.getUint8(peerOffset +
|
|
1290
|
+
for (let i = 0;i < MAX_PLAYERS; i++) {
|
|
1291
|
+
const peerOffset = NET_CTX_PEERS_OFFSET + i * PEER_CTX_SIZE;
|
|
1292
|
+
if (dv.getUint8(peerOffset + PEER_CTX_CONNECTED_OFFSET) !== 1)
|
|
1289
1293
|
continue;
|
|
1290
1294
|
const peer = this.#peers[i];
|
|
1291
1295
|
if (!peer) {
|
|
@@ -1297,8 +1301,8 @@ class NetContext {
|
|
|
1297
1301
|
peer.seq = matchFrame;
|
|
1298
1302
|
peer.ack = minRemoteSeq;
|
|
1299
1303
|
} else {
|
|
1300
|
-
peer.seq = dv.getInt16(peerOffset +
|
|
1301
|
-
peer.ack = dv.getInt16(peerOffset +
|
|
1304
|
+
peer.seq = dv.getInt16(peerOffset + PEER_CTX_SEQ_OFFSET, true);
|
|
1305
|
+
peer.ack = dv.getInt16(peerOffset + PEER_CTX_ACK_OFFSET, true);
|
|
1302
1306
|
}
|
|
1303
1307
|
this.#peersResult.push(peer);
|
|
1304
1308
|
}
|
|
@@ -1308,19 +1312,19 @@ class NetContext {
|
|
|
1308
1312
|
if (!this.#hasValidBuffer()) {
|
|
1309
1313
|
throw new Error("NetContext dataView is not valid");
|
|
1310
1314
|
}
|
|
1311
|
-
return this.dataView.getUint32(
|
|
1315
|
+
return this.dataView.getUint32(NET_CTX_LAST_ROLLBACK_DEPTH_OFFSET, true);
|
|
1312
1316
|
}
|
|
1313
1317
|
get totalRollbacks() {
|
|
1314
1318
|
if (!this.#hasValidBuffer()) {
|
|
1315
1319
|
throw new Error("NetContext dataView is not valid");
|
|
1316
1320
|
}
|
|
1317
|
-
return this.dataView.getUint32(
|
|
1321
|
+
return this.dataView.getUint32(NET_CTX_TOTAL_ROLLBACKS_OFFSET, true);
|
|
1318
1322
|
}
|
|
1319
1323
|
get framesResimulated() {
|
|
1320
1324
|
if (!this.#hasValidBuffer()) {
|
|
1321
1325
|
throw new Error("NetContext dataView is not valid");
|
|
1322
1326
|
}
|
|
1323
|
-
return Number(this.dataView.getBigUint64(
|
|
1327
|
+
return Number(this.dataView.getBigUint64(NET_CTX_FRAMES_RESIMULATED_OFFSET, true));
|
|
1324
1328
|
}
|
|
1325
1329
|
}
|
|
1326
1330
|
|
|
@@ -1333,21 +1337,41 @@ class TimeContext {
|
|
|
1333
1337
|
if (!this.dataView) {
|
|
1334
1338
|
throw new Error("TimeContext DataView is not initialized");
|
|
1335
1339
|
}
|
|
1336
|
-
return this.dataView.getUint32(
|
|
1340
|
+
return this.dataView.getUint32(TIME_CTX_FRAME_OFFSET, true);
|
|
1337
1341
|
}
|
|
1338
1342
|
get dt() {
|
|
1339
1343
|
if (!this.dataView) {
|
|
1340
1344
|
throw new Error("TimeContext DataView is not initialized");
|
|
1341
1345
|
}
|
|
1342
|
-
return this.dataView.getUint32(
|
|
1346
|
+
return this.dataView.getUint32(TIME_CTX_DT_MS_OFFSET, true) / 1000;
|
|
1343
1347
|
}
|
|
1344
1348
|
get time() {
|
|
1345
1349
|
if (!this.dataView) {
|
|
1346
1350
|
throw new Error("TimeContext DataView is not initialized");
|
|
1347
1351
|
}
|
|
1348
|
-
return this.dataView.getUint32(
|
|
1352
|
+
return this.dataView.getUint32(TIME_CTX_TOTAL_MS_OFFSET, true) / 1000;
|
|
1349
1353
|
}
|
|
1350
1354
|
}
|
|
1355
|
+
var EVENT_PAYLOAD_SIZE = 8;
|
|
1356
|
+
var EVENT_PAYLOAD_ALIGN = 4;
|
|
1357
|
+
function keyToKeyCode(key) {
|
|
1358
|
+
return Key[key];
|
|
1359
|
+
}
|
|
1360
|
+
function keyCodeToKey(code) {
|
|
1361
|
+
return Key[code];
|
|
1362
|
+
}
|
|
1363
|
+
function mouseButtonToMouseButtonCode(button) {
|
|
1364
|
+
return MouseButton[button];
|
|
1365
|
+
}
|
|
1366
|
+
function mouseButtonCodeToMouseButton(code) {
|
|
1367
|
+
return MouseButton[code];
|
|
1368
|
+
}
|
|
1369
|
+
function inputSourceToInputSourceCode(source) {
|
|
1370
|
+
return InputSource[source];
|
|
1371
|
+
}
|
|
1372
|
+
function inputSourceCodeToInputSource(code) {
|
|
1373
|
+
return InputSource[code];
|
|
1374
|
+
}
|
|
1351
1375
|
var TAPE_MAGIC = 1413566533;
|
|
1352
1376
|
function readTapeHeader(tape) {
|
|
1353
1377
|
const view = new DataView(tape.buffer, tape.byteOffset, tape.byteLength);
|
|
@@ -1363,7 +1387,7 @@ function readTapeHeader(tape) {
|
|
|
1363
1387
|
eventCount: view.getUint16(14, true)
|
|
1364
1388
|
};
|
|
1365
1389
|
}
|
|
1366
|
-
var DEFAULT_WASM_URL = new URL("https://unpkg.com/@bloopjs/engine@0.0.
|
|
1390
|
+
var DEFAULT_WASM_URL = new URL("https://unpkg.com/@bloopjs/engine@0.0.89/wasm/bloop.wasm");
|
|
1367
1391
|
var MAX_ROLLBACK_FRAMES = 500;
|
|
1368
1392
|
var TIME_CTX_OFFSET = 0;
|
|
1369
1393
|
var INPUT_CTX_OFFSET = TIME_CTX_OFFSET + 4;
|
|
@@ -1628,6 +1652,7 @@ async function mount(mountable, options) {
|
|
|
1628
1652
|
memory,
|
|
1629
1653
|
__systems: function(system_handle, ptr) {
|
|
1630
1654
|
mountable.hooks.setBuffer(memory.buffer);
|
|
1655
|
+
mountable.hooks.setContext(ptr);
|
|
1631
1656
|
mountable.hooks.systemsCallback(system_handle, ptr);
|
|
1632
1657
|
},
|
|
1633
1658
|
__before_frame: function(ptr, frame) {
|
|
@@ -1774,9 +1799,15 @@ class Bloop {
|
|
|
1774
1799
|
const inputCtxPtr = dv.getUint32(INPUT_CTX_OFFSET, true);
|
|
1775
1800
|
const netCtxPtr = dv.getUint32(NET_CTX_OFFSET, true);
|
|
1776
1801
|
this.#context.rawPointer = ptr;
|
|
1777
|
-
this.#context.inputs.dataView
|
|
1778
|
-
|
|
1779
|
-
|
|
1802
|
+
if (!this.#context.inputs.hasDataView() || this.#context.inputs.dataView.buffer !== this.#engineBuffer || this.#context.inputs.dataView.byteOffset !== inputCtxPtr) {
|
|
1803
|
+
this.#context.inputs.dataView = new DataView(this.#engineBuffer, inputCtxPtr);
|
|
1804
|
+
}
|
|
1805
|
+
if (this.#context.time.dataView?.buffer !== this.#engineBuffer || this.#context.time.dataView?.byteOffset !== timeCtxPtr) {
|
|
1806
|
+
this.#context.time.dataView = new DataView(this.#engineBuffer, timeCtxPtr);
|
|
1807
|
+
}
|
|
1808
|
+
if (this.#context.net.dataView?.buffer !== this.#engineBuffer || this.#context.net.dataView?.byteOffset !== netCtxPtr) {
|
|
1809
|
+
this.#context.net.dataView = new DataView(this.#engineBuffer, netCtxPtr);
|
|
1810
|
+
}
|
|
1780
1811
|
},
|
|
1781
1812
|
systemsCallback: (system_handle, ptr) => {
|
|
1782
1813
|
this.hooks.setContext(ptr);
|
|
@@ -1881,6 +1912,13 @@ class Bloop {
|
|
|
1881
1912
|
system.netcode?.(this.#context);
|
|
1882
1913
|
break;
|
|
1883
1914
|
}
|
|
1915
|
+
case exports_enums.EventType.NetSessionInit:
|
|
1916
|
+
console.log("[bloop] NetSessionInit event received");
|
|
1917
|
+
this.#context.event = {
|
|
1918
|
+
type: "session:start"
|
|
1919
|
+
};
|
|
1920
|
+
system.netcode?.(this.#context);
|
|
1921
|
+
break;
|
|
1884
1922
|
default:
|
|
1885
1923
|
break;
|
|
1886
1924
|
}
|
|
@@ -2183,15 +2221,33 @@ var NetJoinFailReason2;
|
|
|
2183
2221
|
NetJoinFailReason22[NetJoinFailReason22["room_not_found"] = 3] = "room_not_found";
|
|
2184
2222
|
NetJoinFailReason22[NetJoinFailReason22["already_in_room"] = 4] = "already_in_room";
|
|
2185
2223
|
})(NetJoinFailReason2 ||= {});
|
|
2186
|
-
var
|
|
2187
|
-
var
|
|
2188
|
-
var
|
|
2189
|
-
var
|
|
2224
|
+
var PEER_CTX_CONNECTED_OFFSET2 = 0;
|
|
2225
|
+
var PEER_CTX_SEQ_OFFSET2 = 2;
|
|
2226
|
+
var PEER_CTX_ACK_OFFSET2 = 4;
|
|
2227
|
+
var PEER_CTX_SIZE2 = 8;
|
|
2228
|
+
var NET_CTX_PEER_COUNT_OFFSET2 = 0;
|
|
2229
|
+
var NET_CTX_LOCAL_PEER_ID_OFFSET2 = 1;
|
|
2230
|
+
var NET_CTX_IN_SESSION_OFFSET2 = 2;
|
|
2231
|
+
var NET_CTX_STATUS_OFFSET2 = 3;
|
|
2232
|
+
var NET_CTX_MATCH_FRAME_OFFSET2 = 4;
|
|
2233
|
+
var NET_CTX_SESSION_START_FRAME_OFFSET2 = 8;
|
|
2234
|
+
var NET_CTX_ROOM_CODE_OFFSET2 = 12;
|
|
2235
|
+
var NET_CTX_WANTS_ROOM_CODE_OFFSET2 = 20;
|
|
2236
|
+
var NET_CTX_WANTS_DISCONNECT_OFFSET2 = 28;
|
|
2237
|
+
var NET_CTX_PEERS_OFFSET2 = 32;
|
|
2238
|
+
var NET_CTX_LAST_ROLLBACK_DEPTH_OFFSET2 = 128;
|
|
2239
|
+
var NET_CTX_TOTAL_ROLLBACKS_OFFSET2 = 132;
|
|
2240
|
+
var NET_CTX_FRAMES_RESIMULATED_OFFSET2 = 136;
|
|
2241
|
+
var MOUSE_CTX_X_OFFSET2 = 0;
|
|
2242
|
+
var MOUSE_CTX_Y_OFFSET2 = 4;
|
|
2243
|
+
var MOUSE_CTX_WHEEL_X_OFFSET2 = 8;
|
|
2244
|
+
var MOUSE_CTX_WHEEL_Y_OFFSET2 = 12;
|
|
2245
|
+
var MOUSE_CTX_BUTTON_STATES_OFFSET2 = 16;
|
|
2246
|
+
var PLAYER_INPUTS_KEY_CTX_OFFSET2 = 0;
|
|
2247
|
+
var PLAYER_INPUTS_MOUSE_CTX_OFFSET2 = 256;
|
|
2190
2248
|
var PLAYER_INPUTS_SIZE2 = 280;
|
|
2191
|
-
var
|
|
2192
|
-
|
|
2193
|
-
return MouseButton2[code];
|
|
2194
|
-
}
|
|
2249
|
+
var MAX_PLAYERS2 = 12;
|
|
2250
|
+
|
|
2195
2251
|
class PlayerInputContext2 {
|
|
2196
2252
|
#dataView;
|
|
2197
2253
|
#keys;
|
|
@@ -2201,13 +2257,13 @@ class PlayerInputContext2 {
|
|
|
2201
2257
|
}
|
|
2202
2258
|
get keys() {
|
|
2203
2259
|
if (!this.#keys) {
|
|
2204
|
-
this.#keys = new KeyboardContext2(new DataView(this.#dataView.buffer, this.#dataView.byteOffset +
|
|
2260
|
+
this.#keys = new KeyboardContext2(new DataView(this.#dataView.buffer, this.#dataView.byteOffset + PLAYER_INPUTS_KEY_CTX_OFFSET2));
|
|
2205
2261
|
}
|
|
2206
2262
|
return this.#keys;
|
|
2207
2263
|
}
|
|
2208
2264
|
get mouse() {
|
|
2209
2265
|
if (!this.#mouse) {
|
|
2210
|
-
this.#mouse = new MouseContext2(new DataView(this.#dataView.buffer, this.#dataView.byteOffset +
|
|
2266
|
+
this.#mouse = new MouseContext2(new DataView(this.#dataView.buffer, this.#dataView.byteOffset + PLAYER_INPUTS_MOUSE_CTX_OFFSET2));
|
|
2211
2267
|
}
|
|
2212
2268
|
return this.#mouse;
|
|
2213
2269
|
}
|
|
@@ -2232,6 +2288,9 @@ class InputContext2 {
|
|
|
2232
2288
|
this.#dataView = dataView;
|
|
2233
2289
|
this.#buildPlayers();
|
|
2234
2290
|
}
|
|
2291
|
+
hasDataView() {
|
|
2292
|
+
return !!this.#dataView;
|
|
2293
|
+
}
|
|
2235
2294
|
#buildPlayers() {
|
|
2236
2295
|
this.#players = [];
|
|
2237
2296
|
for (let i = 0;i < MAX_PLAYERS2; i++) {
|
|
@@ -2264,19 +2323,19 @@ class MouseContext2 {
|
|
|
2264
2323
|
this.#dataView = dataView;
|
|
2265
2324
|
}
|
|
2266
2325
|
get x() {
|
|
2267
|
-
return this.#dataView.getFloat32(
|
|
2326
|
+
return this.#dataView.getFloat32(MOUSE_CTX_X_OFFSET2, true);
|
|
2268
2327
|
}
|
|
2269
2328
|
get y() {
|
|
2270
|
-
return this.#dataView.getFloat32(
|
|
2329
|
+
return this.#dataView.getFloat32(MOUSE_CTX_Y_OFFSET2, true);
|
|
2271
2330
|
}
|
|
2272
2331
|
get wheel() {
|
|
2273
2332
|
return { x: this.wheelX, y: this.wheelY };
|
|
2274
2333
|
}
|
|
2275
2334
|
get wheelX() {
|
|
2276
|
-
return this.#dataView.getFloat32(
|
|
2335
|
+
return this.#dataView.getFloat32(MOUSE_CTX_WHEEL_X_OFFSET2, true);
|
|
2277
2336
|
}
|
|
2278
2337
|
get wheelY() {
|
|
2279
|
-
return this.#dataView.getFloat32(
|
|
2338
|
+
return this.#dataView.getFloat32(MOUSE_CTX_WHEEL_Y_OFFSET2, true);
|
|
2280
2339
|
}
|
|
2281
2340
|
get left() {
|
|
2282
2341
|
return this.#buttonState(1);
|
|
@@ -2295,7 +2354,7 @@ class MouseContext2 {
|
|
|
2295
2354
|
state = { down: false, held: false, up: false };
|
|
2296
2355
|
this.#buttonStates.set(code, state);
|
|
2297
2356
|
}
|
|
2298
|
-
const offset =
|
|
2357
|
+
const offset = MOUSE_CTX_BUTTON_STATES_OFFSET2;
|
|
2299
2358
|
state.held = !!(this.#dataView.getUint8(offset + code) & 1);
|
|
2300
2359
|
state.down = state.held && !(this.#dataView.getUint8(offset + code) & 2);
|
|
2301
2360
|
state.up = !state.held && !!(this.#dataView.getUint8(offset + code) & 2);
|
|
@@ -2917,15 +2976,6 @@ class KeyboardContext2 {
|
|
|
2917
2976
|
return state;
|
|
2918
2977
|
}
|
|
2919
2978
|
}
|
|
2920
|
-
var MAX_PEERS2 = 12;
|
|
2921
|
-
var PEERS_ARRAY_OFFSET2 = 32;
|
|
2922
|
-
var PEER_CTX_SIZE2 = 8;
|
|
2923
|
-
var LAST_ROLLBACK_DEPTH_OFFSET2 = 128;
|
|
2924
|
-
var TOTAL_ROLLBACKS_OFFSET2 = 132;
|
|
2925
|
-
var FRAMES_RESIMULATED_OFFSET2 = 136;
|
|
2926
|
-
var PEER_CONNECTED_OFFSET2 = 0;
|
|
2927
|
-
var PEER_SEQ_OFFSET2 = 2;
|
|
2928
|
-
var PEER_ACK_OFFSET2 = 4;
|
|
2929
2979
|
var STATUS_MAP2 = {
|
|
2930
2980
|
0: "offline",
|
|
2931
2981
|
1: "local",
|
|
@@ -2936,7 +2986,7 @@ var STATUS_MAP2 = {
|
|
|
2936
2986
|
|
|
2937
2987
|
class NetContext2 {
|
|
2938
2988
|
dataView;
|
|
2939
|
-
#peers = Array.from({ length:
|
|
2989
|
+
#peers = Array.from({ length: MAX_PLAYERS2 }, () => ({
|
|
2940
2990
|
isLocal: false,
|
|
2941
2991
|
seq: -1,
|
|
2942
2992
|
ack: -1
|
|
@@ -2954,38 +3004,38 @@ class NetContext2 {
|
|
|
2954
3004
|
if (!this.#hasValidBuffer()) {
|
|
2955
3005
|
throw new Error("NetContext dataView is not valid");
|
|
2956
3006
|
}
|
|
2957
|
-
return this.dataView.getUint8(
|
|
3007
|
+
return this.dataView.getUint8(NET_CTX_PEER_COUNT_OFFSET2);
|
|
2958
3008
|
}
|
|
2959
3009
|
get localPeerId() {
|
|
2960
3010
|
if (!this.#hasValidBuffer()) {
|
|
2961
3011
|
throw new Error("NetContext dataView is not valid");
|
|
2962
3012
|
}
|
|
2963
|
-
return this.dataView.getUint8(
|
|
3013
|
+
return this.dataView.getUint8(NET_CTX_LOCAL_PEER_ID_OFFSET2);
|
|
2964
3014
|
}
|
|
2965
3015
|
get isInSession() {
|
|
2966
3016
|
if (!this.#hasValidBuffer()) {
|
|
2967
3017
|
throw new Error("NetContext dataView is not valid");
|
|
2968
3018
|
}
|
|
2969
|
-
return this.dataView.getUint8(
|
|
3019
|
+
return this.dataView.getUint8(NET_CTX_IN_SESSION_OFFSET2) !== 0;
|
|
2970
3020
|
}
|
|
2971
3021
|
get status() {
|
|
2972
3022
|
if (!this.#hasValidBuffer()) {
|
|
2973
3023
|
throw new Error("NetContext dataView is not valid");
|
|
2974
3024
|
}
|
|
2975
|
-
const statusByte = this.dataView.getUint8(
|
|
3025
|
+
const statusByte = this.dataView.getUint8(NET_CTX_STATUS_OFFSET2);
|
|
2976
3026
|
return STATUS_MAP2[statusByte] ?? "local";
|
|
2977
3027
|
}
|
|
2978
3028
|
get matchFrame() {
|
|
2979
3029
|
if (!this.#hasValidBuffer()) {
|
|
2980
3030
|
throw new Error("NetContext dataView is not valid");
|
|
2981
3031
|
}
|
|
2982
|
-
return this.dataView.getUint32(
|
|
3032
|
+
return this.dataView.getUint32(NET_CTX_MATCH_FRAME_OFFSET2, true);
|
|
2983
3033
|
}
|
|
2984
3034
|
get sessionStartFrame() {
|
|
2985
3035
|
if (!this.#hasValidBuffer()) {
|
|
2986
3036
|
throw new Error("NetContext dataView is not valid");
|
|
2987
3037
|
}
|
|
2988
|
-
return this.dataView.getUint32(
|
|
3038
|
+
return this.dataView.getUint32(NET_CTX_SESSION_START_FRAME_OFFSET2, true);
|
|
2989
3039
|
}
|
|
2990
3040
|
get roomCode() {
|
|
2991
3041
|
if (!this.#hasValidBuffer()) {
|
|
@@ -2993,7 +3043,7 @@ class NetContext2 {
|
|
|
2993
3043
|
}
|
|
2994
3044
|
const bytes = [];
|
|
2995
3045
|
for (let i = 0;i < 8; i++) {
|
|
2996
|
-
const byte = this.dataView.getUint8(
|
|
3046
|
+
const byte = this.dataView.getUint8(NET_CTX_ROOM_CODE_OFFSET2 + i);
|
|
2997
3047
|
if (byte === 0)
|
|
2998
3048
|
break;
|
|
2999
3049
|
bytes.push(byte);
|
|
@@ -3006,7 +3056,7 @@ class NetContext2 {
|
|
|
3006
3056
|
}
|
|
3007
3057
|
const bytes = [];
|
|
3008
3058
|
for (let i = 0;i < 8; i++) {
|
|
3009
|
-
const byte = this.dataView.getUint8(
|
|
3059
|
+
const byte = this.dataView.getUint8(NET_CTX_WANTS_ROOM_CODE_OFFSET2 + i);
|
|
3010
3060
|
if (byte === 0)
|
|
3011
3061
|
break;
|
|
3012
3062
|
bytes.push(byte);
|
|
@@ -3018,11 +3068,11 @@ class NetContext2 {
|
|
|
3018
3068
|
throw new Error("NetContext dataView is not valid");
|
|
3019
3069
|
}
|
|
3020
3070
|
for (let i = 0;i < 8; i++) {
|
|
3021
|
-
this.dataView.setUint8(
|
|
3071
|
+
this.dataView.setUint8(NET_CTX_WANTS_ROOM_CODE_OFFSET2 + i, 0);
|
|
3022
3072
|
}
|
|
3023
3073
|
if (code) {
|
|
3024
3074
|
for (let i = 0;i < Math.min(code.length, 7); i++) {
|
|
3025
|
-
this.dataView.setUint8(
|
|
3075
|
+
this.dataView.setUint8(NET_CTX_WANTS_ROOM_CODE_OFFSET2 + i, code.charCodeAt(i));
|
|
3026
3076
|
}
|
|
3027
3077
|
}
|
|
3028
3078
|
}
|
|
@@ -3030,13 +3080,13 @@ class NetContext2 {
|
|
|
3030
3080
|
if (!this.#hasValidBuffer()) {
|
|
3031
3081
|
return false;
|
|
3032
3082
|
}
|
|
3033
|
-
return this.dataView.getUint8(
|
|
3083
|
+
return this.dataView.getUint8(NET_CTX_WANTS_DISCONNECT_OFFSET2) !== 0;
|
|
3034
3084
|
}
|
|
3035
3085
|
set wantsDisconnect(value) {
|
|
3036
3086
|
if (!this.#hasValidBuffer()) {
|
|
3037
3087
|
throw new Error("NetContext dataView is not valid");
|
|
3038
3088
|
}
|
|
3039
|
-
this.dataView.setUint8(
|
|
3089
|
+
this.dataView.setUint8(NET_CTX_WANTS_DISCONNECT_OFFSET2, value ? 1 : 0);
|
|
3040
3090
|
}
|
|
3041
3091
|
get peers() {
|
|
3042
3092
|
if (!this.#hasValidBuffer()) {
|
|
@@ -3046,13 +3096,13 @@ class NetContext2 {
|
|
|
3046
3096
|
const localPeerId = this.localPeerId;
|
|
3047
3097
|
const matchFrame = this.matchFrame;
|
|
3048
3098
|
let minRemoteSeq = -1;
|
|
3049
|
-
for (let i = 0;i <
|
|
3099
|
+
for (let i = 0;i < MAX_PLAYERS2; i++) {
|
|
3050
3100
|
if (i === localPeerId)
|
|
3051
3101
|
continue;
|
|
3052
|
-
const peerOffset =
|
|
3053
|
-
if (dv.getUint8(peerOffset +
|
|
3102
|
+
const peerOffset = NET_CTX_PEERS_OFFSET2 + i * PEER_CTX_SIZE2;
|
|
3103
|
+
if (dv.getUint8(peerOffset + PEER_CTX_CONNECTED_OFFSET2) !== 1)
|
|
3054
3104
|
continue;
|
|
3055
|
-
const seq = dv.getInt16(peerOffset +
|
|
3105
|
+
const seq = dv.getInt16(peerOffset + PEER_CTX_SEQ_OFFSET2, true);
|
|
3056
3106
|
if (seq < 0)
|
|
3057
3107
|
continue;
|
|
3058
3108
|
if (minRemoteSeq === -1 || seq < minRemoteSeq) {
|
|
@@ -3060,9 +3110,9 @@ class NetContext2 {
|
|
|
3060
3110
|
}
|
|
3061
3111
|
}
|
|
3062
3112
|
this.#peersResult.length = 0;
|
|
3063
|
-
for (let i = 0;i <
|
|
3064
|
-
const peerOffset =
|
|
3065
|
-
if (dv.getUint8(peerOffset +
|
|
3113
|
+
for (let i = 0;i < MAX_PLAYERS2; i++) {
|
|
3114
|
+
const peerOffset = NET_CTX_PEERS_OFFSET2 + i * PEER_CTX_SIZE2;
|
|
3115
|
+
if (dv.getUint8(peerOffset + PEER_CTX_CONNECTED_OFFSET2) !== 1)
|
|
3066
3116
|
continue;
|
|
3067
3117
|
const peer = this.#peers[i];
|
|
3068
3118
|
if (!peer) {
|
|
@@ -3074,8 +3124,8 @@ class NetContext2 {
|
|
|
3074
3124
|
peer.seq = matchFrame;
|
|
3075
3125
|
peer.ack = minRemoteSeq;
|
|
3076
3126
|
} else {
|
|
3077
|
-
peer.seq = dv.getInt16(peerOffset +
|
|
3078
|
-
peer.ack = dv.getInt16(peerOffset +
|
|
3127
|
+
peer.seq = dv.getInt16(peerOffset + PEER_CTX_SEQ_OFFSET2, true);
|
|
3128
|
+
peer.ack = dv.getInt16(peerOffset + PEER_CTX_ACK_OFFSET2, true);
|
|
3079
3129
|
}
|
|
3080
3130
|
this.#peersResult.push(peer);
|
|
3081
3131
|
}
|
|
@@ -3085,21 +3135,24 @@ class NetContext2 {
|
|
|
3085
3135
|
if (!this.#hasValidBuffer()) {
|
|
3086
3136
|
throw new Error("NetContext dataView is not valid");
|
|
3087
3137
|
}
|
|
3088
|
-
return this.dataView.getUint32(
|
|
3138
|
+
return this.dataView.getUint32(NET_CTX_LAST_ROLLBACK_DEPTH_OFFSET2, true);
|
|
3089
3139
|
}
|
|
3090
3140
|
get totalRollbacks() {
|
|
3091
3141
|
if (!this.#hasValidBuffer()) {
|
|
3092
3142
|
throw new Error("NetContext dataView is not valid");
|
|
3093
3143
|
}
|
|
3094
|
-
return this.dataView.getUint32(
|
|
3144
|
+
return this.dataView.getUint32(NET_CTX_TOTAL_ROLLBACKS_OFFSET2, true);
|
|
3095
3145
|
}
|
|
3096
3146
|
get framesResimulated() {
|
|
3097
3147
|
if (!this.#hasValidBuffer()) {
|
|
3098
3148
|
throw new Error("NetContext dataView is not valid");
|
|
3099
3149
|
}
|
|
3100
|
-
return Number(this.dataView.getBigUint64(
|
|
3150
|
+
return Number(this.dataView.getBigUint64(NET_CTX_FRAMES_RESIMULATED_OFFSET2, true));
|
|
3101
3151
|
}
|
|
3102
3152
|
}
|
|
3153
|
+
function mouseButtonCodeToMouseButton2(code) {
|
|
3154
|
+
return MouseButton2[code];
|
|
3155
|
+
}
|
|
3103
3156
|
var TAPE_MAGIC2 = 1413566533;
|
|
3104
3157
|
function readTapeHeader2(tape) {
|
|
3105
3158
|
const view = new DataView(tape.buffer, tape.byteOffset, tape.byteLength);
|
|
@@ -3115,7 +3168,7 @@ function readTapeHeader2(tape) {
|
|
|
3115
3168
|
eventCount: view.getUint16(14, true)
|
|
3116
3169
|
};
|
|
3117
3170
|
}
|
|
3118
|
-
var DEFAULT_WASM_URL2 = new URL("https://unpkg.com/@bloopjs/engine@0.0.
|
|
3171
|
+
var DEFAULT_WASM_URL2 = new URL("https://unpkg.com/@bloopjs/engine@0.0.89/wasm/bloop.wasm");
|
|
3119
3172
|
var TIME_CTX_OFFSET2 = 0;
|
|
3120
3173
|
var INPUT_CTX_OFFSET2 = TIME_CTX_OFFSET2 + 4;
|
|
3121
3174
|
var EVENTS_OFFSET2 = INPUT_CTX_OFFSET2 + 4;
|
|
@@ -6327,6 +6380,138 @@ function joinRoom(brokerUrl, _roomId, cbs) {
|
|
|
6327
6380
|
}
|
|
6328
6381
|
}
|
|
6329
6382
|
|
|
6383
|
+
// src/netcode/reconcile.ts
|
|
6384
|
+
var udp = null;
|
|
6385
|
+
var localPeerId = null;
|
|
6386
|
+
var remotePeerId = null;
|
|
6387
|
+
var localStringPeerId = null;
|
|
6388
|
+
var remoteStringPeerId = null;
|
|
6389
|
+
var incomingPackets = [];
|
|
6390
|
+
var actual = {
|
|
6391
|
+
roomCode: ""
|
|
6392
|
+
};
|
|
6393
|
+
async function reconcile(app, signal) {
|
|
6394
|
+
app.beforeFrame.subscribe((_frame) => {
|
|
6395
|
+
if (!app.game.context.net.isInSession) {
|
|
6396
|
+
return;
|
|
6397
|
+
}
|
|
6398
|
+
try {
|
|
6399
|
+
receivePackets(app);
|
|
6400
|
+
sendPacket(app);
|
|
6401
|
+
} catch (e4) {
|
|
6402
|
+
console.error("Error in beforeFrame:", e4);
|
|
6403
|
+
}
|
|
6404
|
+
});
|
|
6405
|
+
logger.onLog = (log) => {
|
|
6406
|
+
addLog(log);
|
|
6407
|
+
};
|
|
6408
|
+
while (!signal.aborted) {
|
|
6409
|
+
const { net } = app.game.context;
|
|
6410
|
+
if (net.wantsRoomCode && actual.roomCode !== net.wantsRoomCode) {
|
|
6411
|
+
console.log("[netcode] wants a room code", {
|
|
6412
|
+
actual: actual.roomCode,
|
|
6413
|
+
wants: net.wantsRoomCode
|
|
6414
|
+
});
|
|
6415
|
+
actual.roomCode = net.wantsRoomCode;
|
|
6416
|
+
joinRollbackRoom(net.wantsRoomCode, app);
|
|
6417
|
+
}
|
|
6418
|
+
await sleep(150);
|
|
6419
|
+
}
|
|
6420
|
+
}
|
|
6421
|
+
async function sleep(ms) {
|
|
6422
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
6423
|
+
}
|
|
6424
|
+
function joinRollbackRoom(roomId, app) {
|
|
6425
|
+
app.joinRoom(roomId, {
|
|
6426
|
+
onPeerIdAssign: (peerId) => {
|
|
6427
|
+
localStringPeerId = peerId;
|
|
6428
|
+
},
|
|
6429
|
+
onBrokerMessage: (_message) => {},
|
|
6430
|
+
onMessage(_peerId, data, _reliable) {
|
|
6431
|
+
incomingPackets.push(new Uint8Array(data));
|
|
6432
|
+
},
|
|
6433
|
+
onDataChannelClose(_peerId, reliable) {
|
|
6434
|
+
if (!reliable && remotePeerId !== null) {
|
|
6435
|
+
app.sim.emit.network("peer:leave", { peerId: remotePeerId });
|
|
6436
|
+
}
|
|
6437
|
+
},
|
|
6438
|
+
onDataChannelOpen(peerId, reliable, channel) {
|
|
6439
|
+
if (!reliable) {
|
|
6440
|
+
udp = channel;
|
|
6441
|
+
if (localStringPeerId === null) {
|
|
6442
|
+
console.error("[netcode] Local peer ID not assigned yet!");
|
|
6443
|
+
return;
|
|
6444
|
+
}
|
|
6445
|
+
const ids = assignPeerIds(localStringPeerId, peerId);
|
|
6446
|
+
localPeerId = ids.local;
|
|
6447
|
+
setLocalId(localPeerId);
|
|
6448
|
+
remotePeerId = ids.remote;
|
|
6449
|
+
remoteStringPeerId = peerId;
|
|
6450
|
+
setRemoteId(remotePeerId);
|
|
6451
|
+
app.sim.emit.network("peer:join", { peerId: localPeerId });
|
|
6452
|
+
app.sim.emit.network("peer:join", { peerId: remotePeerId });
|
|
6453
|
+
app.sim.emit.network("peer:assign_local_id", { peerId: localPeerId });
|
|
6454
|
+
app.sim.emit.network("session:start", {});
|
|
6455
|
+
}
|
|
6456
|
+
},
|
|
6457
|
+
onPeerConnected(peerId) {
|
|
6458
|
+
addPeer({
|
|
6459
|
+
id: peerId,
|
|
6460
|
+
nickname: peerId.substring(0, 6),
|
|
6461
|
+
ack: -1,
|
|
6462
|
+
seq: -1,
|
|
6463
|
+
lastPacketTime: performance.now()
|
|
6464
|
+
});
|
|
6465
|
+
console.log(`[netcode] Peer connected: ${peerId}. Total peers: ${debugState.netStatus.value.peers.length}`);
|
|
6466
|
+
},
|
|
6467
|
+
onPeerDisconnected(peerId) {
|
|
6468
|
+
removePeer(peerId);
|
|
6469
|
+
if (remotePeerId !== null && peerId === remoteStringPeerId) {
|
|
6470
|
+
app.sim.emit.network("peer:leave", { peerId: remotePeerId });
|
|
6471
|
+
app.sim.emit.network("session:end", {});
|
|
6472
|
+
}
|
|
6473
|
+
}
|
|
6474
|
+
});
|
|
6475
|
+
}
|
|
6476
|
+
function assignPeerIds(localId, remoteId) {
|
|
6477
|
+
if (localId < remoteId) {
|
|
6478
|
+
return { local: 0, remote: 1 };
|
|
6479
|
+
} else {
|
|
6480
|
+
return { local: 1, remote: 0 };
|
|
6481
|
+
}
|
|
6482
|
+
}
|
|
6483
|
+
function receivePackets(app) {
|
|
6484
|
+
for (const packetData of incomingPackets) {
|
|
6485
|
+
app.sim.emit.packet(packetData);
|
|
6486
|
+
if (remotePeerId == null) {
|
|
6487
|
+
return;
|
|
6488
|
+
}
|
|
6489
|
+
const peerState = unwrap(app.sim.net.peers[remotePeerId], `Remote peer state not found for peerId ${remotePeerId}`);
|
|
6490
|
+
updatePeer(remoteStringPeerId, {
|
|
6491
|
+
ack: peerState.ack,
|
|
6492
|
+
seq: peerState.seq,
|
|
6493
|
+
lastPacketTime: performance.now()
|
|
6494
|
+
});
|
|
6495
|
+
}
|
|
6496
|
+
incomingPackets.length = 0;
|
|
6497
|
+
}
|
|
6498
|
+
function sendPacket(app) {
|
|
6499
|
+
if (!udp || remotePeerId === null) {
|
|
6500
|
+
console.warn("[netcode] Cannot send packet, udp or remotePeerId is null");
|
|
6501
|
+
return;
|
|
6502
|
+
}
|
|
6503
|
+
if (udp.readyState !== "open") {
|
|
6504
|
+
console.warn("[netcode] Data channel not open, cannot send packet. readyState=", udp.readyState);
|
|
6505
|
+
return;
|
|
6506
|
+
}
|
|
6507
|
+
const packet = app.sim.getOutboundPacket(remotePeerId);
|
|
6508
|
+
if (!packet) {
|
|
6509
|
+
console.warn("[netcode] No packet to send");
|
|
6510
|
+
return;
|
|
6511
|
+
}
|
|
6512
|
+
udp.send(packet);
|
|
6513
|
+
}
|
|
6514
|
+
|
|
6330
6515
|
// src/App.ts
|
|
6331
6516
|
var DEFAULT_BROKER_URL = "wss://webrtc-divine-glade-8064.fly.dev/ws";
|
|
6332
6517
|
async function start(opts) {
|
|
@@ -6350,6 +6535,7 @@ class App {
|
|
|
6350
6535
|
#unsubscribe = null;
|
|
6351
6536
|
#now = performance.now();
|
|
6352
6537
|
#debugUi = null;
|
|
6538
|
+
#abortController = new AbortController;
|
|
6353
6539
|
constructor(sim, game, brokerUrl, debugUiOpts) {
|
|
6354
6540
|
this.#sim = sim;
|
|
6355
6541
|
this.game = game;
|
|
@@ -6363,6 +6549,9 @@ class App {
|
|
|
6363
6549
|
this.beforeFrame.notify(frame);
|
|
6364
6550
|
};
|
|
6365
6551
|
this.subscribe();
|
|
6552
|
+
reconcile(this, this.#abortController.signal).catch((err) => {
|
|
6553
|
+
console.error("Error in lemmyloop:", err);
|
|
6554
|
+
});
|
|
6366
6555
|
}
|
|
6367
6556
|
get sim() {
|
|
6368
6557
|
return this.#sim;
|
|
@@ -6568,6 +6757,7 @@ class App {
|
|
|
6568
6757
|
this.afterFrame.unsubscribeAll();
|
|
6569
6758
|
this.onHmr.unsubscribeAll();
|
|
6570
6759
|
this.#debugUi?.unmount();
|
|
6760
|
+
this.#abortController.abort();
|
|
6571
6761
|
}
|
|
6572
6762
|
async acceptHmr(module, opts) {
|
|
6573
6763
|
const game = module.game ?? module;
|
|
@@ -6612,131 +6802,13 @@ var PacketType;
|
|
|
6612
6802
|
PacketType2[PacketType2["None"] = 0] = "None";
|
|
6613
6803
|
PacketType2[PacketType2["Inputs"] = 1] = "Inputs";
|
|
6614
6804
|
})(PacketType ||= {});
|
|
6615
|
-
// src/netcode/scaffold.ts
|
|
6616
|
-
function joinRollbackRoom(roomId, app, opts) {
|
|
6617
|
-
let udp = null;
|
|
6618
|
-
let sessionActive = false;
|
|
6619
|
-
let localPeerId = null;
|
|
6620
|
-
let remotePeerId = null;
|
|
6621
|
-
let localStringPeerId = null;
|
|
6622
|
-
let remoteStringPeerId = null;
|
|
6623
|
-
const incomingPackets = [];
|
|
6624
|
-
function assignPeerIds(localId, remoteId) {
|
|
6625
|
-
if (localId < remoteId) {
|
|
6626
|
-
return { local: 0, remote: 1 };
|
|
6627
|
-
} else {
|
|
6628
|
-
return { local: 1, remote: 0 };
|
|
6629
|
-
}
|
|
6630
|
-
}
|
|
6631
|
-
function receivePackets() {
|
|
6632
|
-
for (const packetData of incomingPackets) {
|
|
6633
|
-
app.sim.emit.packet(packetData);
|
|
6634
|
-
if (remotePeerId == null) {
|
|
6635
|
-
return;
|
|
6636
|
-
}
|
|
6637
|
-
const peerState = unwrap(app.sim.net.peers[remotePeerId], `Remote peer state not found for peerId ${remotePeerId}`);
|
|
6638
|
-
updatePeer(remoteStringPeerId, {
|
|
6639
|
-
ack: peerState.ack,
|
|
6640
|
-
seq: peerState.seq,
|
|
6641
|
-
lastPacketTime: performance.now()
|
|
6642
|
-
});
|
|
6643
|
-
}
|
|
6644
|
-
incomingPackets.length = 0;
|
|
6645
|
-
}
|
|
6646
|
-
function sendPacket() {
|
|
6647
|
-
if (!udp || remotePeerId === null) {
|
|
6648
|
-
console.warn("[netcode] Cannot send packet, udp or remotePeerId is null");
|
|
6649
|
-
return;
|
|
6650
|
-
}
|
|
6651
|
-
if (udp.readyState !== "open") {
|
|
6652
|
-
console.warn("[netcode] Data channel not open, cannot send packet. readyState=", udp.readyState);
|
|
6653
|
-
return;
|
|
6654
|
-
}
|
|
6655
|
-
const packet = app.sim.getOutboundPacket(remotePeerId);
|
|
6656
|
-
if (!packet) {
|
|
6657
|
-
console.warn("[netcode] No packet to send");
|
|
6658
|
-
return;
|
|
6659
|
-
}
|
|
6660
|
-
udp.send(packet);
|
|
6661
|
-
}
|
|
6662
|
-
logger.onLog = (log) => {
|
|
6663
|
-
addLog(log);
|
|
6664
|
-
};
|
|
6665
|
-
app.joinRoom(roomId, {
|
|
6666
|
-
onPeerIdAssign: (peerId) => {
|
|
6667
|
-
localStringPeerId = peerId;
|
|
6668
|
-
},
|
|
6669
|
-
onBrokerMessage: (_message) => {},
|
|
6670
|
-
onMessage(_peerId, data, _reliable) {
|
|
6671
|
-
incomingPackets.push(new Uint8Array(data));
|
|
6672
|
-
},
|
|
6673
|
-
onDataChannelClose(peerId, reliable) {
|
|
6674
|
-
if (!reliable && remotePeerId !== null) {
|
|
6675
|
-
app.sim.emit.network("peer:leave", { peerId: remotePeerId });
|
|
6676
|
-
sessionActive = false;
|
|
6677
|
-
opts?.onSessionEnd?.();
|
|
6678
|
-
}
|
|
6679
|
-
},
|
|
6680
|
-
onDataChannelOpen(peerId, reliable, channel) {
|
|
6681
|
-
if (!reliable) {
|
|
6682
|
-
udp = channel;
|
|
6683
|
-
if (localStringPeerId === null) {
|
|
6684
|
-
console.error("[netcode] Local peer ID not assigned yet!");
|
|
6685
|
-
return;
|
|
6686
|
-
}
|
|
6687
|
-
const ids = assignPeerIds(localStringPeerId, peerId);
|
|
6688
|
-
localPeerId = ids.local;
|
|
6689
|
-
setLocalId(localPeerId);
|
|
6690
|
-
remotePeerId = ids.remote;
|
|
6691
|
-
remoteStringPeerId = peerId;
|
|
6692
|
-
setRemoteId(remotePeerId);
|
|
6693
|
-
app.sim.emit.network("peer:join", { peerId: localPeerId });
|
|
6694
|
-
app.sim.emit.network("peer:join", { peerId: remotePeerId });
|
|
6695
|
-
app.sim.emit.network("peer:assign_local_id", { peerId: localPeerId });
|
|
6696
|
-
app.sim.emit.network("session:start", {});
|
|
6697
|
-
sessionActive = true;
|
|
6698
|
-
opts?.onSessionStart?.();
|
|
6699
|
-
}
|
|
6700
|
-
},
|
|
6701
|
-
onPeerConnected(peerId) {
|
|
6702
|
-
addPeer({
|
|
6703
|
-
id: peerId,
|
|
6704
|
-
nickname: peerId.substring(0, 6),
|
|
6705
|
-
ack: -1,
|
|
6706
|
-
seq: -1,
|
|
6707
|
-
lastPacketTime: performance.now()
|
|
6708
|
-
});
|
|
6709
|
-
console.log(`[netcode] Peer connected: ${peerId}. Total peers: ${debugState.netStatus.value.peers.length}`);
|
|
6710
|
-
},
|
|
6711
|
-
onPeerDisconnected(peerId) {
|
|
6712
|
-
removePeer(peerId);
|
|
6713
|
-
if (remotePeerId !== null && peerId === remoteStringPeerId) {
|
|
6714
|
-
app.sim.emit.network("peer:leave", { peerId: remotePeerId });
|
|
6715
|
-
sessionActive = false;
|
|
6716
|
-
opts?.onSessionEnd?.();
|
|
6717
|
-
}
|
|
6718
|
-
}
|
|
6719
|
-
});
|
|
6720
|
-
app.beforeFrame.subscribe((_frame) => {
|
|
6721
|
-
if (!sessionActive || !udp || remotePeerId === null) {
|
|
6722
|
-
return;
|
|
6723
|
-
}
|
|
6724
|
-
try {
|
|
6725
|
-
receivePackets();
|
|
6726
|
-
sendPacket();
|
|
6727
|
-
} catch (e4) {
|
|
6728
|
-
console.error("Error in beforeFrame:", e4);
|
|
6729
|
-
}
|
|
6730
|
-
});
|
|
6731
|
-
}
|
|
6732
6805
|
export {
|
|
6733
6806
|
start,
|
|
6734
6807
|
logger,
|
|
6735
|
-
joinRollbackRoom,
|
|
6736
6808
|
PacketType,
|
|
6737
6809
|
exports_mod as Debug,
|
|
6738
6810
|
App
|
|
6739
6811
|
};
|
|
6740
6812
|
|
|
6741
|
-
//# debugId=
|
|
6813
|
+
//# debugId=164BA35FD7424E1864756E2164756E21
|
|
6742
6814
|
//# sourceMappingURL=mod.js.map
|