@bloopjs/bloop 0.0.19 → 0.0.21
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 +53 -0
- package/dist/bloop.d.ts.map +1 -0
- package/dist/context.d.ts +17 -0
- package/dist/context.d.ts.map +1 -0
- package/dist/data/bag.d.ts +8 -0
- package/dist/data/bag.d.ts.map +1 -0
- package/dist/data/schema.d.ts +5 -0
- package/dist/data/schema.d.ts.map +1 -0
- package/dist/events.d.ts +17 -0
- package/dist/events.d.ts.map +1 -0
- package/dist/mod.d.ts +4 -0
- package/dist/mod.d.ts.map +1 -0
- package/dist/mod.js +1296 -0
- package/dist/mod.js.map +13 -0
- package/dist/runtime.d.ts +70 -0
- package/dist/runtime.d.ts.map +1 -0
- package/dist/system.d.ts +26 -0
- package/dist/system.d.ts.map +1 -0
- package/dist/util.d.ts +4 -0
- package/dist/util.d.ts.map +1 -0
- package/package.json +10 -2
- package/.cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc +0 -111
- package/jsr.json +0 -6
- package/publish/tsconfig.publish.json +0 -7
- package/test/inputs.test.ts +0 -227
- package/test/runtime.test.ts +0 -298
- package/test/tape.test.ts +0 -128
- package/tsconfig.json +0 -34
package/test/inputs.test.ts
DELETED
|
@@ -1,227 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it } from "bun:test";
|
|
2
|
-
import type { Key, MouseButton } from "@bloopjs/engine";
|
|
3
|
-
import { Bloop } from "../src/bloop";
|
|
4
|
-
import { mount } from "../src/runtime";
|
|
5
|
-
|
|
6
|
-
describe("inputs", () => {
|
|
7
|
-
it("runs a single system", async () => {
|
|
8
|
-
const bloop = Bloop.create();
|
|
9
|
-
let count = 0;
|
|
10
|
-
|
|
11
|
-
bloop.system("test", {
|
|
12
|
-
update() {
|
|
13
|
-
count++;
|
|
14
|
-
},
|
|
15
|
-
});
|
|
16
|
-
|
|
17
|
-
const { runtime } = await mount(bloop);
|
|
18
|
-
runtime.step();
|
|
19
|
-
|
|
20
|
-
expect(count).toEqual(1);
|
|
21
|
-
});
|
|
22
|
-
|
|
23
|
-
it("routes keydown event", async () => {
|
|
24
|
-
const bloop = Bloop.create();
|
|
25
|
-
let receivedKey: Key | null = null;
|
|
26
|
-
let called = false;
|
|
27
|
-
bloop.system("input", {
|
|
28
|
-
keydown({ event }) {
|
|
29
|
-
receivedKey = event.key;
|
|
30
|
-
called = true;
|
|
31
|
-
},
|
|
32
|
-
});
|
|
33
|
-
|
|
34
|
-
const { runtime } = await mount(bloop);
|
|
35
|
-
runtime.emit.keydown("Space");
|
|
36
|
-
runtime.step();
|
|
37
|
-
|
|
38
|
-
expect(called).toBe(true);
|
|
39
|
-
expect(receivedKey!).toEqual("Space");
|
|
40
|
-
});
|
|
41
|
-
|
|
42
|
-
it("routes all input events", async () => {
|
|
43
|
-
const bloop = Bloop.create();
|
|
44
|
-
|
|
45
|
-
const events = {
|
|
46
|
-
keydown: null as Key | null,
|
|
47
|
-
keyup: null as Key | null,
|
|
48
|
-
|
|
49
|
-
mousemove: null as { x: number; y: number } | null,
|
|
50
|
-
mousedown: null as MouseButton | null,
|
|
51
|
-
mouseup: null as MouseButton | null,
|
|
52
|
-
mousewheel: null as { x: number; y: number } | null,
|
|
53
|
-
};
|
|
54
|
-
|
|
55
|
-
bloop.system("input", {
|
|
56
|
-
keydown({ event }) {
|
|
57
|
-
events.keydown = event.key;
|
|
58
|
-
},
|
|
59
|
-
keyup({ event }) {
|
|
60
|
-
events.keyup = event.key;
|
|
61
|
-
},
|
|
62
|
-
mousemove({ event }) {
|
|
63
|
-
events.mousemove = { x: event.x, y: event.y };
|
|
64
|
-
},
|
|
65
|
-
mousedown({ event }) {
|
|
66
|
-
events.mousedown = event.button;
|
|
67
|
-
},
|
|
68
|
-
mouseup({ event }) {
|
|
69
|
-
events.mouseup = event.button;
|
|
70
|
-
},
|
|
71
|
-
mousewheel({ event }) {
|
|
72
|
-
events.mousewheel = event;
|
|
73
|
-
},
|
|
74
|
-
});
|
|
75
|
-
|
|
76
|
-
const { runtime } = await mount(bloop);
|
|
77
|
-
|
|
78
|
-
runtime.emit.keydown("Space");
|
|
79
|
-
runtime.emit.mousedown("Left");
|
|
80
|
-
runtime.emit.mousemove(100, 150);
|
|
81
|
-
runtime.emit.mousewheel(1, 2);
|
|
82
|
-
|
|
83
|
-
runtime.step();
|
|
84
|
-
|
|
85
|
-
expect(events.keydown).toEqual("Space");
|
|
86
|
-
expect(events.mousemove).toEqual({ x: 100, y: 150 });
|
|
87
|
-
expect(events.mousedown).toEqual("Left");
|
|
88
|
-
expect(events.mousewheel).toEqual({ x: 1, y: 2 });
|
|
89
|
-
|
|
90
|
-
runtime.emit.keyup("Space");
|
|
91
|
-
runtime.emit.mouseup("Left");
|
|
92
|
-
runtime.emit.mousemove(3, 4);
|
|
93
|
-
|
|
94
|
-
runtime.step();
|
|
95
|
-
|
|
96
|
-
expect(events.keyup).toEqual("Space");
|
|
97
|
-
expect(events.mouseup).toEqual("Left");
|
|
98
|
-
expect(events.mousemove).toEqual({ x: 3, y: 4 });
|
|
99
|
-
});
|
|
100
|
-
|
|
101
|
-
it("exposes keyboard context", async () => {
|
|
102
|
-
const bloop = Bloop.create({
|
|
103
|
-
bag: {
|
|
104
|
-
down: null as boolean | null,
|
|
105
|
-
held: null as boolean | null,
|
|
106
|
-
up: null as boolean | null,
|
|
107
|
-
},
|
|
108
|
-
});
|
|
109
|
-
|
|
110
|
-
bloop.system("key state", {
|
|
111
|
-
update({ inputs, bag }) {
|
|
112
|
-
bag.down = inputs.keys.backquote.down;
|
|
113
|
-
bag.held = inputs.keys.backquote.held;
|
|
114
|
-
bag.up = inputs.keys.backquote.up;
|
|
115
|
-
},
|
|
116
|
-
});
|
|
117
|
-
|
|
118
|
-
const { runtime } = await mount(bloop);
|
|
119
|
-
|
|
120
|
-
// Initial state
|
|
121
|
-
runtime.step();
|
|
122
|
-
expect(bloop.bag).toEqual({
|
|
123
|
-
down: false,
|
|
124
|
-
held: false,
|
|
125
|
-
up: false,
|
|
126
|
-
});
|
|
127
|
-
|
|
128
|
-
// down and held are both true on the first frame of a key down
|
|
129
|
-
runtime.emit.keydown("Backquote");
|
|
130
|
-
runtime.step();
|
|
131
|
-
expect(bloop.bag).toEqual({
|
|
132
|
-
down: true,
|
|
133
|
-
held: true,
|
|
134
|
-
up: false,
|
|
135
|
-
});
|
|
136
|
-
|
|
137
|
-
// held remains true, down goes false
|
|
138
|
-
runtime.step();
|
|
139
|
-
expect(bloop.bag).toEqual({
|
|
140
|
-
down: false,
|
|
141
|
-
held: true,
|
|
142
|
-
up: false,
|
|
143
|
-
});
|
|
144
|
-
|
|
145
|
-
// on key up, up is true, held and down are false
|
|
146
|
-
runtime.emit.keyup("Backquote");
|
|
147
|
-
runtime.step();
|
|
148
|
-
expect(bloop.bag).toEqual({
|
|
149
|
-
down: false,
|
|
150
|
-
held: false,
|
|
151
|
-
up: true,
|
|
152
|
-
});
|
|
153
|
-
});
|
|
154
|
-
|
|
155
|
-
it("exposes mouse context", async () => {
|
|
156
|
-
const bloop = Bloop.create({
|
|
157
|
-
bag: {
|
|
158
|
-
down: null as boolean | null,
|
|
159
|
-
held: null as boolean | null,
|
|
160
|
-
up: null as boolean | null,
|
|
161
|
-
position: null as { x: number; y: number } | null,
|
|
162
|
-
wheel: null as { x: number; y: number } | null,
|
|
163
|
-
},
|
|
164
|
-
});
|
|
165
|
-
|
|
166
|
-
bloop.system("mouse state", {
|
|
167
|
-
update({ inputs, bag }) {
|
|
168
|
-
bag.down = inputs.mouse.left.down;
|
|
169
|
-
bag.held = inputs.mouse.left.held;
|
|
170
|
-
bag.up = inputs.mouse.left.up;
|
|
171
|
-
bag.position = { x: inputs.mouse.x, y: inputs.mouse.y };
|
|
172
|
-
bag.wheel = inputs.mouse.wheel;
|
|
173
|
-
},
|
|
174
|
-
});
|
|
175
|
-
|
|
176
|
-
const { runtime } = await mount(bloop);
|
|
177
|
-
|
|
178
|
-
// Initial state
|
|
179
|
-
runtime.step();
|
|
180
|
-
expect(bloop.bag).toEqual({
|
|
181
|
-
down: false,
|
|
182
|
-
held: false,
|
|
183
|
-
up: false,
|
|
184
|
-
position: { x: 0, y: 0 },
|
|
185
|
-
wheel: { x: 0, y: 0 },
|
|
186
|
-
});
|
|
187
|
-
|
|
188
|
-
// down and held are both true on the first frame of a key down
|
|
189
|
-
runtime.emit.mousedown("Left");
|
|
190
|
-
runtime.step();
|
|
191
|
-
expect(bloop.bag).toMatchObject({
|
|
192
|
-
down: true,
|
|
193
|
-
held: true,
|
|
194
|
-
up: false,
|
|
195
|
-
});
|
|
196
|
-
|
|
197
|
-
runtime.emit.mousemove(123, 456);
|
|
198
|
-
runtime.step();
|
|
199
|
-
expect(bloop.bag).toMatchObject({
|
|
200
|
-
down: false,
|
|
201
|
-
held: true,
|
|
202
|
-
up: false,
|
|
203
|
-
position: { x: 123, y: 456 },
|
|
204
|
-
});
|
|
205
|
-
|
|
206
|
-
runtime.emit.mousewheel(5, -3);
|
|
207
|
-
runtime.step();
|
|
208
|
-
expect(bloop.bag).toMatchObject({
|
|
209
|
-
down: false,
|
|
210
|
-
held: true,
|
|
211
|
-
up: false,
|
|
212
|
-
position: { x: 123, y: 456 },
|
|
213
|
-
wheel: { x: 5, y: -3 },
|
|
214
|
-
});
|
|
215
|
-
|
|
216
|
-
runtime.emit.mouseup("Left");
|
|
217
|
-
runtime.step();
|
|
218
|
-
expect(bloop.bag).toMatchObject({
|
|
219
|
-
down: false,
|
|
220
|
-
held: false,
|
|
221
|
-
up: true,
|
|
222
|
-
});
|
|
223
|
-
});
|
|
224
|
-
|
|
225
|
-
it.skip("handles multiple frames between accumulated inputs", async () => {});
|
|
226
|
-
it.skip("handles down and up between frames", async () => {});
|
|
227
|
-
});
|
package/test/runtime.test.ts
DELETED
|
@@ -1,298 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it } from "bun:test";
|
|
2
|
-
import {
|
|
3
|
-
KeyboardContext,
|
|
4
|
-
type KeyState,
|
|
5
|
-
MOUSE_OFFSET,
|
|
6
|
-
MouseContext,
|
|
7
|
-
} from "@bloopjs/engine";
|
|
8
|
-
import { mount } from "../src/runtime";
|
|
9
|
-
import { assert } from "../src/util";
|
|
10
|
-
|
|
11
|
-
it("hello wasm", async () => {
|
|
12
|
-
let count = 0;
|
|
13
|
-
const { wasm } = await mount({
|
|
14
|
-
systemsCallback() {
|
|
15
|
-
count++;
|
|
16
|
-
},
|
|
17
|
-
setBuffer() {},
|
|
18
|
-
});
|
|
19
|
-
|
|
20
|
-
wasm.step(16);
|
|
21
|
-
expect(count).toBe(1);
|
|
22
|
-
});
|
|
23
|
-
|
|
24
|
-
describe("time", () => {
|
|
25
|
-
it("injects frame and dt", async () => {
|
|
26
|
-
const { runtime } = await mount({
|
|
27
|
-
systemsCallback() {},
|
|
28
|
-
setBuffer() {},
|
|
29
|
-
});
|
|
30
|
-
|
|
31
|
-
runtime.step(16);
|
|
32
|
-
expect(runtime.time.frame).toEqual(1);
|
|
33
|
-
expect(runtime.time.dt).toEqual(0.016);
|
|
34
|
-
});
|
|
35
|
-
|
|
36
|
-
it("exposes time context pointer in system callback", async () => {
|
|
37
|
-
let called = false;
|
|
38
|
-
const { runtime } = await mount({
|
|
39
|
-
systemsCallback(_handle, ptr) {
|
|
40
|
-
called = true;
|
|
41
|
-
const dataView = new DataView(runtime.buffer, ptr);
|
|
42
|
-
const timeCtxPtr = dataView.getUint32(0, true);
|
|
43
|
-
const timeDataView = new DataView(runtime.buffer, timeCtxPtr);
|
|
44
|
-
const frame = timeDataView.getUint32(0, true);
|
|
45
|
-
const dt = timeDataView.getUint32(4, true);
|
|
46
|
-
expect(frame).toEqual(0);
|
|
47
|
-
expect(dt).toEqual(16);
|
|
48
|
-
},
|
|
49
|
-
setBuffer() {},
|
|
50
|
-
});
|
|
51
|
-
runtime.step(16);
|
|
52
|
-
|
|
53
|
-
expect(called).toEqual(true);
|
|
54
|
-
});
|
|
55
|
-
});
|
|
56
|
-
|
|
57
|
-
describe("snapshots", () => {
|
|
58
|
-
it("can capture time to a snapshot", async () => {
|
|
59
|
-
const { runtime } = await mount({
|
|
60
|
-
systemsCallback() {},
|
|
61
|
-
setBuffer() {},
|
|
62
|
-
});
|
|
63
|
-
|
|
64
|
-
runtime.step(16);
|
|
65
|
-
runtime.step(16);
|
|
66
|
-
expect(runtime.time.frame).toEqual(2);
|
|
67
|
-
expect(runtime.time.dt).toEqual(0.016);
|
|
68
|
-
|
|
69
|
-
const snapshot = runtime.snapshot();
|
|
70
|
-
|
|
71
|
-
runtime.step(16);
|
|
72
|
-
expect(runtime.time.frame).toEqual(3);
|
|
73
|
-
|
|
74
|
-
runtime.restore(snapshot);
|
|
75
|
-
expect(runtime.time.frame).toEqual(2);
|
|
76
|
-
|
|
77
|
-
runtime.step(16);
|
|
78
|
-
expect(runtime.time.frame).toEqual(3);
|
|
79
|
-
});
|
|
80
|
-
});
|
|
81
|
-
|
|
82
|
-
describe("inputs", () => {
|
|
83
|
-
it("updates input context in response to keyboard events", async () => {
|
|
84
|
-
let called = false;
|
|
85
|
-
const states: KeyState[] = [];
|
|
86
|
-
|
|
87
|
-
const { runtime } = await mount({
|
|
88
|
-
systemsCallback(_handle, ptr) {
|
|
89
|
-
const dataView = new DataView(runtime.buffer, ptr);
|
|
90
|
-
const inputCtxPtr = dataView.getUint32(4, true);
|
|
91
|
-
const inputDataView = new DataView(runtime.buffer, inputCtxPtr);
|
|
92
|
-
|
|
93
|
-
const keyboardContext = new KeyboardContext(inputDataView);
|
|
94
|
-
states.push(keyboardContext.digit8);
|
|
95
|
-
|
|
96
|
-
called = true;
|
|
97
|
-
},
|
|
98
|
-
setBuffer() {},
|
|
99
|
-
});
|
|
100
|
-
|
|
101
|
-
runtime.emit.keydown("Digit8");
|
|
102
|
-
runtime.step();
|
|
103
|
-
runtime.step();
|
|
104
|
-
runtime.emit.keyup("Digit8");
|
|
105
|
-
runtime.step();
|
|
106
|
-
expect(called).toEqual(true);
|
|
107
|
-
|
|
108
|
-
expect(states[0]).toEqual({
|
|
109
|
-
down: true,
|
|
110
|
-
held: true,
|
|
111
|
-
up: false,
|
|
112
|
-
});
|
|
113
|
-
|
|
114
|
-
expect(states[1]).toEqual({
|
|
115
|
-
down: false,
|
|
116
|
-
held: true,
|
|
117
|
-
up: false,
|
|
118
|
-
});
|
|
119
|
-
|
|
120
|
-
expect(states[2]).toEqual({
|
|
121
|
-
down: false,
|
|
122
|
-
held: false,
|
|
123
|
-
up: true,
|
|
124
|
-
});
|
|
125
|
-
});
|
|
126
|
-
|
|
127
|
-
it("updates input context in response to mouse events", async () => {
|
|
128
|
-
let called = false;
|
|
129
|
-
type MouseState = {
|
|
130
|
-
x: number;
|
|
131
|
-
y: number;
|
|
132
|
-
wheelX: number;
|
|
133
|
-
wheelY: number;
|
|
134
|
-
left: KeyState;
|
|
135
|
-
};
|
|
136
|
-
const states: MouseState[] = [];
|
|
137
|
-
|
|
138
|
-
const { runtime } = await mount({
|
|
139
|
-
systemsCallback(_handle, ptr) {
|
|
140
|
-
const dataView = new DataView(runtime.buffer, ptr);
|
|
141
|
-
const inputCtxPtr = dataView.getUint32(4, true);
|
|
142
|
-
const inputDataView = new DataView(runtime.buffer, inputCtxPtr);
|
|
143
|
-
|
|
144
|
-
const dv = new DataView(
|
|
145
|
-
inputDataView.buffer,
|
|
146
|
-
inputDataView.byteOffset + MOUSE_OFFSET,
|
|
147
|
-
);
|
|
148
|
-
const mouseContext = new MouseContext(dv);
|
|
149
|
-
|
|
150
|
-
states.push({
|
|
151
|
-
x: mouseContext.x,
|
|
152
|
-
y: mouseContext.y,
|
|
153
|
-
left: mouseContext.left,
|
|
154
|
-
wheelX: mouseContext.wheelX,
|
|
155
|
-
wheelY: mouseContext.wheelY,
|
|
156
|
-
});
|
|
157
|
-
|
|
158
|
-
called = true;
|
|
159
|
-
},
|
|
160
|
-
setBuffer() {},
|
|
161
|
-
});
|
|
162
|
-
|
|
163
|
-
runtime.emit.mousedown("Left");
|
|
164
|
-
runtime.step();
|
|
165
|
-
|
|
166
|
-
runtime.emit.mousemove(123, 456);
|
|
167
|
-
runtime.emit.mousewheel(789, 101);
|
|
168
|
-
runtime.step();
|
|
169
|
-
|
|
170
|
-
runtime.emit.mouseup("Left");
|
|
171
|
-
runtime.step();
|
|
172
|
-
|
|
173
|
-
expect(called).toEqual(true);
|
|
174
|
-
|
|
175
|
-
expect(states[0]).toMatchObject({
|
|
176
|
-
left: {
|
|
177
|
-
down: true,
|
|
178
|
-
held: true,
|
|
179
|
-
up: false,
|
|
180
|
-
},
|
|
181
|
-
});
|
|
182
|
-
|
|
183
|
-
expect(states[1]).toMatchObject({
|
|
184
|
-
left: {
|
|
185
|
-
down: false,
|
|
186
|
-
held: true,
|
|
187
|
-
up: false,
|
|
188
|
-
},
|
|
189
|
-
x: 123,
|
|
190
|
-
y: 456,
|
|
191
|
-
wheelX: 789,
|
|
192
|
-
wheelY: 101,
|
|
193
|
-
});
|
|
194
|
-
|
|
195
|
-
expect(states[2]).toMatchObject({
|
|
196
|
-
left: {
|
|
197
|
-
down: false,
|
|
198
|
-
held: false,
|
|
199
|
-
up: true,
|
|
200
|
-
},
|
|
201
|
-
});
|
|
202
|
-
});
|
|
203
|
-
|
|
204
|
-
it("updates platform events with input events", async () => {
|
|
205
|
-
let called = false;
|
|
206
|
-
const { runtime } = await mount({
|
|
207
|
-
systemsCallback(_handle, ptr) {
|
|
208
|
-
const dataView = new DataView(runtime.buffer, ptr);
|
|
209
|
-
const eventsPtr = dataView.getUint32(8, true);
|
|
210
|
-
const eventsDataView = new DataView(runtime.buffer, eventsPtr);
|
|
211
|
-
const eventCount = eventsDataView.getUint32(0, true);
|
|
212
|
-
expect(eventCount).toEqual(1);
|
|
213
|
-
// kind = 1 byte + 3 bytes padding
|
|
214
|
-
// payload = 8 bytes
|
|
215
|
-
const typeOffset = 4;
|
|
216
|
-
const payloadOffset = 7;
|
|
217
|
-
const eventType = eventsDataView.getUint8(typeOffset + 0);
|
|
218
|
-
const eventPayload = eventsDataView.getUint8(payloadOffset + 1);
|
|
219
|
-
expect(eventCount).toEqual(1);
|
|
220
|
-
expect(eventType).toEqual(1);
|
|
221
|
-
expect(eventPayload).toEqual(3); // KeyCode for BracketLeft
|
|
222
|
-
called = true;
|
|
223
|
-
},
|
|
224
|
-
setBuffer() {},
|
|
225
|
-
});
|
|
226
|
-
|
|
227
|
-
runtime.emit.keydown("BracketLeft");
|
|
228
|
-
runtime.step();
|
|
229
|
-
expect(called).toEqual(true);
|
|
230
|
-
});
|
|
231
|
-
});
|
|
232
|
-
|
|
233
|
-
describe("tapes", () => {
|
|
234
|
-
describe("engine snapshot", () => {
|
|
235
|
-
it("saves and restores time context", async () => {
|
|
236
|
-
const { runtime } = await mount({
|
|
237
|
-
systemsCallback() {},
|
|
238
|
-
setBuffer() {},
|
|
239
|
-
});
|
|
240
|
-
|
|
241
|
-
const snapshot = runtime.snapshot();
|
|
242
|
-
expect(runtime.time.frame).toEqual(0);
|
|
243
|
-
runtime.step();
|
|
244
|
-
expect(runtime.time.frame).toEqual(1);
|
|
245
|
-
runtime.step();
|
|
246
|
-
expect(runtime.time.frame).toEqual(2);
|
|
247
|
-
runtime.restore(snapshot);
|
|
248
|
-
|
|
249
|
-
expect(runtime.time.frame).toEqual(0);
|
|
250
|
-
});
|
|
251
|
-
});
|
|
252
|
-
|
|
253
|
-
describe("caller payload", () => {
|
|
254
|
-
it("can capture and restore arbitrary payloads", async () => {
|
|
255
|
-
let called = false;
|
|
256
|
-
const { runtime } = await mount({
|
|
257
|
-
startRecording: false,
|
|
258
|
-
systemsCallback() {},
|
|
259
|
-
setBuffer() {},
|
|
260
|
-
serialize() {
|
|
261
|
-
return {
|
|
262
|
-
write(buffer, ptr) {
|
|
263
|
-
const data = new Uint8Array(buffer, ptr, 1);
|
|
264
|
-
data[0] = 66;
|
|
265
|
-
},
|
|
266
|
-
size: 1,
|
|
267
|
-
};
|
|
268
|
-
},
|
|
269
|
-
deserialize(buffer, ptr, length) {
|
|
270
|
-
called = true;
|
|
271
|
-
const data = new Uint8Array(buffer, ptr, length);
|
|
272
|
-
expect(data.byteLength).toBe(1);
|
|
273
|
-
expect(length).toEqual(1);
|
|
274
|
-
expect(data[0]).toBe(66);
|
|
275
|
-
},
|
|
276
|
-
});
|
|
277
|
-
|
|
278
|
-
const snapshot = runtime.snapshot();
|
|
279
|
-
runtime.restore(snapshot);
|
|
280
|
-
expect(called).toEqual(true);
|
|
281
|
-
});
|
|
282
|
-
});
|
|
283
|
-
});
|
|
284
|
-
|
|
285
|
-
function toHexString(bytes: DataView | Uint8Array, length?: number): string {
|
|
286
|
-
const dv =
|
|
287
|
-
bytes instanceof DataView
|
|
288
|
-
? bytes
|
|
289
|
-
: new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
|
|
290
|
-
length ??= dv.byteLength;
|
|
291
|
-
|
|
292
|
-
let hexString = "";
|
|
293
|
-
for (let i = 0; i < length; i++) {
|
|
294
|
-
const byte = dv.getUint8(i);
|
|
295
|
-
hexString += `${byte.toString(16).padStart(2, "0")} `;
|
|
296
|
-
}
|
|
297
|
-
return hexString.trim();
|
|
298
|
-
}
|
package/test/tape.test.ts
DELETED
|
@@ -1,128 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it } from "bun:test";
|
|
2
|
-
import { Bloop } from "../src/bloop";
|
|
3
|
-
import { mount } from "../src/runtime";
|
|
4
|
-
|
|
5
|
-
describe("tapes", () => {
|
|
6
|
-
describe("snapshots", () => {
|
|
7
|
-
it("can snapshot the bag", async () => {
|
|
8
|
-
const bloop = Bloop.create({
|
|
9
|
-
bag: {
|
|
10
|
-
cool: 42,
|
|
11
|
-
},
|
|
12
|
-
});
|
|
13
|
-
|
|
14
|
-
bloop.system("inc", {
|
|
15
|
-
update({ bag }) {
|
|
16
|
-
bag.cool++;
|
|
17
|
-
},
|
|
18
|
-
});
|
|
19
|
-
|
|
20
|
-
const { runtime } = await mount(bloop);
|
|
21
|
-
runtime.step();
|
|
22
|
-
|
|
23
|
-
expect(bloop.bag.cool).toEqual(43);
|
|
24
|
-
const snapshot = runtime.snapshot();
|
|
25
|
-
|
|
26
|
-
runtime.step();
|
|
27
|
-
expect(bloop.bag.cool).toEqual(44);
|
|
28
|
-
|
|
29
|
-
runtime.restore(snapshot);
|
|
30
|
-
expect(bloop.bag.cool).toEqual(43);
|
|
31
|
-
});
|
|
32
|
-
|
|
33
|
-
it("can snapshot the bag on frame 0", async () => {
|
|
34
|
-
const bloop = Bloop.create({
|
|
35
|
-
bag: {
|
|
36
|
-
score: 10,
|
|
37
|
-
},
|
|
38
|
-
});
|
|
39
|
-
|
|
40
|
-
const { runtime } = await mount(bloop);
|
|
41
|
-
const snapshot = runtime.snapshot();
|
|
42
|
-
runtime.restore(snapshot);
|
|
43
|
-
expect(bloop.bag.score).toEqual(10);
|
|
44
|
-
});
|
|
45
|
-
|
|
46
|
-
it("snapshots time", async () => {
|
|
47
|
-
const bloop = Bloop.create();
|
|
48
|
-
|
|
49
|
-
const timeCheck = {
|
|
50
|
-
dt: 0,
|
|
51
|
-
time: 0,
|
|
52
|
-
frame: 0,
|
|
53
|
-
};
|
|
54
|
-
|
|
55
|
-
bloop.system("timeCheck", {
|
|
56
|
-
update({ time }) {
|
|
57
|
-
timeCheck.dt = time.dt;
|
|
58
|
-
timeCheck.time = time.time;
|
|
59
|
-
timeCheck.frame = time.frame;
|
|
60
|
-
},
|
|
61
|
-
});
|
|
62
|
-
|
|
63
|
-
const { runtime } = await mount(bloop);
|
|
64
|
-
|
|
65
|
-
runtime.step();
|
|
66
|
-
|
|
67
|
-
expect(timeCheck.dt).toBeCloseTo(0.016);
|
|
68
|
-
expect(timeCheck.time).toBeCloseTo(0.016);
|
|
69
|
-
expect(timeCheck.frame).toEqual(0);
|
|
70
|
-
expect(bloop.context.time.frame).toEqual(1);
|
|
71
|
-
|
|
72
|
-
// const snapshot = bloop.snapshot();
|
|
73
|
-
const snapshot = runtime.snapshot();
|
|
74
|
-
|
|
75
|
-
runtime.step();
|
|
76
|
-
expect(timeCheck.dt).toBeCloseTo(0.016);
|
|
77
|
-
expect(timeCheck.time).toBeCloseTo(0.016 * 2);
|
|
78
|
-
expect(timeCheck.frame).toEqual(1);
|
|
79
|
-
expect(bloop.context.time.frame).toEqual(2);
|
|
80
|
-
|
|
81
|
-
runtime.restore(snapshot);
|
|
82
|
-
expect(bloop.context.time.frame).toEqual(1);
|
|
83
|
-
runtime.step();
|
|
84
|
-
|
|
85
|
-
expect(timeCheck.dt).toBeCloseTo(0.016);
|
|
86
|
-
expect(timeCheck.time).toBeCloseTo(0.016 * 2);
|
|
87
|
-
expect(bloop.context.time.frame).toEqual(2);
|
|
88
|
-
});
|
|
89
|
-
});
|
|
90
|
-
|
|
91
|
-
describe("playback", () => {
|
|
92
|
-
it("can step back", async () => {
|
|
93
|
-
const bloop = Bloop.create({
|
|
94
|
-
bag: {
|
|
95
|
-
clicks: 0,
|
|
96
|
-
},
|
|
97
|
-
});
|
|
98
|
-
|
|
99
|
-
bloop.system("countClicks", {
|
|
100
|
-
update({ bag, inputs }) {
|
|
101
|
-
if (inputs.mouse.left.down) {
|
|
102
|
-
bag.clicks++;
|
|
103
|
-
}
|
|
104
|
-
},
|
|
105
|
-
});
|
|
106
|
-
|
|
107
|
-
const { runtime } = await mount(bloop);
|
|
108
|
-
|
|
109
|
-
runtime.emit.mousedown("Left");
|
|
110
|
-
runtime.step();
|
|
111
|
-
expect(bloop.context.time.frame).toEqual(1);
|
|
112
|
-
expect(bloop.bag.clicks).toEqual(1);
|
|
113
|
-
|
|
114
|
-
runtime.emit.mouseup("Left");
|
|
115
|
-
runtime.step();
|
|
116
|
-
expect(bloop.context.time.frame).toEqual(2);
|
|
117
|
-
expect(bloop.bag.clicks).toEqual(1);
|
|
118
|
-
|
|
119
|
-
runtime.stepBack();
|
|
120
|
-
expect(bloop.context.time.frame).toEqual(1);
|
|
121
|
-
expect(bloop.bag.clicks).toEqual(1);
|
|
122
|
-
|
|
123
|
-
runtime.stepBack();
|
|
124
|
-
expect(bloop.context.time.frame).toEqual(0);
|
|
125
|
-
expect(bloop.bag.clicks).toEqual(0);
|
|
126
|
-
});
|
|
127
|
-
});
|
|
128
|
-
});
|
package/tsconfig.json
DELETED
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"compilerOptions": {
|
|
3
|
-
// Environment setup & latest features
|
|
4
|
-
"lib": ["ESNext"],
|
|
5
|
-
"target": "ESNext",
|
|
6
|
-
"module": "Preserve",
|
|
7
|
-
"moduleDetection": "force",
|
|
8
|
-
"jsx": "react-jsx",
|
|
9
|
-
"allowJs": true,
|
|
10
|
-
|
|
11
|
-
// Bundler mode
|
|
12
|
-
"moduleResolution": "bundler",
|
|
13
|
-
"allowImportingTsExtensions": true,
|
|
14
|
-
"verbatimModuleSyntax": true,
|
|
15
|
-
|
|
16
|
-
// Best practices
|
|
17
|
-
"strict": true,
|
|
18
|
-
"skipLibCheck": true,
|
|
19
|
-
"noFallthroughCasesInSwitch": true,
|
|
20
|
-
"noUncheckedIndexedAccess": true,
|
|
21
|
-
"noImplicitOverride": true,
|
|
22
|
-
|
|
23
|
-
// Some stricter flags (disabled by default)
|
|
24
|
-
"noUnusedLocals": false,
|
|
25
|
-
"noUnusedParameters": false,
|
|
26
|
-
"noPropertyAccessFromIndexSignature": false,
|
|
27
|
-
|
|
28
|
-
// Declarations
|
|
29
|
-
"emitDeclarationOnly": true,
|
|
30
|
-
"declaration": true,
|
|
31
|
-
"outDir": "dist",
|
|
32
|
-
},
|
|
33
|
-
"include": ["src", "test"]
|
|
34
|
-
}
|