@bloopjs/bloop 0.0.79 → 0.0.81

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.
@@ -1 +1 @@
1
- {"version":3,"file":"bloop.d.ts","sourceRoot":"","sources":["../src/bloop.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAQjD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,OAAO,CAAC;AACzC,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAEvC,MAAM,MAAM,SAAS,CAAC,CAAC,SAAS,GAAG,IAAI;IACrC,yBAAyB;IACzB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;;OAIG;IAEH;;OAEG;IAEH;;;OAGG;IACH,GAAG,CAAC,EAAE,CAAC,CAAC;CAET,CAAC;AAEF,qBAAa,KAAK,CAAC,EAAE,SAAS,WAAW;;IAKvC;;OAEG;IACH,MAAM,CAAC,MAAM,CAGX,CAAC,SAAS,GAAG,EAGb,IAAI,GAAE,SAAS,CAAC,CAAC,CAAM,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;IAI5C;;OAEG;gBACS,IAAI,EAAE,SAAS,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,YAAK,EAAE,kBAAkB,EAAE,MAAM;IAoBrE;;OAEG;IACH,IAAI,GAAG,IAAI,EAAE,CAAC,GAAG,CAAC,CAEjB;IAED;;OAEG;IACH,IAAI,OAAO,IAAI,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,CAEnC;IAED;;OAEG;IACH,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,CAAC,GAAG,MAAM;IAMjD;;OAEG;IACH,KAAK,EAAE,WAAW,CAqJhB;CACH;AAUD,KAAK,MAAM,CAAC,CAAC,SAAS,GAAG,IAAI,WAAW,CAAC,CAAC,CAAC,CAAC"}
1
+ {"version":3,"file":"bloop.d.ts","sourceRoot":"","sources":["../src/bloop.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAQjD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,OAAO,CAAC;AACzC,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAEvC,MAAM,MAAM,SAAS,CAAC,CAAC,SAAS,GAAG,IAAI;IACrC,yBAAyB;IACzB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;;OAIG;IAEH;;OAEG;IAEH;;;OAGG;IACH,GAAG,CAAC,EAAE,CAAC,CAAC;CAET,CAAC;AAEF,qBAAa,KAAK,CAAC,EAAE,SAAS,WAAW;;IAKvC;;OAEG;IACH,MAAM,CAAC,MAAM,CAGX,CAAC,SAAS,GAAG,EAGb,IAAI,GAAE,SAAS,CAAC,CAAC,CAAM,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;IAI5C;;OAEG;gBACS,IAAI,EAAE,SAAS,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,YAAK,EAAE,kBAAkB,EAAE,MAAM;IAoBrE;;OAEG;IACH,IAAI,GAAG,IAAI,EAAE,CAAC,GAAG,CAAC,CAEjB;IAED;;OAEG;IACH,IAAI,OAAO,IAAI,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,CAEnC;IAED;;OAEG;IACH,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,CAAC,GAAG,MAAM;IAMjD;;OAEG;IACH,KAAK,EAAE,WAAW,CAmNhB;CACH;AAUD,KAAK,MAAM,CAAC,CAAC,SAAS,GAAG,IAAI,WAAW,CAAC,CAAC,CAAC,CAAC"}
package/dist/mod.js CHANGED
@@ -104,6 +104,7 @@ var __export2 = (target, all) => {
104
104
  };
105
105
  var exports_enums = {};
106
106
  __export2(exports_enums, {
107
+ NetJoinFailReason: () => NetJoinFailReason,
107
108
  MouseButton: () => MouseButton,
108
109
  Key: () => Key,
109
110
  InputSource: () => InputSource,
@@ -119,11 +120,13 @@ var EventType;
119
120
  EventType2[EventType2["MouseUp"] = 5] = "MouseUp";
120
121
  EventType2[EventType2["MouseWheel"] = 6] = "MouseWheel";
121
122
  EventType2[EventType2["FrameStart"] = 7] = "FrameStart";
122
- EventType2[EventType2["SessionInit"] = 8] = "SessionInit";
123
- EventType2[EventType2["SessionSetLocalPeer"] = 9] = "SessionSetLocalPeer";
124
- EventType2[EventType2["SessionConnectPeer"] = 10] = "SessionConnectPeer";
125
- EventType2[EventType2["SessionDisconnectPeer"] = 11] = "SessionDisconnectPeer";
126
- EventType2[EventType2["SessionEnd"] = 12] = "SessionEnd";
123
+ EventType2[EventType2["NetJoinOk"] = 8] = "NetJoinOk";
124
+ EventType2[EventType2["NetJoinFail"] = 9] = "NetJoinFail";
125
+ EventType2[EventType2["NetPeerJoin"] = 10] = "NetPeerJoin";
126
+ EventType2[EventType2["NetPeerLeave"] = 11] = "NetPeerLeave";
127
+ EventType2[EventType2["NetPeerAssignLocalId"] = 12] = "NetPeerAssignLocalId";
128
+ EventType2[EventType2["NetPacketReceived"] = 13] = "NetPacketReceived";
129
+ EventType2[EventType2["NetSessionInit"] = 14] = "NetSessionInit";
127
130
  })(EventType ||= {});
128
131
  var MouseButton;
129
132
  ((MouseButton2) => {
@@ -367,6 +370,14 @@ var InputSource;
367
370
  InputSource2[InputSource2["RemotePeer11"] = 139] = "RemotePeer11";
368
371
  InputSource2[InputSource2["Unmapped"] = 255] = "Unmapped";
369
372
  })(InputSource ||= {});
373
+ var NetJoinFailReason;
374
+ ((NetJoinFailReason2) => {
375
+ NetJoinFailReason2[NetJoinFailReason2["unknown"] = 0] = "unknown";
376
+ NetJoinFailReason2[NetJoinFailReason2["timeout"] = 1] = "timeout";
377
+ NetJoinFailReason2[NetJoinFailReason2["room_full"] = 2] = "room_full";
378
+ NetJoinFailReason2[NetJoinFailReason2["room_not_found"] = 3] = "room_not_found";
379
+ NetJoinFailReason2[NetJoinFailReason2["already_in_room"] = 4] = "already_in_room";
380
+ })(NetJoinFailReason ||= {});
370
381
  var MAX_PLAYERS = 12;
371
382
  var KEYBOARD_OFFSET = 0;
372
383
  var KEYBOARD_SIZE = 256;
@@ -1120,30 +1131,171 @@ class KeyboardContext {
1120
1131
  return state;
1121
1132
  }
1122
1133
  }
1134
+ var MAX_PEERS = 12;
1135
+ var PEERS_ARRAY_OFFSET = 32;
1136
+ var PEER_CTX_SIZE = 8;
1137
+ var PEER_CONNECTED_OFFSET = 0;
1138
+ var PEER_PACKET_COUNT_OFFSET = 1;
1139
+ var PEER_SEQ_OFFSET = 2;
1140
+ var PEER_ACK_OFFSET = 4;
1141
+ var PEER_ACK_COUNT_OFFSET = 6;
1142
+ var STATUS_MAP = {
1143
+ 0: "offline",
1144
+ 1: "local",
1145
+ 2: "join:pending",
1146
+ 3: "connected",
1147
+ 4: "disconnected"
1148
+ };
1123
1149
 
1124
1150
  class NetContext {
1125
1151
  dataView;
1152
+ #peers = Array.from({ length: MAX_PEERS }, () => ({
1153
+ isLocal: false,
1154
+ seq: -1,
1155
+ ack: -1
1156
+ }));
1157
+ #peersResult = [];
1126
1158
  constructor(dataView) {
1127
1159
  this.dataView = dataView;
1128
1160
  }
