@bloopjs/bloop 0.0.88 → 0.0.90

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":"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"}
1
+ {"version":3,"file":"bloop.d.ts","sourceRoot":"","sources":["../src/bloop.ts"],"names":[],"mappings":"AAiBA,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;AASjD,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;IAqBrE;;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,CAuQhB;CACH;AAUD,KAAK,MAAM,CAAC,CAAC,SAAS,GAAG,IAAI,WAAW,CAAC,CAAC,CAAC,CAAC"}
package/dist/context.d.ts CHANGED
@@ -1,5 +1,6 @@
1
- import type { EnginePointer, InputContext, NetContext, PlayerInputContext, TimeContext } from "@bloopjs/engine";
1
+ import type { EnginePointer, InputContext, NetContext, ScreenContext, TimeContext } from "@bloopjs/engine";
2
2
  import type { BloopSchema } from "./data/schema";
3
+ import type { Players } from "./players";
3
4
  export type Context<GS extends BloopSchema = BloopSchema> = {
4
5
  /** The wrapper to the engine instance */
5
6
  /** Result of any resources requested */
@@ -12,13 +13,16 @@ export type Context<GS extends BloopSchema = BloopSchema> = {
12
13
  /** The input snapshot */
13
14
  inputs: InputContext;
14
15
  /**
15
- * Per-player input states. Shorthand for inputs.players.
16
- * Access via: context.players[0].keys.a.held
16
+ * Per-player input states.
17
+ * Access via: context.players.get(0).keys.a.held
18
+ * Iterate connected players: for (const p of context.players) { ... }
17
19
  */
18
- players: readonly PlayerInputContext[];
20
+ players: Players;
19
21
  /** The engine pointer to the injected system arguments (for advanced use cases) */
20
22
  rawPointer: EnginePointer;
21
23
  /** Network context for multiplayer sessions */
22
24
  net: NetContext;
25
+ /** Screen/viewport dimensions and pixel ratio */
26
+ screen: ScreenContext;
23
27
  };
24
28
  //# sourceMappingURL=context.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,aAAa,EACb,YAAY,EACZ,UAAU,EACV,kBAAkB,EAClB,WAAW,EACZ,MAAM,iBAAiB,CAAC;AACzB,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAEjD,MAAM,MAAM,OAAO,CACjB,EAAE,SAAS,WAAW,GAAG,WAAW,IAGlC;IACF,yCAAyC;IAEzC,wCAAwC;IAExC,gDAAgD;IAEhD,oDAAoD;IAEpD,uCAAuC;IACvC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC;IACb,mDAAmD;IACnD,IAAI,EAAE,WAAW,CAAC;IAClB,yBAAyB;IACzB,MAAM,EAAE,YAAY,CAAC;IACrB;;;OAGG;IACH,OAAO,EAAE,SAAS,kBAAkB,EAAE,CAAC;IACvC,mFAAmF;IACnF,UAAU,EAAE,aAAa,CAAC;IAC1B,+CAA+C;IAC/C,GAAG,EAAE,UAAU,CAAC;CACjB,CAAC"}
1
+ {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,aAAa,EACb,YAAY,EACZ,UAAU,EACV,aAAa,EACb,WAAW,EACZ,MAAM,iBAAiB,CAAC;AACzB,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AACjD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEzC,MAAM,MAAM,OAAO,CACjB,EAAE,SAAS,WAAW,GAAG,WAAW,IAGlC;IACF,yCAAyC;IAEzC,wCAAwC;IAExC,gDAAgD;IAEhD,oDAAoD;IAEpD,uCAAuC;IACvC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC;IACb,mDAAmD;IACnD,IAAI,EAAE,WAAW,CAAC;IAClB,yBAAyB;IACzB,MAAM,EAAE,YAAY,CAAC;IACrB;;;;OAIG;IACH,OAAO,EAAE,OAAO,CAAC;IACjB,mFAAmF;IACnF,UAAU,EAAE,aAAa,CAAC;IAC1B,+CAA+C;IAC/C,GAAG,EAAE,UAAU,CAAC;IAChB,iDAAiD;IACjD,MAAM,EAAE,aAAa,CAAC;CACvB,CAAC"}
package/dist/events.d.ts CHANGED
@@ -14,4 +14,12 @@ export type MouseWheelEvent = {
14
14
  x: number;
15
15
  y: number;
16
16
  };
17
+ export type ResizeEvent = {
18
+ width: number;
19
+ height: number;
20
+ physicalWidth: number;
21
+ physicalHeight: number;
22
+ pixelRatio: number;
23
+ };
24
+ export type BloopEvent = InputEvent | ResizeEvent;
17
25
  //# sourceMappingURL=events.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"events.d.ts","sourceRoot":"","sources":["../src/events.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAExD,MAAM,MAAM,UAAU,GAClB,QAAQ,GACR,gBAAgB,GAChB,cAAc,GACd,eAAe,CAAC;AAEpB,MAAM,MAAM,QAAQ,GAAG;IACrB,GAAG,EAAE,GAAG,CAAC;CACV,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,MAAM,EAAE,WAAW,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG;IAC3B,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;CACX,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG;IAC5B,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;CACX,CAAC"}
1
+ {"version":3,"file":"events.d.ts","sourceRoot":"","sources":["../src/events.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAExD,MAAM,MAAM,UAAU,GAClB,QAAQ,GACR,gBAAgB,GAChB,cAAc,GACd,eAAe,CAAC;AAEpB,MAAM,MAAM,QAAQ,GAAG;IACrB,GAAG,EAAE,GAAG,CAAC;CACV,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,MAAM,EAAE,WAAW,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG;IAC3B,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;CACX,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG;IAC5B,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;CACX,CAAC;AAEF,MAAM,MAAM,WAAW,GAAG;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,aAAa,EAAE,MAAM,CAAC;IACtB,cAAc,EAAE,MAAM,CAAC;IACvB,UAAU,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF,MAAM,MAAM,UAAU,GAAG,UAAU,GAAG,WAAW,CAAC"}
package/dist/mod.d.ts CHANGED
@@ -4,4 +4,5 @@ export { unwrap, assert } from "./util";
4
4
  export { mount, type Mountable, type MountOptions } from "./mount";
5
5
  export { Bloop } from "./bloop";
6
6
  export { Sim, type LoadTapeOptions } from "./sim";
7
+ export { Players } from "./players";
7
8
  //# sourceMappingURL=mod.d.ts.map
package/dist/mod.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"mod.d.ts","sourceRoot":"","sources":["../src/mod.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,IAAI,MAAM,QAAQ,CAAC;AAC/B,OAAO,KAAK,MAAM,MAAM,iBAAiB,CAAC;AAE1C,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAExC,OAAO,EAAE,KAAK,EAAE,KAAK,SAAS,EAAE,KAAK,YAAY,EAAE,MAAM,SAAS,CAAC;AACnE,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAChC,OAAO,EAAE,GAAG,EAAE,KAAK,eAAe,EAAE,MAAM,OAAO,CAAC"}
1
+ {"version":3,"file":"mod.d.ts","sourceRoot":"","sources":["../src/mod.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,IAAI,MAAM,QAAQ,CAAC;AAC/B,OAAO,KAAK,MAAM,MAAM,iBAAiB,CAAC;AAE1C,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAExC,OAAO,EAAE,KAAK,EAAE,KAAK,SAAS,EAAE,KAAK,YAAY,EAAE,MAAM,SAAS,CAAC;AACnE,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAChC,OAAO,EAAE,GAAG,EAAE,KAAK,eAAe,EAAE,MAAM,OAAO,CAAC;AAClD,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC"}
package/dist/mod.js CHANGED
@@ -68,21 +68,28 @@ __export(exports_engine, {
68
68
  inputSourceCodeToInputSource: () => inputSourceCodeToInputSource,
69
69
  TimeContext: () => TimeContext,
70
70
  TIME_CTX_OFFSET: () => TIME_CTX_OFFSET,
71
+ ScreenContext: () => ScreenContext,
71
72
  SNAPSHOT_HEADER_USER_LEN_OFFSET: () => SNAPSHOT_HEADER_USER_LEN_OFFSET,
72
73
  SNAPSHOT_HEADER_LEN: () => SNAPSHOT_HEADER_LEN,
73
74
  SNAPSHOT_HEADER_ENGINE_LEN_OFFSET: () => SNAPSHOT_HEADER_ENGINE_LEN_OFFSET,
75
+ SCREEN_CTX_OFFSET: () => SCREEN_CTX_OFFSET,
74
76
  PlayerInputContext: () => PlayerInputContext,
75
77
  PLAYER_INPUTS_SIZE: () => PLAYER_INPUTS_SIZE,
78
+ PLAYER_INPUTS_MOUSE_CTX_OFFSET: () => PLAYER_INPUTS_MOUSE_CTX_OFFSET,
79
+ PLAYER_INPUTS_KEY_CTX_OFFSET: () => PLAYER_INPUTS_KEY_CTX_OFFSET,
76
80
  NetContext: () => NetContext,
77
81
  NET_CTX_OFFSET: () => NET_CTX_OFFSET,
78
82
  MouseContext: () => MouseContext,
79
- MOUSE_OFFSET: () => MOUSE_OFFSET,
80
- MOUSE_BUTTONS_OFFSET: () => MOUSE_BUTTONS_OFFSET,
83
+ MOUSE_OFFSET: () => PLAYER_INPUTS_MOUSE_CTX_OFFSET,
84
+ MOUSE_CTX_SIZE: () => MOUSE_CTX_SIZE,
85
+ MOUSE_CTX_BUTTON_STATES_OFFSET: () => MOUSE_CTX_BUTTON_STATES_OFFSET,
86
+ MOUSE_BUTTONS_OFFSET: () => MOUSE_CTX_BUTTON_STATES_OFFSET,
81
87
  MAX_ROLLBACK_FRAMES: () => MAX_ROLLBACK_FRAMES,
82
88
  MAX_PLAYERS: () => MAX_PLAYERS,
83
89
  KeyboardContext: () => KeyboardContext,
84
- KEYBOARD_SIZE: () => KEYBOARD_SIZE,
85
- KEYBOARD_OFFSET: () => KEYBOARD_OFFSET,
90
+ KEY_CTX_SIZE: () => KEY_CTX_SIZE,
91
+ KEYBOARD_SIZE: () => KEY_CTX_SIZE,
92
+ KEYBOARD_OFFSET: () => PLAYER_INPUTS_KEY_CTX_OFFSET,
86
93
  InputContext: () => InputContext,
87
94
  INPUT_CTX_SIZE: () => INPUT_CTX_SIZE,
88
95
  INPUT_CTX_OFFSET: () => INPUT_CTX_OFFSET,
@@ -127,6 +134,7 @@ var EventType;
127
134
  EventType2[EventType2["NetPeerAssignLocalId"] = 12] = "NetPeerAssignLocalId";
128
135
  EventType2[EventType2["NetPacketReceived"] = 13] = "NetPacketReceived";
129
136
  EventType2[EventType2["NetSessionInit"] = 14] = "NetSessionInit";
137
+ EventType2[EventType2["Resize"] = 15] = "Resize";
130
138
  })(EventType ||= {});
131
139
  var MouseButton;
132
140
  ((MouseButton2) => {
@@ -378,33 +386,43 @@ var NetJoinFailReason;
378
386
  NetJoinFailReason2[NetJoinFailReason2["room_not_found"] = 3] = "room_not_found";
379
387
  NetJoinFailReason2[NetJoinFailReason2["already_in_room"] = 4] = "already_in_room";
380
388
  })(NetJoinFailReason ||= {});
381
- var MAX_PLAYERS = 12;
382
- var KEYBOARD_OFFSET = 0;
383
- var KEYBOARD_SIZE = 256;
384
- var MOUSE_OFFSET = 256;
385
- var MOUSE_BUTTONS_OFFSET = 16;
389
+ var TIME_CTX_FRAME_OFFSET = 0;
390
+ var TIME_CTX_DT_MS_OFFSET = 4;
391
+ var TIME_CTX_TOTAL_MS_OFFSET = 8;
392
+ var PEER_CTX_CONNECTED_OFFSET = 0;
393
+ var PEER_CTX_SEQ_OFFSET = 2;
394
+ var PEER_CTX_ACK_OFFSET = 4;
395
+ var PEER_CTX_SIZE = 8;
396
+ var NET_CTX_PEER_COUNT_OFFSET = 0;
397
+ var NET_CTX_LOCAL_PEER_ID_OFFSET = 1;
398
+ var NET_CTX_IN_SESSION_OFFSET = 2;
399
+ var NET_CTX_STATUS_OFFSET = 3;
400
+ var NET_CTX_MATCH_FRAME_OFFSET = 4;
401
+ var NET_CTX_SESSION_START_FRAME_OFFSET = 8;
402
+ var NET_CTX_ROOM_CODE_OFFSET = 12;
403
+ var NET_CTX_WANTS_ROOM_CODE_OFFSET = 20;
404
+ var NET_CTX_WANTS_DISCONNECT_OFFSET = 28;
405
+ var NET_CTX_PEERS_OFFSET = 32;
406
+ var NET_CTX_LAST_ROLLBACK_DEPTH_OFFSET = 128;
407
+ var NET_CTX_TOTAL_ROLLBACKS_OFFSET = 132;
408
+ var NET_CTX_FRAMES_RESIMULATED_OFFSET = 136;
409
+ var SCREEN_CTX_WIDTH_OFFSET = 0;
410
+ var SCREEN_CTX_HEIGHT_OFFSET = 4;
411
+ var SCREEN_CTX_PHYSICAL_WIDTH_OFFSET = 8;
412
+ var SCREEN_CTX_PHYSICAL_HEIGHT_OFFSET = 12;
413
+ var SCREEN_CTX_PIXEL_RATIO_OFFSET = 16;
414
+ var MOUSE_CTX_X_OFFSET = 0;
415
+ var MOUSE_CTX_Y_OFFSET = 4;
416
+ var MOUSE_CTX_WHEEL_X_OFFSET = 8;
417
+ var MOUSE_CTX_WHEEL_Y_OFFSET = 12;
418
+ var MOUSE_CTX_BUTTON_STATES_OFFSET = 16;
419
+ var MOUSE_CTX_SIZE = 24;
420
+ var KEY_CTX_SIZE = 256;
421
+ var PLAYER_INPUTS_KEY_CTX_OFFSET = 0;
422
+ var PLAYER_INPUTS_MOUSE_CTX_OFFSET = 256;
386
423
  var PLAYER_INPUTS_SIZE = 280;
387
- var INPUT_CTX_SIZE = MAX_PLAYERS * PLAYER_INPUTS_SIZE;
388
- var EVENT_PAYLOAD_SIZE = 8;
389
- var EVENT_PAYLOAD_ALIGN = 4;
390
- function keyToKeyCode(key) {
391
- return Key[key];
392
- }
393
- function keyCodeToKey(code) {
394
- return Key[code];
395
- }
396
- function mouseButtonToMouseButtonCode(button) {
397
- return MouseButton[button];
398
- }
399
- function mouseButtonCodeToMouseButton(code) {
400
- return MouseButton[code];
401
- }
402
- function inputSourceToInputSourceCode(source) {
403
- return InputSource[source];
404
- }
405
- function inputSourceCodeToInputSource(code) {
406
- return InputSource[code];
407
- }
424
+ var INPUT_CTX_SIZE = 3360;
425
+ var MAX_PLAYERS = 12;
408
426
 
409
427
  class PlayerInputContext {
410
428
  #dataView;
@@ -415,13 +433,13 @@ class PlayerInputContext {
415
433
  }
416
434
  get keys() {
417
435
  if (!this.#keys) {
418
- this.#keys = new KeyboardContext(new DataView(this.#dataView.buffer, this.#dataView.byteOffset + KEYBOARD_OFFSET));
436
+ this.#keys = new KeyboardContext(new DataView(this.#dataView.buffer, this.#dataView.byteOffset + PLAYER_INPUTS_KEY_CTX_OFFSET));
419
437
  }
420
438
  return this.#keys;
421
439
  }
422
440
  get mouse() {
423
441
  if (!this.#mouse) {
424
- this.#mouse = new MouseContext(new DataView(this.#dataView.buffer, this.#dataView.byteOffset + MOUSE_OFFSET));
442
+ this.#mouse = new MouseContext(new DataView(this.#dataView.buffer, this.#dataView.byteOffset + PLAYER_INPUTS_MOUSE_CTX_OFFSET));
425
443
  }
426
444
  return this.#mouse;
427
445
  }
@@ -446,6 +464,9 @@ class InputContext {
446
464
  this.#dataView = dataView;
447
465
  this.#buildPlayers();
448
466
  }
467
+ hasDataView() {
468
+ return !!this.#dataView;
469
+ }
449
470
  #buildPlayers() {
450
471
  this.#players = [];
451
472
  for (let i = 0;i < MAX_PLAYERS; i++) {
@@ -478,19 +499,19 @@ class MouseContext {
478
499
  this.#dataView = dataView;
479
500
  }
480
501
  get x() {
481
- return this.#dataView.getFloat32(0, true);
502
+ return this.#dataView.getFloat32(MOUSE_CTX_X_OFFSET, true);
482
503
  }
483
504
  get y() {
484
- return this.#dataView.getFloat32(4, true);
505
+ return this.#dataView.getFloat32(MOUSE_CTX_Y_OFFSET, true);
485
506
  }
486
507
  get wheel() {
487
508
  return { x: this.wheelX, y: this.wheelY };
488
509
  }
489
510
  get wheelX() {
490
- return this.#dataView.getFloat32(8, true);
511
+ return this.#dataView.getFloat32(MOUSE_CTX_WHEEL_X_OFFSET, true);
491
512
  }
492
513
  get wheelY() {
493
- return this.#dataView.getFloat32(12, true);
514
+ return this.#dataView.getFloat32(MOUSE_CTX_WHEEL_Y_OFFSET, true);
494
515
  }
495
516
  get left() {
496
517
  return this.#buttonState(1);
@@ -509,7 +530,7 @@ class MouseContext {
509
530
  state = { down: false, held: false, up: false };
510
531
  this.#buttonStates.set(code, state);
511
532
  }
512
- const offset = MOUSE_BUTTONS_OFFSET;
533
+ const offset = MOUSE_CTX_BUTTON_STATES_OFFSET;
513
534
  state.held = !!(this.#dataView.getUint8(offset + code) & 1);
514
535
  state.down = state.held && !(this.#dataView.getUint8(offset + code) & 2);
515
536
  state.up = !state.held && !!(this.#dataView.getUint8(offset + code) & 2);
@@ -1131,15 +1152,6 @@ class KeyboardContext {
1131
1152
  return state;
1132
1153
  }
1133
1154
  }
1134
- var MAX_PEERS = 12;
1135
- var PEERS_ARRAY_OFFSET = 32;
1136
- var PEER_CTX_SIZE = 8;
1137
- var LAST_ROLLBACK_DEPTH_OFFSET = 128;
1138
- var TOTAL_ROLLBACKS_OFFSET = 132;
1139
- var FRAMES_RESIMULATED_OFFSET = 136;
1140
- var PEER_CONNECTED_OFFSET = 0;
1141
- var PEER_SEQ_OFFSET = 2;
1142
- var PEER_ACK_OFFSET = 4;
1143
1155
  var STATUS_MAP = {
1144
1156
  0: "offline",
1145
1157
  1: "local",
@@ -1150,7 +1162,7 @@ var STATUS_MAP = {
1150
1162
 
1151
1163
  class NetContext {
1152
1164
  dataView;
1153
- #peers = Array.from({ length: MAX_PEERS }, () => ({
1165
+ #peers = Array.from({ length: MAX_PLAYERS }, () => ({
1154
1166
  isLocal: false,
1155
1167
  seq: -1,
1156
1168
  ack: -1
@@ -1168,38 +1180,38 @@ class NetContext {
1168
1180
  if (!this.#hasValidBuffer()) {
1169
1181
  throw new Error("NetContext dataView is not valid");
1170
1182
  }
1171
- return this.dataView.getUint8(0);
1183
+ return this.dataView.getUint8(NET_CTX_PEER_COUNT_OFFSET);
1172
1184
  }
1173
1185
  get localPeerId() {
1174
1186
  if (!this.#hasValidBuffer()) {
1175
1187
  throw new Error("NetContext dataView is not valid");
1176
1188
  }
1177
- return this.dataView.getUint8(1);
1189
+ return this.dataView.getUint8(NET_CTX_LOCAL_PEER_ID_OFFSET);
1178
1190
  }
1179
1191
  get isInSession() {
1180
1192
  if (!this.#hasValidBuffer()) {
1181
1193
  throw new Error("NetContext dataView is not valid");
1182
1194
  }
1183
- return this.dataView.getUint8(2) !== 0;
1195
+ return this.dataView.getUint8(NET_CTX_IN_SESSION_OFFSET) !== 0;
1184
1196
  }
1185
1197
  get status() {
1186
1198
  if (!this.#hasValidBuffer()) {
1187
1199
  throw new Error("NetContext dataView is not valid");
1188
1200
  }
1189
- const statusByte = this.dataView.getUint8(3);
1201
+ const statusByte = this.dataView.getUint8(NET_CTX_STATUS_OFFSET);
1190
1202
  return STATUS_MAP[statusByte] ?? "local";
1191
1203
  }
1192
1204
  get matchFrame() {
1193
1205
  if (!this.#hasValidBuffer()) {
1194
1206
  throw new Error("NetContext dataView is not valid");
1195
1207
  }
1196
- return this.dataView.getUint32(4, true);
1208
+ return this.dataView.getUint32(NET_CTX_MATCH_FRAME_OFFSET, true);
1197
1209
  }
1198
1210
  get sessionStartFrame() {
1199
1211
  if (!this.#hasValidBuffer()) {
1200
1212
  throw new Error("NetContext dataView is not valid");
1201
1213
  }
1202
- return this.dataView.getUint32(8, true);
1214
+ return this.dataView.getUint32(NET_CTX_SESSION_START_FRAME_OFFSET, true);
1203
1215
  }
1204
1216
  get roomCode() {
1205
1217
  if (!this.#hasValidBuffer()) {
@@ -1207,7 +1219,7 @@ class NetContext {
1207
1219
  }
1208
1220
  const bytes = [];
1209
1221
  for (let i = 0;i < 8; i++) {
1210
- const byte = this.dataView.getUint8(12 + i);
1222
+ const byte = this.dataView.getUint8(NET_CTX_ROOM_CODE_OFFSET + i);
1211
1223
  if (byte === 0)
1212
1224
  break;
1213
1225
  bytes.push(byte);
@@ -1220,7 +1232,7 @@ class NetContext {
1220
1232
  }
1221
1233
  const bytes = [];
1222
1234
  for (let i = 0;i < 8; i++) {
1223
- const byte = this.dataView.getUint8(20 + i);
1235
+ const byte = this.dataView.getUint8(NET_CTX_WANTS_ROOM_CODE_OFFSET + i);
1224
1236
  if (byte === 0)
1225
1237
  break;
1226
1238
  bytes.push(byte);
@@ -1232,11 +1244,11 @@ class NetContext {
1232
1244
  throw new Error("NetContext dataView is not valid");
1233
1245
  }
1234
1246
  for (let i = 0;i < 8; i++) {
1235
- this.dataView.setUint8(20 + i, 0);
1247
+ this.dataView.setUint8(NET_CTX_WANTS_ROOM_CODE_OFFSET + i, 0);
1236
1248
  }
1237
1249
  if (code) {
1238
1250
  for (let i = 0;i < Math.min(code.length, 7); i++) {
1239
- this.dataView.setUint8(20 + i, code.charCodeAt(i));
1251
+ this.dataView.setUint8(NET_CTX_WANTS_ROOM_CODE_OFFSET + i, code.charCodeAt(i));
1240
1252
  }
1241
1253
  }
1242
1254
  }
@@ -1244,13 +1256,13 @@ class NetContext {
1244
1256
  if (!this.#hasValidBuffer()) {
1245
1257
  return false;
1246
1258
  }
1247
- return this.dataView.getUint8(28) !== 0;
1259
+ return this.dataView.getUint8(NET_CTX_WANTS_DISCONNECT_OFFSET) !== 0;
1248
1260
  }
1249
1261
  set wantsDisconnect(value) {
1250
1262
  if (!this.#hasValidBuffer()) {
1251
1263
  throw new Error("NetContext dataView is not valid");
1252
1264
  }
1253
- this.dataView.setUint8(28, value ? 1 : 0);
1265
+ this.dataView.setUint8(NET_CTX_WANTS_DISCONNECT_OFFSET, value ? 1 : 0);
1254
1266
  }
1255
1267
  get peers() {
1256
1268
  if (!this.#hasValidBuffer()) {
@@ -1260,13 +1272,13 @@ class NetContext {
1260
1272
  const localPeerId = this.localPeerId;
1261
1273
  const matchFrame = this.matchFrame;
1262
1274
  let minRemoteSeq = -1;
1263
- for (let i = 0;i < MAX_PEERS; i++) {
1275
+ for (let i = 0;i < MAX_PLAYERS; i++) {
1264
1276
  if (i === localPeerId)
1265
1277
  continue;
1266
- const peerOffset = PEERS_ARRAY_OFFSET + i * PEER_CTX_SIZE;
1267
- if (dv.getUint8(peerOffset + PEER_CONNECTED_OFFSET) !== 1)
1278
+ const peerOffset = NET_CTX_PEERS_OFFSET + i * PEER_CTX_SIZE;
1279
+ if (dv.getUint8(peerOffset + PEER_CTX_CONNECTED_OFFSET) !== 1)
1268
1280
  continue;
1269
- const seq = dv.getInt16(peerOffset + PEER_SEQ_OFFSET, true);
1281
+ const seq = dv.getInt16(peerOffset + PEER_CTX_SEQ_OFFSET, true);
1270
1282
  if (seq < 0)
1271
1283
  continue;
1272
1284
  if (minRemoteSeq === -1 || seq < minRemoteSeq) {
@@ -1274,9 +1286,9 @@ class NetContext {
1274
1286
  }
1275
1287
  }
1276
1288
  this.#peersResult.length = 0;
1277
- for (let i = 0;i < MAX_PEERS; i++) {
1278
- const peerOffset = PEERS_ARRAY_OFFSET + i * PEER_CTX_SIZE;
1279
- if (dv.getUint8(peerOffset + PEER_CONNECTED_OFFSET) !== 1)
1289
+ for (let i = 0;i < MAX_PLAYERS; i++) {
1290
+ const peerOffset = NET_CTX_PEERS_OFFSET + i * PEER_CTX_SIZE;
1291
+ if (dv.getUint8(peerOffset + PEER_CTX_CONNECTED_OFFSET) !== 1)
1280
1292
  continue;
1281
1293
  const peer = this.#peers[i];
1282
1294
  if (!peer) {
@@ -1288,8 +1300,8 @@ class NetContext {
1288
1300
  peer.seq = matchFrame;
1289
1301
  peer.ack = minRemoteSeq;
1290
1302
  } else {
1291
- peer.seq = dv.getInt16(peerOffset + PEER_SEQ_OFFSET, true);
1292
- peer.ack = dv.getInt16(peerOffset + PEER_ACK_OFFSET, true);
1303
+ peer.seq = dv.getInt16(peerOffset + PEER_CTX_SEQ_OFFSET, true);
1304
+ peer.ack = dv.getInt16(peerOffset + PEER_CTX_ACK_OFFSET, true);
1293
1305
  }
1294
1306
  this.#peersResult.push(peer);
1295
1307
  }
@@ -1299,19 +1311,56 @@ class NetContext {
1299
1311
  if (!this.#hasValidBuffer()) {
1300
1312
  throw new Error("NetContext dataView is not valid");
1301
1313
  }
1302
- return this.dataView.getUint32(LAST_ROLLBACK_DEPTH_OFFSET, true);
1314
+ return this.dataView.getUint32(NET_CTX_LAST_ROLLBACK_DEPTH_OFFSET, true);
1303
1315
  }
1304
1316
  get totalRollbacks() {
1305
1317
  if (!this.#hasValidBuffer()) {
1306
1318
  throw new Error("NetContext dataView is not valid");
1307
1319
  }
1308
- return this.dataView.getUint32(TOTAL_ROLLBACKS_OFFSET, true);
1320
+ return this.dataView.getUint32(NET_CTX_TOTAL_ROLLBACKS_OFFSET, true);
1309
1321
  }
1310
1322
  get framesResimulated() {
1311
1323
  if (!this.#hasValidBuffer()) {
1312
1324
  throw new Error("NetContext dataView is not valid");
1313
1325
  }
1314
- return Number(this.dataView.getBigUint64(FRAMES_RESIMULATED_OFFSET, true));
1326
+ return Number(this.dataView.getBigUint64(NET_CTX_FRAMES_RESIMULATED_OFFSET, true));
1327
+ }
1328
+ }
1329
+
1330
+ class ScreenContext {
1331
+ dataView;
1332
+ constructor(dataView) {
1333
+ this.dataView = dataView;
1334
+ }
1335
+ get width() {
1336
+ if (!this.dataView) {
1337
+ throw new Error("ScreenContext DataView is not initialized");
1338
+ }
1339
+ return this.dataView.getUint32(SCREEN_CTX_WIDTH_OFFSET, true);
1340
+ }
1341
+ get height() {
1342
+ if (!this.dataView) {
1343
+ throw new Error("ScreenContext DataView is not initialized");
1344
+ }
1345
+ return this.dataView.getUint32(SCREEN_CTX_HEIGHT_OFFSET, true);
1346
+ }
1347
+ get physicalWidth() {
1348
+ if (!this.dataView) {
1349
+ throw new Error("ScreenContext DataView is not initialized");
1350
+ }
1351
+ return this.dataView.getUint32(SCREEN_CTX_PHYSICAL_WIDTH_OFFSET, true);
1352
+ }
1353
+ get physicalHeight() {
1354
+ if (!this.dataView) {
1355
+ throw new Error("ScreenContext DataView is not initialized");
1356
+ }
1357
+ return this.dataView.getUint32(SCREEN_CTX_PHYSICAL_HEIGHT_OFFSET, true);
1358
+ }
1359
+ get pixelRatio() {
1360
+ if (!this.dataView) {
1361
+ throw new Error("ScreenContext DataView is not initialized");
1362
+ }
1363
+ return this.dataView.getFloat32(SCREEN_CTX_PIXEL_RATIO_OFFSET, true);
1315
1364
  }
1316
1365
  }
1317
1366
 
@@ -1324,21 +1373,41 @@ class TimeContext {
1324
1373
  if (!this.dataView) {
1325
1374
  throw new Error("TimeContext DataView is not initialized");
1326
1375
  }
1327
- return this.dataView.getUint32(0, true);
1376
+ return this.dataView.getUint32(TIME_CTX_FRAME_OFFSET, true);
1328
1377
  }
1329
1378
  get dt() {
1330
1379
  if (!this.dataView) {
1331
1380
  throw new Error("TimeContext DataView is not initialized");
1332
1381
  }
1333
- return this.dataView.getUint32(4, true) / 1000;
1382
+ return this.dataView.getUint32(TIME_CTX_DT_MS_OFFSET, true) / 1000;
1334
1383
  }
1335
1384
  get time() {
1336
1385
  if (!this.dataView) {
1337
1386
  throw new Error("TimeContext DataView is not initialized");
1338
1387
  }
1339
- return this.dataView.getUint32(8, true) / 1000;
1388
+ return this.dataView.getUint32(TIME_CTX_TOTAL_MS_OFFSET, true) / 1000;
1340
1389
  }
1341
1390
  }
1391
+ var EVENT_PAYLOAD_SIZE = 8;
1392
+ var EVENT_PAYLOAD_ALIGN = 4;
1393
+ function keyToKeyCode(key) {
1394
+ return Key[key];
1395
+ }
1396
+ function keyCodeToKey(code) {
1397
+ return Key[code];
1398
+ }
1399
+ function mouseButtonToMouseButtonCode(button) {
1400
+ return MouseButton[button];
1401
+ }
1402
+ function mouseButtonCodeToMouseButton(code) {
1403
+ return MouseButton[code];
1404
+ }
1405
+ function inputSourceToInputSourceCode(source) {
1406
+ return InputSource[source];
1407
+ }
1408
+ function inputSourceCodeToInputSource(code) {
1409
+ return InputSource[code];
1410
+ }
1342
1411
  var TAPE_MAGIC = 1413566533;
1343
1412
  function readTapeHeader(tape) {
1344
1413
  const view = new DataView(tape.buffer, tape.byteOffset, tape.byteLength);
@@ -1354,12 +1423,13 @@ function readTapeHeader(tape) {
1354
1423
  eventCount: view.getUint16(14, true)
1355
1424
  };
1356
1425
  }
1357
- var DEFAULT_WASM_URL = new URL("https://unpkg.com/@bloopjs/engine@0.0.88/wasm/bloop.wasm");
1426
+ var DEFAULT_WASM_URL = new URL("https://unpkg.com/@bloopjs/engine@0.0.90/wasm/bloop.wasm");
1358
1427
  var MAX_ROLLBACK_FRAMES = 500;
1359
1428
  var TIME_CTX_OFFSET = 0;
1360
1429
  var INPUT_CTX_OFFSET = TIME_CTX_OFFSET + 4;
1361
1430
  var EVENTS_OFFSET = INPUT_CTX_OFFSET + 4;
1362
1431
  var NET_CTX_OFFSET = EVENTS_OFFSET + 4;
1432
+ var SCREEN_CTX_OFFSET = NET_CTX_OFFSET + 4;
1363
1433
  var SNAPSHOT_HEADER_LEN = 16;
1364
1434
  var SNAPSHOT_HEADER_USER_LEN_OFFSET = 4;
1365
1435
  var SNAPSHOT_HEADER_ENGINE_LEN_OFFSET = 8;
@@ -1382,6 +1452,7 @@ class Sim {
1382
1452
  #serialize;
1383
1453
  #isPaused = false;
1384
1454
  #net;
1455
+ #screen;
1385
1456
  onTapeFull;
1386
1457
  constructor(wasm, memory, opts) {
1387
1458
  this.wasm = wasm;
@@ -1390,6 +1461,7 @@ class Sim {
1390
1461
  this.id = `${Math.floor(Math.random() * 1e6)}`;
1391
1462
  this.#serialize = opts?.serialize;
1392
1463
  this.#net = new NetContext;
1464
+ this.#screen = new ScreenContext;
1393
1465
  }
1394
1466
  step(ms) {
1395
1467
  if (this.#isPaused) {
@@ -1502,6 +1574,12 @@ class Sim {
1502
1574
  }
1503
1575
  return this.#net;
1504
1576
  }
1577
+ get screen() {
1578
+ if (!this.#screen.dataView || this.#screen.dataView.buffer !== this.#memory.buffer) {
1579
+ this.#screen.dataView = new DataView(this.#memory.buffer, this.wasm.get_screen_ctx());
1580
+ }
1581
+ return this.#screen;
1582
+ }
1505
1583
  get buffer() {
1506
1584
  return this.#memory.buffer;
1507
1585
  }
@@ -1533,6 +1611,9 @@ class Sim {
1533
1611
  mousewheel: (x, y, peerId = 0) => {
1534
1612
  this.wasm.emit_mousewheel(x, y, peerId);
1535
1613
  },
1614
+ resize: (width, height, physicalWidth, physicalHeight, pixelRatio) => {
1615
+ this.wasm.emit_resize(width, height, physicalWidth, physicalHeight, pixelRatio);
1616
+ },
1536
1617
  network: (type, data) => {
1537
1618
  switch (type) {
1538
1619
  case "join:ok": {
@@ -1622,6 +1703,7 @@ async function mount(mountable, options) {
1622
1703
  memory,
1623
1704
  __systems: function(system_handle, ptr) {
1624
1705
  mountable.hooks.setBuffer(memory.buffer);
1706
+ mountable.hooks.setContext(ptr);
1625
1707
  mountable.hooks.systemsCallback(system_handle, ptr);
1626
1708
  },
1627
1709
  __before_frame: function(ptr, frame) {
@@ -1698,6 +1780,40 @@ function calculateTapeConfig(tape) {
1698
1780
  const maxPacketBytes = localOnly ? 0 : Sim.NETWORK_MAX_PACKET_BYTES;
1699
1781
  return { maxEvents, maxPacketBytes };
1700
1782
  }
1783
+ // src/players.ts
1784
+ class Players {
1785
+ #inputs;
1786
+ #net;
1787
+ constructor(inputs, net) {
1788
+ this.#inputs = inputs;
1789
+ this.#net = net;
1790
+ }
1791
+ get(index) {
1792
+ const players = this.#inputs.players;
1793
+ if (index < 0 || index >= players.length) {
1794
+ throw new RangeError(`Player index ${index} out of bounds (0-${players.length - 1})`);
1795
+ }
1796
+ return players[index];
1797
+ }
1798
+ get count() {
1799
+ return this.#net.isInSession ? this.#net.peerCount : 1;
1800
+ }
1801
+ *[Symbol.iterator]() {
1802
+ const players = this.#inputs.players;
1803
+ const count = this.count;
1804
+ for (let i = 0;i < count; i++) {
1805
+ yield players[i];
1806
+ }
1807
+ }
1808
+ *entries() {
1809
+ const players = this.#inputs.players;
1810
+ const count = this.count;
1811
+ for (let i = 0;i < count; i++) {
1812
+ yield [i, players[i]];
1813
+ }
1814
+ }
1815
+ }
1816
+
1701
1817
  // src/bloop.ts
1702
1818
  class Bloop {
1703
1819
  #systems = [];
@@ -1711,15 +1827,16 @@ class Bloop {
1711
1827
  throw new Error("Bloop constructor is private. Use Bloop.create() to create a new game instance.");
1712
1828
  }
1713
1829
  const inputs = new InputContext;
1830
+ const net = new NetContext;
1831
+ const screen = new ScreenContext;
1714
1832
  this.#context = {
1715
1833
  bag: opts.bag ?? {},
1716
1834
  time: new TimeContext,
1717
1835
  inputs,
1718
- get players() {
1719
- return inputs.players;
1720
- },
1836
+ players: new Players(inputs, net),
1721
1837
  rawPointer: -1,
1722
- net: new NetContext
1838
+ net,
1839
+ screen
1723
1840
  };
1724
1841
  }
1725
1842
  get bag() {
@@ -1767,10 +1884,20 @@ class Bloop {
1767
1884
  const timeCtxPtr = dv.getUint32(TIME_CTX_OFFSET, true);
1768
1885
  const inputCtxPtr = dv.getUint32(INPUT_CTX_OFFSET, true);
1769
1886
  const netCtxPtr = dv.getUint32(NET_CTX_OFFSET, true);
1887
+ const screenCtxPtr = dv.getUint32(SCREEN_CTX_OFFSET, true);
1770
1888
  this.#context.rawPointer = ptr;
1771
- this.#context.inputs.dataView = new DataView(this.#engineBuffer, inputCtxPtr);
1772
- this.#context.time.dataView = new DataView(this.#engineBuffer, timeCtxPtr);
1773
- this.#context.net.dataView = new DataView(this.#engineBuffer, netCtxPtr);
1889
+ if (!this.#context.inputs.hasDataView() || this.#context.inputs.dataView.buffer !== this.#engineBuffer || this.#context.inputs.dataView.byteOffset !== inputCtxPtr) {
1890
+ this.#context.inputs.dataView = new DataView(this.#engineBuffer, inputCtxPtr);
1891
+ }
1892
+ if (this.#context.time.dataView?.buffer !== this.#engineBuffer || this.#context.time.dataView?.byteOffset !== timeCtxPtr) {
1893
+ this.#context.time.dataView = new DataView(this.#engineBuffer, timeCtxPtr);
1894
+ }
1895
+ if (this.#context.net.dataView?.buffer !== this.#engineBuffer || this.#context.net.dataView?.byteOffset !== netCtxPtr) {
1896
+ this.#context.net.dataView = new DataView(this.#engineBuffer, netCtxPtr);
1897
+ }
1898
+ if (this.#context.screen.dataView?.buffer !== this.#engineBuffer || this.#context.screen.dataView?.byteOffset !== screenCtxPtr) {
1899
+ this.#context.screen.dataView = new DataView(this.#engineBuffer, screenCtxPtr);
1900
+ }
1774
1901
  },
1775
1902
  systemsCallback: (system_handle, ptr) => {
1776
1903
  this.hooks.setContext(ptr);
@@ -1875,6 +2002,22 @@ class Bloop {
1875
2002
  system.netcode?.(this.#context);
1876
2003
  break;
1877
2004
  }
2005
+ case exports_enums.EventType.NetSessionInit:
2006
+ console.log("[bloop] NetSessionInit event received");
2007
+ this.#context.event = {
2008
+ type: "session:start"
2009
+ };
2010
+ system.netcode?.(this.#context);
2011
+ break;
2012
+ case exports_enums.EventType.Resize:
2013
+ system.resize?.(attachEvent(this.#context, {
2014
+ width: this.#context.screen.width,
2015
+ height: this.#context.screen.height,
2016
+ physicalWidth: this.#context.screen.physicalWidth,
2017
+ physicalHeight: this.#context.screen.physicalHeight,
2018
+ pixelRatio: this.#context.screen.pixelRatio
2019
+ }));
2020
+ break;
1878
2021
  default:
1879
2022
  break;
1880
2023
  }
@@ -1895,9 +2038,10 @@ export {
1895
2038
  assert,
1896
2039
  exports_util as Util,
1897
2040
  Sim,
2041
+ Players,
1898
2042
  exports_engine as Engine,
1899
2043
  Bloop
1900
2044
  };
1901
2045
 
1902
- //# debugId=53D4C6C8E955612164756E2164756E21
2046
+ //# debugId=009B52E93313582464756E2164756E21
1903
2047
  //# sourceMappingURL=mod.js.map