@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.
- package/dist/bloop.d.ts.map +1 -1
- package/dist/context.d.ts +8 -4
- package/dist/context.d.ts.map +1 -1
- package/dist/events.d.ts +8 -0
- package/dist/events.d.ts.map +1 -1
- package/dist/mod.d.ts +1 -0
- package/dist/mod.d.ts.map +1 -1
- package/dist/mod.js +227 -83
- package/dist/mod.js.map +8 -7
- package/dist/mount.d.ts.map +1 -1
- package/dist/players.d.ts +26 -0
- package/dist/players.d.ts.map +1 -0
- package/dist/sim.d.ts +11 -1
- package/dist/sim.d.ts.map +1 -1
- package/dist/system.d.ts +5 -1
- package/dist/system.d.ts.map +1 -1
- package/package.json +2 -2
- package/src/bloop.ts +77 -20
- package/src/context.ts +8 -4
- package/src/events.ts +10 -0
- package/src/mod.ts +1 -0
- package/src/mount.ts +1 -0
- package/src/players.ts +61 -0
- package/src/sim.ts +38 -0
- package/src/system.ts +8 -0
package/dist/mount.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mount.d.ts","sourceRoot":"","sources":["../src/mount.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,KAAK,WAAW,EAAE,GAAG,EAAE,MAAM,OAAO,CAAC;AAG9C;;;GAGG;AACH,MAAM,MAAM,SAAS,GAAG;IACtB,KAAK,EAAE,WAAW,CAAC;CACpB,CAAC;AAEF;;;;GAIG;AACH,wBAAsB,KAAK,CACzB,SAAS,EAAE,SAAS,EACpB,OAAO,CAAC,EAAE,YAAY,GACrB,OAAO,CAAC,WAAW,CAAC,
|
|
1
|
+
{"version":3,"file":"mount.d.ts","sourceRoot":"","sources":["../src/mount.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,KAAK,WAAW,EAAE,GAAG,EAAE,MAAM,OAAO,CAAC;AAG9C;;;GAGG;AACH,MAAM,MAAM,SAAS,GAAG;IACtB,KAAK,EAAE,WAAW,CAAC;CACpB,CAAC;AAEF;;;;GAIG;AACH,wBAAsB,KAAK,CACzB,SAAS,EAAE,SAAS,EACpB,OAAO,CAAC,EAAE,YAAY,GACrB,OAAO,CAAC,WAAW,CAAC,CAgGtB;AAED,MAAM,MAAM,WAAW,GAAG,CACtB;IAAE,SAAS,EAAE,MAAM,CAAA;CAAE,GACrB;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,qBAAqB,CAAC,EAAE,MAAM,CAAA;CAAE,CACvD,GAAG;IACF;;;OAGG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG;IACzB;;;OAGG;IACH,cAAc,CAAC,EAAE,OAAO,CAAC;IAEzB;;OAEG;IACH,IAAI,CAAC,EAAE,WAAW,CAAC;IAEnB;;OAEG;IACH,OAAO,CAAC,EAAE,GAAG,CAAC;CACf,CAAC;AAEF,MAAM,MAAM,WAAW,GAAG;IACxB,GAAG,EAAE,GAAG,CAAC;CACV,CAAC"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { InputContext, PlayerInputContext, NetContext } from "@bloopjs/engine";
|
|
2
|
+
/**
|
|
3
|
+
* Collection of player input contexts with ergonomic access.
|
|
4
|
+
*
|
|
5
|
+
* - `.get(i)` returns PlayerInputContext without undefined (throws for out-of-bounds 0-11)
|
|
6
|
+
* - Iteration yields only connected players
|
|
7
|
+
* - `.count` returns number of connected players
|
|
8
|
+
*/
|
|
9
|
+
export declare class Players implements Iterable<PlayerInputContext> {
|
|
10
|
+
#private;
|
|
11
|
+
constructor(inputs: InputContext, net: NetContext);
|
|
12
|
+
/**
|
|
13
|
+
* Get player input context by index.
|
|
14
|
+
* @param index Player index (0-11)
|
|
15
|
+
* @returns PlayerInputContext for that slot
|
|
16
|
+
* @throws RangeError if index out of bounds
|
|
17
|
+
*/
|
|
18
|
+
get(index: number): PlayerInputContext;
|
|
19
|
+
/** Number of connected players (1 in local mode, peerCount in multiplayer) */
|
|
20
|
+
get count(): number;
|
|
21
|
+
/** Iterate over connected players only */
|
|
22
|
+
[Symbol.iterator](): IterableIterator<PlayerInputContext>;
|
|
23
|
+
/** Iterate over connected players with their indices */
|
|
24
|
+
entries(): IterableIterator<[number, PlayerInputContext]>;
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=players.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"players.d.ts","sourceRoot":"","sources":["../src/players.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,YAAY,EACZ,kBAAkB,EAClB,UAAU,EACX,MAAM,iBAAiB,CAAC;AAEzB;;;;;;GAMG;AACH,qBAAa,OAAQ,YAAW,QAAQ,CAAC,kBAAkB,CAAC;;gBAI9C,MAAM,EAAE,YAAY,EAAE,GAAG,EAAE,UAAU;IAKjD;;;;;OAKG;IACH,GAAG,CAAC,KAAK,EAAE,MAAM,GAAG,kBAAkB;IAUtC,8EAA8E;IAC9E,IAAI,KAAK,IAAI,MAAM,CAElB;IAED,0CAA0C;IACzC,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,gBAAgB,CAAC,kBAAkB,CAAC;IAQ1D,wDAAwD;IACvD,OAAO,IAAI,gBAAgB,CAAC,CAAC,MAAM,EAAE,kBAAkB,CAAC,CAAC;CAO3D"}
|
package/dist/sim.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type EnginePointer, type Key, type MouseButton, NetContext, type NetEvent, type NetEventType, TimeContext, type WasmEngine } from "@bloopjs/engine";
|
|
1
|
+
import { type EnginePointer, type Key, type MouseButton, NetContext, type NetEvent, type NetEventType, ScreenContext, TimeContext, type WasmEngine } from "@bloopjs/engine";
|
|
2
2
|
export type LoadTapeOptions = {
|
|
3
3
|
/** Frames between checkpoints for seek optimization (0 = disabled). Default: 0 */
|
|
4
4
|
checkpointInterval?: number;
|
|
@@ -139,6 +139,7 @@ export declare class Sim {
|
|
|
139
139
|
unmount(): void;
|
|
140
140
|
get time(): TimeContext;
|
|
141
141
|
get net(): NetContext;
|
|
142
|
+
get screen(): ScreenContext;
|
|
142
143
|
get buffer(): ArrayBuffer;
|
|
143
144
|
get isRecording(): boolean;
|
|
144
145
|
get isReplaying(): boolean;
|
|
@@ -150,6 +151,15 @@ export declare class Sim {
|
|
|
150
151
|
mousedown: (button: MouseButton, peerId?: number) => void;
|
|
151
152
|
mouseup: (button: MouseButton, peerId?: number) => void;
|
|
152
153
|
mousewheel: (x: number, y: number, peerId?: number) => void;
|
|
154
|
+
/**
|
|
155
|
+
* Emit a resize event. Updates screen context and fires resize callback in systems.
|
|
156
|
+
* @param width Logical width in CSS pixels
|
|
157
|
+
* @param height Logical height in CSS pixels
|
|
158
|
+
* @param physicalWidth Physical width in device pixels
|
|
159
|
+
* @param physicalHeight Physical height in device pixels
|
|
160
|
+
* @param pixelRatio Device pixel ratio
|
|
161
|
+
*/
|
|
162
|
+
resize: (width: number, height: number, physicalWidth: number, physicalHeight: number, pixelRatio: number) => void;
|
|
153
163
|
/**
|
|
154
164
|
* Emit a network event (join:ok, peer:join, etc.)
|
|
155
165
|
* Events are queued in the engine and processed during the next tick's systemsCallback.
|
package/dist/sim.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sim.d.ts","sourceRoot":"","sources":["../src/sim.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,aAAa,EAClB,KAAK,GAAG,EAER,KAAK,WAAW,EAEhB,UAAU,EACV,KAAK,QAAQ,EACb,KAAK,YAAY,
|
|
1
|
+
{"version":3,"file":"sim.d.ts","sourceRoot":"","sources":["../src/sim.ts"],"names":[],"mappings":"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"}
|
package/dist/system.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { NetEvent } from "@bloopjs/engine";
|
|
2
2
|
import type { Context } from "./context";
|
|
3
3
|
import type { BloopSchema } from "./data/schema";
|
|
4
|
-
import type { KeyEvent, MouseButtonEvent, MouseMoveEvent, MouseWheelEvent } from "./events";
|
|
4
|
+
import type { KeyEvent, MouseButtonEvent, MouseMoveEvent, MouseWheelEvent, ResizeEvent } from "./events";
|
|
5
5
|
export type System<GS extends BloopSchema = BloopSchema> = {
|
|
6
6
|
label?: string;
|
|
7
7
|
update?: (context: Context<GS>) => void;
|
|
@@ -27,5 +27,9 @@ export type System<GS extends BloopSchema = BloopSchema> = {
|
|
|
27
27
|
netcode?: (context: Context<GS> & {
|
|
28
28
|
event: NetEvent;
|
|
29
29
|
}) => void;
|
|
30
|
+
/** Handle screen/viewport resize events */
|
|
31
|
+
resize?: (context: Context<GS> & {
|
|
32
|
+
event: ResizeEvent;
|
|
33
|
+
}) => void;
|
|
30
34
|
};
|
|
31
35
|
//# sourceMappingURL=system.d.ts.map
|
package/dist/system.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"system.d.ts","sourceRoot":"","sources":["../src/system.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AACjD,OAAO,KAAK,EACV,QAAQ,EACR,gBAAgB,EAChB,cAAc,EACd,eAAe,
|
|
1
|
+
{"version":3,"file":"system.d.ts","sourceRoot":"","sources":["../src/system.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AACjD,OAAO,KAAK,EACV,QAAQ,EACR,gBAAgB,EAChB,cAAc,EACd,eAAe,EACf,WAAW,EACZ,MAAM,UAAU,CAAC;AAElB,MAAM,MAAM,MAAM,CAAC,EAAE,SAAS,WAAW,GAAG,WAAW,IAAI;IACzD,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,CAAC,EAAE,CAAC,KAAK,IAAI,CAAC;IAExC,OAAO,CAAC,EAAE,CACR,OAAO,EAAE,OAAO,CAAC,EAAE,CAAC,GAAG;QACrB,KAAK,EAAE,QAAQ,CAAC;KACjB,KACE,IAAI,CAAC;IAEV,KAAK,CAAC,EAAE,CACN,OAAO,EAAE,OAAO,CAAC,EAAE,CAAC,GAAG;QACrB,KAAK,EAAE,QAAQ,CAAC;KACjB,KACE,IAAI,CAAC;IAEV,SAAS,CAAC,EAAE,CACV,OAAO,EAAE,OAAO,CAAC,EAAE,CAAC,GAAG;QACrB,KAAK,EAAE,gBAAgB,CAAC;KACzB,KACE,IAAI,CAAC;IAEV,OAAO,CAAC,EAAE,CACR,OAAO,EAAE,OAAO,CAAC,EAAE,CAAC,GAAG;QACrB,KAAK,EAAE,gBAAgB,CAAC;KACzB,KACE,IAAI,CAAC;IAEV,SAAS,CAAC,EAAE,CACV,OAAO,EAAE,OAAO,CAAC,EAAE,CAAC,GAAG;QACrB,KAAK,EAAE,cAAc,CAAC;KACvB,KACE,IAAI,CAAC;IAEV,UAAU,CAAC,EAAE,CACX,OAAO,EAAE,OAAO,CAAC,EAAE,CAAC,GAAG;QACrB,KAAK,EAAE,eAAe,CAAC;KACxB,KACE,IAAI,CAAC;IAEV,uDAAuD;IACvD,OAAO,CAAC,EAAE,CACR,OAAO,EAAE,OAAO,CAAC,EAAE,CAAC,GAAG;QACrB,KAAK,EAAE,QAAQ,CAAC;KACjB,KACE,IAAI,CAAC;IAEV,2CAA2C;IAC3C,MAAM,CAAC,EAAE,CACP,OAAO,EAAE,OAAO,CAAC,EAAE,CAAC,GAAG;QACrB,KAAK,EAAE,WAAW,CAAC;KACpB,KACE,IAAI,CAAC;CACX,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bloopjs/bloop",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.90",
|
|
4
4
|
"author": "Neil Sarkar",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"repository": {
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
"@types/bun": "latest"
|
|
36
36
|
},
|
|
37
37
|
"dependencies": {
|
|
38
|
-
"@bloopjs/engine": "0.0.
|
|
38
|
+
"@bloopjs/engine": "0.0.90"
|
|
39
39
|
},
|
|
40
40
|
"peerDependencies": {
|
|
41
41
|
"typescript": "^5"
|
package/src/bloop.ts
CHANGED
|
@@ -9,18 +9,22 @@ import {
|
|
|
9
9
|
NET_CTX_OFFSET,
|
|
10
10
|
NetContext,
|
|
11
11
|
type NetEvent,
|
|
12
|
+
SCREEN_CTX_OFFSET,
|
|
13
|
+
ScreenContext,
|
|
12
14
|
TIME_CTX_OFFSET,
|
|
13
15
|
TimeContext,
|
|
14
16
|
} from "@bloopjs/engine";
|
|
17
|
+
import { Players } from "./players";
|
|
15
18
|
import type { Context } from "./context";
|
|
16
19
|
import type { Bag } from "./data/bag";
|
|
17
20
|
import type { BloopSchema } from "./data/schema";
|
|
18
21
|
import type {
|
|
19
|
-
|
|
22
|
+
BloopEvent,
|
|
20
23
|
KeyEvent,
|
|
21
24
|
MouseButtonEvent,
|
|
22
25
|
MouseMoveEvent,
|
|
23
26
|
MouseWheelEvent,
|
|
27
|
+
ResizeEvent,
|
|
24
28
|
} from "./events";
|
|
25
29
|
import type { EngineHooks } from "./sim";
|
|
26
30
|
import type { System } from "./system";
|
|
@@ -75,15 +79,16 @@ export class Bloop<GS extends BloopSchema> {
|
|
|
75
79
|
}
|
|
76
80
|
|
|
77
81
|
const inputs = new InputContext();
|
|
82
|
+
const net = new NetContext();
|
|
83
|
+
const screen = new ScreenContext();
|
|
78
84
|
this.#context = {
|
|
79
85
|
bag: opts.bag ?? {},
|
|
80
86
|
time: new TimeContext(),
|
|
81
87
|
inputs,
|
|
82
|
-
|
|
83
|
-
return inputs.players;
|
|
84
|
-
},
|
|
88
|
+
players: new Players(inputs, net),
|
|
85
89
|
rawPointer: -1,
|
|
86
|
-
net
|
|
90
|
+
net,
|
|
91
|
+
screen,
|
|
87
92
|
};
|
|
88
93
|
}
|
|
89
94
|
|
|
@@ -152,7 +157,6 @@ export class Bloop<GS extends BloopSchema> {
|
|
|
152
157
|
this.#engineBuffer = buffer;
|
|
153
158
|
},
|
|
154
159
|
|
|
155
|
-
// TODO - move this to engine
|
|
156
160
|
setContext: (ptr: EnginePointer) => {
|
|
157
161
|
if (!this.#engineBuffer) {
|
|
158
162
|
throw new Error("Tried to set context before engine buffer");
|
|
@@ -161,18 +165,50 @@ export class Bloop<GS extends BloopSchema> {
|
|
|
161
165
|
const timeCtxPtr = dv.getUint32(TIME_CTX_OFFSET, true);
|
|
162
166
|
const inputCtxPtr = dv.getUint32(INPUT_CTX_OFFSET, true);
|
|
163
167
|
const netCtxPtr = dv.getUint32(NET_CTX_OFFSET, true);
|
|
168
|
+
const screenCtxPtr = dv.getUint32(SCREEN_CTX_OFFSET, true);
|
|
164
169
|
|
|
165
170
|
this.#context.rawPointer = ptr;
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
this.#
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
this.#
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
171
|
+
|
|
172
|
+
if (
|
|
173
|
+
!this.#context.inputs.hasDataView() ||
|
|
174
|
+
this.#context.inputs.dataView.buffer !== this.#engineBuffer ||
|
|
175
|
+
this.#context.inputs.dataView.byteOffset !== inputCtxPtr
|
|
176
|
+
) {
|
|
177
|
+
this.#context.inputs.dataView = new DataView(
|
|
178
|
+
this.#engineBuffer,
|
|
179
|
+
inputCtxPtr,
|
|
180
|
+
);
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
if (
|
|
184
|
+
this.#context.time.dataView?.buffer !== this.#engineBuffer ||
|
|
185
|
+
this.#context.time.dataView?.byteOffset !== timeCtxPtr
|
|
186
|
+
) {
|
|
187
|
+
this.#context.time.dataView = new DataView(
|
|
188
|
+
this.#engineBuffer,
|
|
189
|
+
timeCtxPtr,
|
|
190
|
+
);
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
if (
|
|
194
|
+
this.#context.net.dataView?.buffer !== this.#engineBuffer ||
|
|
195
|
+
this.#context.net.dataView?.byteOffset !== netCtxPtr
|
|
196
|
+
) {
|
|
197
|
+
this.#context.net.dataView = new DataView(
|
|
198
|
+
this.#engineBuffer,
|
|
199
|
+
netCtxPtr,
|
|
200
|
+
);
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
if (
|
|
204
|
+
this.#context.screen.dataView?.buffer !== this.#engineBuffer ||
|
|
205
|
+
this.#context.screen.dataView?.byteOffset !== screenCtxPtr
|
|
206
|
+
) {
|
|
207
|
+
this.#context.screen.dataView = new DataView(
|
|
208
|
+
this.#engineBuffer,
|
|
209
|
+
screenCtxPtr,
|
|
210
|
+
);
|
|
211
|
+
}
|
|
176
212
|
},
|
|
177
213
|
|
|
178
214
|
systemsCallback: (system_handle: number, ptr: EnginePointer) => {
|
|
@@ -313,6 +349,27 @@ export class Bloop<GS extends BloopSchema> {
|
|
|
313
349
|
);
|
|
314
350
|
break;
|
|
315
351
|
}
|
|
352
|
+
case Enums.EventType.NetSessionInit:
|
|
353
|
+
console.log("[bloop] NetSessionInit event received");
|
|
354
|
+
(this.#context as any).event = {
|
|
355
|
+
type: "session:start",
|
|
356
|
+
};
|
|
357
|
+
system.netcode?.(
|
|
358
|
+
this.#context as Context<GS> & { event: NetEvent },
|
|
359
|
+
);
|
|
360
|
+
break;
|
|
361
|
+
case Enums.EventType.Resize:
|
|
362
|
+
// Resize event - values are read from screen context (already updated by engine)
|
|
363
|
+
system.resize?.(
|
|
364
|
+
attachEvent<ResizeEvent, GS>(this.#context, {
|
|
365
|
+
width: this.#context.screen.width,
|
|
366
|
+
height: this.#context.screen.height,
|
|
367
|
+
physicalWidth: this.#context.screen.physicalWidth,
|
|
368
|
+
physicalHeight: this.#context.screen.physicalHeight,
|
|
369
|
+
pixelRatio: this.#context.screen.pixelRatio,
|
|
370
|
+
}),
|
|
371
|
+
);
|
|
372
|
+
break;
|
|
316
373
|
default:
|
|
317
374
|
// Session lifecycle and other internal events are handled by engine
|
|
318
375
|
// They don't need to be dispatched to game systems
|
|
@@ -327,12 +384,12 @@ export class Bloop<GS extends BloopSchema> {
|
|
|
327
384
|
};
|
|
328
385
|
}
|
|
329
386
|
|
|
330
|
-
function attachEvent<
|
|
387
|
+
function attachEvent<E extends BloopEvent, GS extends BloopSchema>(
|
|
331
388
|
context: Context<GS>,
|
|
332
|
-
event:
|
|
333
|
-
): Context<GS> & { event:
|
|
389
|
+
event: E,
|
|
390
|
+
): Context<GS> & { event: E } {
|
|
334
391
|
(context as any).event = event;
|
|
335
|
-
return context as Context<GS> & { event:
|
|
392
|
+
return context as Context<GS> & { event: E };
|
|
336
393
|
}
|
|
337
394
|
|
|
338
395
|
type MakeGS<B extends Bag> = BloopSchema<B>;
|
package/src/context.ts
CHANGED
|
@@ -2,10 +2,11 @@ import type {
|
|
|
2
2
|
EnginePointer,
|
|
3
3
|
InputContext,
|
|
4
4
|
NetContext,
|
|
5
|
-
|
|
5
|
+
ScreenContext,
|
|
6
6
|
TimeContext,
|
|
7
7
|
} from "@bloopjs/engine";
|
|
8
8
|
import type { BloopSchema } from "./data/schema";
|
|
9
|
+
import type { Players } from "./players";
|
|
9
10
|
|
|
10
11
|
export type Context<
|
|
11
12
|
GS extends BloopSchema = BloopSchema,
|
|
@@ -27,12 +28,15 @@ export type Context<
|
|
|
27
28
|
/** The input snapshot */
|
|
28
29
|
inputs: InputContext;
|
|
29
30
|
/**
|
|
30
|
-
* Per-player input states.
|
|
31
|
-
* Access via: context.players
|
|
31
|
+
* Per-player input states.
|
|
32
|
+
* Access via: context.players.get(0).keys.a.held
|
|
33
|
+
* Iterate connected players: for (const p of context.players) { ... }
|
|
32
34
|
*/
|
|
33
|
-
players:
|
|
35
|
+
players: Players;
|
|
34
36
|
/** The engine pointer to the injected system arguments (for advanced use cases) */
|
|
35
37
|
rawPointer: EnginePointer;
|
|
36
38
|
/** Network context for multiplayer sessions */
|
|
37
39
|
net: NetContext;
|
|
40
|
+
/** Screen/viewport dimensions and pixel ratio */
|
|
41
|
+
screen: ScreenContext;
|
|
38
42
|
};
|
package/src/events.ts
CHANGED
|
@@ -23,3 +23,13 @@ export type MouseWheelEvent = {
|
|
|
23
23
|
x: number;
|
|
24
24
|
y: number;
|
|
25
25
|
};
|
|
26
|
+
|
|
27
|
+
export type ResizeEvent = {
|
|
28
|
+
width: number;
|
|
29
|
+
height: number;
|
|
30
|
+
physicalWidth: number;
|
|
31
|
+
physicalHeight: number;
|
|
32
|
+
pixelRatio: number;
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
export type BloopEvent = InputEvent | ResizeEvent;
|
package/src/mod.ts
CHANGED
package/src/mount.ts
CHANGED
|
@@ -47,6 +47,7 @@ export async function mount(
|
|
|
47
47
|
memory,
|
|
48
48
|
__systems: function (system_handle: number, ptr: number) {
|
|
49
49
|
mountable.hooks.setBuffer(memory.buffer);
|
|
50
|
+
mountable.hooks.setContext(ptr);
|
|
50
51
|
mountable.hooks.systemsCallback(system_handle, ptr);
|
|
51
52
|
},
|
|
52
53
|
__before_frame: function (ptr: EnginePointer, frame: number) {
|
package/src/players.ts
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
InputContext,
|
|
3
|
+
PlayerInputContext,
|
|
4
|
+
NetContext,
|
|
5
|
+
} from "@bloopjs/engine";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Collection of player input contexts with ergonomic access.
|
|
9
|
+
*
|
|
10
|
+
* - `.get(i)` returns PlayerInputContext without undefined (throws for out-of-bounds 0-11)
|
|
11
|
+
* - Iteration yields only connected players
|
|
12
|
+
* - `.count` returns number of connected players
|
|
13
|
+
*/
|
|
14
|
+
export class Players implements Iterable<PlayerInputContext> {
|
|
15
|
+
readonly #inputs: InputContext;
|
|
16
|
+
readonly #net: NetContext;
|
|
17
|
+
|
|
18
|
+
constructor(inputs: InputContext, net: NetContext) {
|
|
19
|
+
this.#inputs = inputs;
|
|
20
|
+
this.#net = net;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Get player input context by index.
|
|
25
|
+
* @param index Player index (0-11)
|
|
26
|
+
* @returns PlayerInputContext for that slot
|
|
27
|
+
* @throws RangeError if index out of bounds
|
|
28
|
+
*/
|
|
29
|
+
get(index: number): PlayerInputContext {
|
|
30
|
+
const players = this.#inputs.players;
|
|
31
|
+
if (index < 0 || index >= players.length) {
|
|
32
|
+
throw new RangeError(
|
|
33
|
+
`Player index ${index} out of bounds (0-${players.length - 1})`,
|
|
34
|
+
);
|
|
35
|
+
}
|
|
36
|
+
return players[index]!;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/** Number of connected players (1 in local mode, peerCount in multiplayer) */
|
|
40
|
+
get count(): number {
|
|
41
|
+
return this.#net.isInSession ? this.#net.peerCount : 1;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/** Iterate over connected players only */
|
|
45
|
+
*[Symbol.iterator](): IterableIterator<PlayerInputContext> {
|
|
46
|
+
const players = this.#inputs.players;
|
|
47
|
+
const count = this.count;
|
|
48
|
+
for (let i = 0; i < count; i++) {
|
|
49
|
+
yield players[i]!;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/** Iterate over connected players with their indices */
|
|
54
|
+
*entries(): IterableIterator<[number, PlayerInputContext]> {
|
|
55
|
+
const players = this.#inputs.players;
|
|
56
|
+
const count = this.count;
|
|
57
|
+
for (let i = 0; i < count; i++) {
|
|
58
|
+
yield [i, players[i]!];
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
package/src/sim.ts
CHANGED
|
@@ -7,6 +7,7 @@ import {
|
|
|
7
7
|
NetContext,
|
|
8
8
|
type NetEvent,
|
|
9
9
|
type NetEventType,
|
|
10
|
+
ScreenContext,
|
|
10
11
|
SNAPSHOT_HEADER_ENGINE_LEN_OFFSET,
|
|
11
12
|
SNAPSHOT_HEADER_USER_LEN_OFFSET,
|
|
12
13
|
TimeContext,
|
|
@@ -104,6 +105,11 @@ export class Sim {
|
|
|
104
105
|
*/
|
|
105
106
|
#net: NetContext;
|
|
106
107
|
|
|
108
|
+
/**
|
|
109
|
+
* Screen context - reads viewport dimensions from WASM memory.
|
|
110
|
+
*/
|
|
111
|
+
#screen: ScreenContext;
|
|
112
|
+
|
|
107
113
|
/**
|
|
108
114
|
* Callback fired when tape buffer fills up and recording stops.
|
|
109
115
|
* The tape data is passed so you can save it before clearing.
|
|
@@ -125,6 +131,7 @@ export class Sim {
|
|
|
125
131
|
|
|
126
132
|
this.#serialize = opts?.serialize;
|
|
127
133
|
this.#net = new NetContext();
|
|
134
|
+
this.#screen = new ScreenContext();
|
|
128
135
|
}
|
|
129
136
|
|
|
130
137
|
/**
|
|
@@ -379,6 +386,20 @@ export class Sim {
|
|
|
379
386
|
return this.#net;
|
|
380
387
|
}
|
|
381
388
|
|
|
389
|
+
get screen(): ScreenContext {
|
|
390
|
+
if (
|
|
391
|
+
!this.#screen.dataView ||
|
|
392
|
+
this.#screen.dataView.buffer !== this.#memory.buffer
|
|
393
|
+
) {
|
|
394
|
+
// update the data view to the latest memory buffer
|
|
395
|
+
this.#screen.dataView = new DataView(
|
|
396
|
+
this.#memory.buffer,
|
|
397
|
+
this.wasm.get_screen_ctx(),
|
|
398
|
+
);
|
|
399
|
+
}
|
|
400
|
+
return this.#screen;
|
|
401
|
+
}
|
|
402
|
+
|
|
382
403
|
get buffer(): ArrayBuffer {
|
|
383
404
|
return this.#memory.buffer;
|
|
384
405
|
}
|
|
@@ -414,6 +435,23 @@ export class Sim {
|
|
|
414
435
|
mousewheel: (x: number, y: number, peerId: number = 0): void => {
|
|
415
436
|
this.wasm.emit_mousewheel(x, y, peerId);
|
|
416
437
|
},
|
|
438
|
+
/**
|
|
439
|
+
* Emit a resize event. Updates screen context and fires resize callback in systems.
|
|
440
|
+
* @param width Logical width in CSS pixels
|
|
441
|
+
* @param height Logical height in CSS pixels
|
|
442
|
+
* @param physicalWidth Physical width in device pixels
|
|
443
|
+
* @param physicalHeight Physical height in device pixels
|
|
444
|
+
* @param pixelRatio Device pixel ratio
|
|
445
|
+
*/
|
|
446
|
+
resize: (
|
|
447
|
+
width: number,
|
|
448
|
+
height: number,
|
|
449
|
+
physicalWidth: number,
|
|
450
|
+
physicalHeight: number,
|
|
451
|
+
pixelRatio: number,
|
|
452
|
+
): void => {
|
|
453
|
+
this.wasm.emit_resize(width, height, physicalWidth, physicalHeight, pixelRatio);
|
|
454
|
+
},
|
|
417
455
|
/**
|
|
418
456
|
* Emit a network event (join:ok, peer:join, etc.)
|
|
419
457
|
* Events are queued in the engine and processed during the next tick's systemsCallback.
|
package/src/system.ts
CHANGED
|
@@ -6,6 +6,7 @@ import type {
|
|
|
6
6
|
MouseButtonEvent,
|
|
7
7
|
MouseMoveEvent,
|
|
8
8
|
MouseWheelEvent,
|
|
9
|
+
ResizeEvent,
|
|
9
10
|
} from "./events";
|
|
10
11
|
|
|
11
12
|
export type System<GS extends BloopSchema = BloopSchema> = {
|
|
@@ -55,4 +56,11 @@ export type System<GS extends BloopSchema = BloopSchema> = {
|
|
|
55
56
|
event: NetEvent;
|
|
56
57
|
},
|
|
57
58
|
) => void;
|
|
59
|
+
|
|
60
|
+
/** Handle screen/viewport resize events */
|
|
61
|
+
resize?: (
|
|
62
|
+
context: Context<GS> & {
|
|
63
|
+
event: ResizeEvent;
|
|
64
|
+
},
|
|
65
|
+
) => void;
|
|
58
66
|
};
|