1161
+ #hasValidBuffer() {
1162
+ if (!this.dataView)
1163
+ return false;
1164
+ return this.dataView.buffer.byteLength > 0;
1165
+ }
1129
1166
  get peerCount() {
1130
- if (!this.dataView) {
1131
- throw new Error("NetContext DataView is not initialized");
1167
+ if (!this.#hasValidBuffer()) {
1168
+ throw new Error("NetContext dataView is not valid");
1132
1169
  }
1133
1170
  return this.dataView.getUint8(0);
1134
1171
  }
1172
+ get localPeerId() {
1173
+ if (!this.#hasValidBuffer()) {
1174
+ throw new Error("NetContext dataView is not valid");
1175
+ }
1176
+ return this.dataView.getUint8(1);
1177
+ }
1135
1178
  get isInSession() {
1136
- if (!this.dataView) {
1137
- throw new Error("NetContext DataView is not initialized");
1179
+ if (!this.#hasValidBuffer()) {
1180
+ throw new Error("NetContext dataView is not valid");
1138
1181
  }
1139
1182
  return this.dataView.getUint8(2) !== 0;
1140
1183
  }
1184
+ get status() {
1185
+ if (!this.#hasValidBuffer()) {
1186
+ throw new Error("NetContext dataView is not valid");
1187
+ }
1188
+ const statusByte = this.dataView.getUint8(3);
1189
+ return STATUS_MAP[statusByte] ?? "local";
1190
+ }
1141
1191
  get matchFrame() {
1142
- if (!this.dataView) {
1143
- throw new Error("NetContext DataView is not initialized");
1192
+ if (!this.#hasValidBuffer()) {
1193
+ throw new Error("NetContext dataView is not valid");
1144
1194
  }
1145
1195
  return this.dataView.getUint32(4, true);
1146
1196
  }
1197
+ get sessionStartFrame() {
1198
+ if (!this.#hasValidBuffer()) {
1199
+ throw new Error("NetContext dataView is not valid");
1200
+ }
1201
+ return this.dataView.getUint32(8, true);
1202
+ }
1203
+ get roomCode() {
1204
+ if (!this.#hasValidBuffer()) {
1205
+ throw new Error("NetContext dataView is not valid");
1206
+ }
1207
+ const bytes = [];
1208
+ for (let i = 0;i < 8; i++) {
1209
+ const byte = this.dataView.getUint8(12 + i);
1210
+ if (byte === 0)
1211
+ break;
1212
+ bytes.push(byte);
1213
+ }
1214
+ return String.fromCharCode(...bytes);
1215
+ }
1216
+ get wantsRoomCode() {
1217
+ if (!this.#hasValidBuffer()) {
1218
+ return;
1219
+ }
1220
+ const bytes = [];
1221
+ for (let i = 0;i < 8; i++) {
1222
+ const byte = this.dataView.getUint8(20 + i);
1223
+ if (byte === 0)
1224
+ break;
1225
+ bytes.push(byte);
1226
+ }
1227
+ return bytes.length > 0 ? String.fromCharCode(...bytes) : undefined;
1228
+ }
1229
+ set wantsRoomCode(code) {
1230
+ if (!this.#hasValidBuffer()) {
1231
+ throw new Error("NetContext dataView is not valid");
1232
+ }
1233
+ for (let i = 0;i < 8; i++) {
1234
+ this.dataView.setUint8(20 + i, 0);
1235
+ }
1236
+ if (code) {
1237
+ for (let i = 0;i < Math.min(code.length, 7); i++) {
1238
+ this.dataView.setUint8(20 + i, code.charCodeAt(i));
1239
+ }
1240
+ }
1241
+ }
1242
+ get wantsDisconnect() {
1243
+ if (!this.#hasValidBuffer()) {
1244
+ return false;
1245
+ }
1246
+ return this.dataView.getUint8(28) !== 0;
1247
+ }
1248
+ set wantsDisconnect(value) {
1249
+ if (!this.#hasValidBuffer()) {
1250
+ throw new Error("NetContext dataView is not valid");
1251
+ }
1252
+ this.dataView.setUint8(28, value ? 1 : 0);
1253
+ }
1254
+ get peers() {
1255
+ if (!this.#hasValidBuffer()) {
1256
+ throw new Error("NetContext dataView is not valid");
1257
+ }
1258
+ const dv = this.dataView;
1259
+ const localPeerId = this.localPeerId;
1260
+ const matchFrame = this.matchFrame;
1261
+ let minRemoteSeq = -1;
1262
+ for (let i = 0;i < MAX_PEERS; i++) {
1263
+ if (i === localPeerId)
1264
+ continue;
1265
+ const peerOffset = PEERS_ARRAY_OFFSET + i * PEER_CTX_SIZE;
1266
+ if (dv.getUint8(peerOffset + PEER_CONNECTED_OFFSET) !== 1)
1267
+ continue;
1268
+ if (dv.getUint8(peerOffset + PEER_PACKET_COUNT_OFFSET) === 0)
1269
+ continue;
1270
+ const seq = dv.getUint16(peerOffset + PEER_SEQ_OFFSET, true);
1271
+ if (minRemoteSeq === -1 || seq < minRemoteSeq) {
1272
+ minRemoteSeq = seq;
1273
+ }
1274
+ }
1275
+ this.#peersResult.length = 0;
1276
+ for (let i = 0;i < MAX_PEERS; i++) {
1277
+ const peerOffset = PEERS_ARRAY_OFFSET + i * PEER_CTX_SIZE;
1278
+ if (dv.getUint8(peerOffset + PEER_CONNECTED_OFFSET) !== 1)
1279
+ continue;
1280
+ const peer = this.#peers[i];
1281
+ if (!peer) {
1282
+ throw new Error(`Unexpected missing peer object at index ${i}`);
1283
+ }
1284
+ const isLocal = i === localPeerId;
1285
+ peer.isLocal = isLocal;
1286
+ if (isLocal) {
1287
+ peer.seq = matchFrame;
1288
+ peer.ack = minRemoteSeq;
1289
+ } else {
1290
+ const packetCount = dv.getUint8(peerOffset + PEER_PACKET_COUNT_OFFSET);
1291
+ const ackCount = dv.getUint8(peerOffset + PEER_ACK_COUNT_OFFSET);
1292
+ peer.seq = packetCount === 0 ? -1 : dv.getUint16(peerOffset + PEER_SEQ_OFFSET, true);
1293
+ peer.ack = ackCount === 0 ? -1 : dv.getUint16(peerOffset + PEER_ACK_OFFSET, true);
1294
+ }
1295
+ this.#peersResult.push(peer);
1296
+ }
1297
+ return this.#peersResult;
1298
+ }
1147
1299
  }
1148
1300
 
1149
1301
  class TimeContext {
@@ -1185,7 +1337,7 @@ function readTapeHeader(tape) {
1185
1337
  eventCount: view.getUint16(14, true)
1186
1338
  };
1187
1339
  }
1188
- var DEFAULT_WASM_URL = new URL("https://unpkg.com/@bloopjs/engine@0.0.79/wasm/bloop.wasm");
1340
+ var DEFAULT_WASM_URL = new URL("https://unpkg.com/@bloopjs/engine@0.0.81/wasm/bloop.wasm");
1189
1341
  var MAX_ROLLBACK_FRAMES = 500;
1190
1342
  var TIME_CTX_OFFSET = 0;
1191
1343
  var INPUT_CTX_OFFSET = TIME_CTX_OFFSET + 4;
@@ -1194,64 +1346,6 @@ var NET_CTX_OFFSET = EVENTS_OFFSET + 4;
1194
1346
  var SNAPSHOT_HEADER_LEN = 16;
1195
1347
  var SNAPSHOT_HEADER_USER_LEN_OFFSET = 4;
1196
1348
  var SNAPSHOT_HEADER_ENGINE_LEN_OFFSET = 8;
1197
- // src/net.ts
1198
- class Net {
1199
- #wasm;
1200
- #memory;
1201
- constructor(wasm, memory) {
1202
- this.#wasm = wasm;
1203
- this.#memory = memory;
1204
- }
1205
- setLocalPeer(peerId) {
1206
- this.#wasm.session_set_local_peer(peerId);
1207
- }
1208
- connectPeer(peerId) {
1209
- this.#wasm.session_peer_connect(peerId);
1210
- }
1211
- disconnectPeer(peerId) {
1212
- this.#wasm.session_peer_disconnect(peerId);
1213
- }
1214
- getOutboundPacket(targetPeer) {
1215
- this.#wasm.build_outbound_packet(targetPeer);
1216
- const len = this.#wasm.get_outbound_packet_len();
1217
- if (len === 0) {
1218
- return null;
1219
- }
1220
- const ptr = this.#wasm.get_outbound_packet();
1221
- assert(ptr > 0, `Invalid outbound packet pointer: ${ptr}`);
1222
- const memoryView = new Uint8Array(this.#memory.buffer, ptr, len);
1223
- const copy = new Uint8Array(len);
1224
- copy.set(memoryView);
1225
- return copy;
1226
- }
1227
- receivePacket(data) {
1228
- if (data.length === 0) {
1229
- return;
1230
- }
1231
- const ptr = this.#wasm.alloc(data.byteLength);
1232
- assert(ptr > 0, `Failed to allocate ${data.byteLength} bytes for received packet`);
1233
- const memoryView = new Uint8Array(this.#memory.buffer, ptr, data.byteLength);
1234
- memoryView.set(data);
1235
- const result = this.#wasm.receive_packet(ptr, data.byteLength);
1236
- this.#wasm.free(ptr, data.byteLength);
1237
- if (result !== 0) {
1238
- const errorMessages = {
1239
- 1: "No active session",
1240
- 2: "Buffer too small",
1241
- 3: "Unsupported packet version",
1242
- 4: "Invalid event count"
1243
- };
1244
- throw new Error(errorMessages[result] ?? `Unknown packet error: ${result}`);
1245
- }
1246
- }
1247
- getPeerState(peer) {
1248
- return {
1249
- seq: this.#wasm.get_peer_seq(peer),
1250
- ack: this.#wasm.get_peer_ack(peer)
1251
- };
1252
- }
1253
- }
1254
-
1255
1349
  // src/sim.ts
1256
1350
  var originalConsole = globalThis.console;
1257
1351
  var noop = () => {};
@@ -1270,7 +1364,7 @@ class Sim {
1270
1364
  #time;
1271
1365
  #serialize;
1272
1366
  #isPaused = false;
1273
- net;
1367
+ #net;
1274
1368
  onTapeFull;
1275
1369
  constructor(wasm, memory, opts) {
1276
1370
  this.wasm = wasm;
@@ -1278,7 +1372,7 @@ class Sim {
1278
1372
  this.#time = new TimeContext(new DataView(this.#memory.buffer, this.wasm.get_time_ctx()));
1279
1373
  this.id = `${Math.floor(Math.random() * 1e6)}`;
1280
1374
  this.#serialize = opts?.serialize;
1281
- this.net = new Net(wasm, memory);
1375
+ this.#net = new NetContext;
1282
1376
  }
1283
1377
  step(ms) {
1284
1378
  if (this.#isPaused) {
@@ -1359,7 +1453,9 @@ class Sim {
1359
1453
  assert(tapePtr > 0, `failed to allocate ${tape.byteLength} bytes for tape load, pointer=${tapePtr}`);
1360
1454
  const memoryView = new Uint8Array(this.#memory.buffer, tapePtr, tape.byteLength);
1361
1455
  memoryView.set(tape);
1362
- this.wasm.stop_recording();
1456
+ if (this.isRecording) {
1457
+ this.wasm.stop_recording();
1458
+ }
1363
1459
  const result = this.wasm.load_tape(tapePtr, tape.byteLength);
1364
1460
  assert(result === 0, `failed to load tape, error code=${result}`);
1365
1461
  this.wasm.free(tapePtr, tape.byteLength);
@@ -1381,6 +1477,12 @@ class Sim {
1381
1477
  }
1382
1478
  return this.#time;
1383
1479
  }
1480
+ get net() {
1481
+ if (!this.#net.dataView || this.#net.dataView.buffer !== this.#memory.buffer) {
1482
+ this.#net.dataView = new DataView(this.#memory.buffer, this.wasm.get_net_ctx());
1483
+ }
1484
+ return this.#net;
1485
+ }
1384
1486
  get buffer() {
1385
1487
  return this.#memory.buffer;
1386
1488
  }
@@ -1411,16 +1513,77 @@ class Sim {
1411
1513
  },
1412
1514
  mousewheel: (x, y, peerId = 0) => {
1413
1515
  this.wasm.emit_mousewheel(x, y, peerId);
1516
+ },
1517
+ network: (type, data) => {
1518
+ switch (type) {
1519
+ case "join:ok": {
1520
+ const roomCode = data.roomCode;
1521
+ const encoded = new TextEncoder().encode(roomCode);
1522
+ const ptr = this.wasm.alloc(encoded.length);
1523
+ new Uint8Array(this.#memory.buffer, ptr, encoded.length).set(encoded);
1524
+ this.wasm.emit_net_join_ok(ptr, encoded.length);
1525
+ this.wasm.free(ptr, encoded.length);
1526
+ break;
1527
+ }
1528
+ case "join:fail":
1529
+ this.wasm.emit_net_join_fail(0);
1530
+ break;
1531
+ case "peer:join": {
1532
+ const peerId = data.peerId;
1533
+ this.wasm.emit_net_peer_join(peerId);
1534
+ break;
1535
+ }
1536
+ case "peer:leave": {
1537
+ const peerId = data.peerId;
1538
+ this.wasm.emit_net_peer_leave(peerId);
1539
+ break;
1540
+ }
1541
+ case "peer:assign_local_id": {
1542
+ const peerId = data.peerId;
1543
+ this.wasm.emit_net_peer_assign_local_id(peerId);
1544
+ break;
1545
+ }
1546
+ case "session:start":
1547
+ this.wasm.emit_net_session_init();
1548
+ break;
1549
+ case "session:end":
1550
+ this.wasm.emit_net_session_end();
1551
+ break;
1552
+ }
1553
+ },
1554
+ packet: (data) => {
1555
+ if (data.length === 0) {
1556
+ return;
1557
+ }
1558
+ const ptr = this.wasm.alloc(data.byteLength);
1559
+ assert(ptr > 0, `Failed to allocate ${data.byteLength} bytes for received packet`);
1560
+ const memoryView = new Uint8Array(this.#memory.buffer, ptr, data.byteLength);
1561
+ memoryView.set(data);
1562
+ const result = this.wasm.emit_receive_packet(ptr, data.byteLength);
1563
+ this.wasm.free(ptr, data.byteLength);
1564
+ if (result !== 0) {
1565
+ const errorMessages = {
1566
+ 1: "No active session",
1567
+ 2: "Buffer too small",
1568
+ 3: "Unsupported packet version",
1569
+ 4: "Invalid event count"
1570
+ };
1571
+ throw new Error(errorMessages[result] ?? `Unknown packet error: ${result}`);
1572
+ }
1414
1573
  }
1415
1574
  };
1416
- sessionInit(peerCount) {
1417
- const serializer = this.#serialize ? this.#serialize() : null;
1418
- const size = serializer ? serializer.size : 0;
1419
- const result = this.wasm.session_init(peerCount, size);
1420
- assert(result === 0, `failed to initialize session, error code=${result}`);
1421
- }
1422
- sessionEnd() {
1423
- this.wasm.session_end();
1575
+ getOutboundPacket(targetPeer) {
1576
+ this.wasm.build_outbound_packet(targetPeer);
1577
+ const len = this.wasm.get_outbound_packet_len();
1578
+ if (len === 0) {
1579
+ throw new Error(`No outbound packet available for peer ${targetPeer}`);
1580
+ }
1581
+ const ptr = this.wasm.get_outbound_packet();
1582
+ assert(ptr > 0, `Invalid outbound packet pointer: ${ptr}`);
1583
+ const memoryView = new Uint8Array(this.#memory.buffer, ptr, len);
1584
+ const copy = new Uint8Array(len);
1585
+ copy.set(memoryView);
1586
+ return copy;
1424
1587
  }
1425
1588
  }
1426
1589
 
@@ -1641,8 +1804,59 @@ class Bloop {
1641
1804
  y: payloadVec2.y
1642
1805
  }));
1643
1806
  break;
1807
+ case exports_enums.EventType.NetJoinOk: {
1808
+ const roomCodeBytes = [];
1809
+ for (let j = 0;j < 8; j++) {
1810
+ const byte = eventsDataView.getUint8(payloadOffset + j);
1811
+ if (byte === 0)
1812
+ break;
1813
+ roomCodeBytes.push(byte);
1814
+ }
1815
+ const roomCode = String.fromCharCode(...roomCodeBytes);
1816
+ this.#context.event = {
1817
+ type: "join:ok",
1818
+ data: { roomCode }
1819
+ };
1820
+ system.netcode?.(this.#context);
1821
+ break;
1822
+ }
1823
+ case exports_enums.EventType.NetJoinFail: {
1824
+ const reasonCode = eventsDataView.getUint8(payloadOffset);
1825
+ const reasons = [
1826
+ "unknown",
1827
+ "timeout",
1828
+ "room_full",
1829
+ "room_not_found",
1830
+ "already_in_room"
1831
+ ];
1832
+ const reason = reasons[reasonCode] ?? "unknown";
1833
+ this.#context.event = {
1834
+ type: "join:fail",
1835
+ data: { reason }
1836
+ };
1837
+ system.netcode?.(this.#context);
1838
+ break;
1839
+ }
1840
+ case exports_enums.EventType.NetPeerJoin: {
1841
+ const peerId = eventsDataView.getUint8(payloadOffset);
1842
+ this.#context.event = {
1843
+ type: "peer:join",
1844
+ data: { peerId }
1845
+ };
1846
+ system.netcode?.(this.#context);
1847
+ break;
1848
+ }
1849
+ case exports_enums.EventType.NetPeerLeave: {
1850
+ const peerId = eventsDataView.getUint8(payloadOffset);
1851
+ this.#context.event = {
1852
+ type: "peer:leave",
1853
+ data: { peerId }
1854
+ };
1855
+ system.netcode?.(this.#context);
1856
+ break;
1857
+ }
1644
1858
  default:
1645
- throw new Error(`Unknown event type: ${eventType}`);
1859
+ break;
1646
1860
  }
1647
1861
  offset += 12;
1648
1862
  }
@@ -1665,5 +1879,5 @@ export {
1665
1879
  Bloop
1666
1880
  };
1667
1881
 
1668
- //# debugId=D8698C30FEA349E064756E2164756E21
1882
+ //# debugId=11E88A9DA26FCC9364756E2164756E21
1669
1883
  //# sourceMappingURL=mod.js.map