bloody-engine 1.0.8 → 1.0.10

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/README.md CHANGED
@@ -1,15 +1,19 @@
1
1
  # Bloody Engine
2
2
 
3
- A WebGL-based 2.5D graphics engine for isometric rendering on Node.js, written in TypeScript. Designed for server-side rendering and headless graphics processing.
3
+ A WebGL-based 2.5D graphics engine for isometric rendering on Node.js, written in TypeScript. Designed for server-side rendering, headless graphics processing, and networked multiplayer games.
4
4
 
5
5
  ## Features
6
6
 
7
- - **2.5D Rendering** - Optimized for isometric and dimetric projections
7
+ - **2.5D Rendering** - Optimized for isometric and dimetric projections with depth sorting
8
8
  - **Server-Side Rendering** - Headless WebGL rendering on Node.js using `gl` and `@kmamal/sdl`
9
9
  - **Batch Rendering** - Efficient sprite batching with GPU-accelerated transformations
10
- - **Resource Management** - Unified asset loading pipeline for textures and resources
10
+ - **Resource Management** - Unified asset loading pipeline for textures and shaders
11
+ - **Input System** - Command queue pattern supporting SDL and network input sources
12
+ - **Networking** - Client-side prediction, server reconciliation, and state synchronization
13
+ - **Simulation** - Pure game logic simulation system with entity management
14
+ - **Game Loop** - Fixed timestep ticker for deterministic game logic
11
15
  - **TypeScript** - Fully typed for excellent developer experience
12
- - **Depth Sorting** - Proper 2.5D occlusion handling
16
+ - **Object Pooling** - Memory-efficient object reuse patterns
13
17
  - **Window Management** - SDL-based window creation for interactive applications
14
18
 
15
19
  ## Installation
@@ -18,15 +22,73 @@ A WebGL-based 2.5D graphics engine for isometric rendering on Node.js, written i
18
22
  npm install bloody-engine
19
23
  ```
20
24
 
25
+ ## API Overview
26
+
27
+ ### Core Graphics
28
+
29
+ | Class | Description |
30
+ |-------|-------------|
31
+ | [GraphicsDevice](src/core/grahpic-device.ts) | Main graphics device with WebGL context management |
32
+ | [Shader](src/core/shader.ts) | Shader program compilation and uniform/attribute management |
33
+ | [Texture](src/core/texture.ts) | Texture creation, binding, and management |
34
+ | [VertexBuffer](src/core/buffer.ts) / [IndexBuffer](src/core/buffer.ts) | GPU buffer management for geometry |
35
+ | [Camera](src/rendering/camera.ts) | 2D camera with position, zoom, and view matrix |
36
+
37
+ ### Rendering
38
+
39
+ | Class | Description |
40
+ |-------|-------------|
41
+ | [BatchRenderer](src/rendering/batch-renderer.ts) | Generic quad batch rendering |
42
+ | [SpriteBatchRenderer](src/rendering/batch-renderer.ts) | Sprite-specific batch renderer with depth sorting |
43
+ | [ProjectionConfig](src/rendering/projection.ts) | Isometric/dimetric projection utilities |
44
+ | [SpatialHash](src/rendering/spatial-hash.ts) | Spatial partitioning for efficient queries |
45
+
46
+ ### Resource Loading
47
+
48
+ | Class | Description |
49
+ |-------|-------------|
50
+ | [NodeResourceLoader](src/platforms/node/node-resource-loader.ts) | File system resource loader for Node.js |
51
+ | [NodeTextureLoader](src/platforms/node/node-texture-loader.ts) | PNG texture loading for Node.js |
52
+ | [ResourcePipeline](src/core/resource-pipeline.ts) | Batch resource loading with caching |
53
+ | [TextureAtlas](src/core/sprite-atlas.ts) | Sprite atlas packing and UV coordinate management |
54
+
55
+ ### Input System
56
+
57
+ | Class | Description |
58
+ |-------|-------------|
59
+ | [CommandQueue](src/input/command-queue.ts) | Thread-safe command queue for input |
60
+ | [SDLInputSource](src/input/sdl-input-source.ts) | SDL keyboard/mouse input |
61
+ | [NetworkInputSource](src/input/networking-input-source.ts) | Network-based input for multiplayer |
62
+
63
+ ### Simulation & Networking
64
+
65
+ | Class | Description |
66
+ |-------|-------------|
67
+ | [Ticker](src/core/ticker.ts) | Fixed timestep game loop |
68
+ | [Entity](src/simulation/entity.ts) / [EntityManager](src/simulation/entity-manager.ts) | Entity component system |
69
+ | [SimulationLoop](src/simulation/simulation-loop.ts) | Deterministic game logic simulation |
70
+ | [ClientPredictor](src/networking/client-predictor.ts) | Client-side prediction for lag compensation |
71
+ | [ServerReconciler](src/networking/server-reconciler.ts) | Server-side reconciliation |
72
+ | [StateSnapshot](src/networking/state-snapshot.ts) | World state serialization |
73
+ | [BinarySerializer](src/networking/binary-serializer.ts) | Efficient binary serialization |
74
+
75
+ ### Utilities
76
+
77
+ | Class | Description |
78
+ |-------|-------------|
79
+ | [ObjectPool](src/core/object-pool.ts) | Generic object pooling for GC optimization |
80
+ | [Matrix4Pool](src/core/matrix-pool.ts) | Matrix4 specific pooling |
81
+ | [lerp](src/core/interpolation.ts), [lerpVec2](src/core/interpolation.ts), [lerpVec3](src/core/interpolation.ts) | Interpolation utilities |
82
+
21
83
  ## Quick Start
22
84
 
85
+ ### Basic Rendering Setup
86
+
23
87
  ```typescript
24
- import { GraphicsDevice, Shader, Texture } from 'bloody-engine';
88
+ import { GraphicsDevice, Shader, Texture, VertexBuffer } from 'bloody-engine';
25
89
 
26
- // Create a graphics device with SDL window
90
+ // Create graphics device (800x600)
27
91
  const device = new GraphicsDevice(800, 600);
28
-
29
- // Get the WebGL context
30
92
  const gl = device.getGLContext();
31
93
 
32
94
  // Create a shader
@@ -46,67 +108,392 @@ const shader = device.createShader(`
46
108
  }
47
109
  `);
48
110
 
49
- // Create a texture from PNG
50
- const { PNG } = require('pngjs');
51
- const fs = require('fs/promises');
52
- const pngData = await fs.readFile('texture.png');
53
- const png = PNG.sync.read(pngData);
54
- const texture = Texture.createFromPNG(gl, png);
111
+ // Create a gradient texture
112
+ const texture = Texture.createGradient(gl, 256, 256);
113
+
114
+ // Create geometry
115
+ const vertices = new Float32Array([
116
+ // x, y, z, u, v
117
+ -0.5, -0.5, 0, 0, 1,
118
+ 0.5, -0.5, 0, 1, 1,
119
+ 0.5, 0.5, 0, 1, 0,
120
+ -0.5, -0.5, 0, 0, 1,
121
+ 0.5, 0.5, 0, 1, 0,
122
+ -0.5, 0.5, 0, 0, 0
123
+ ]);
124
+ const buffer = new VertexBuffer(gl, vertices, 20); // 5 floats * 4 bytes
55
125
 
56
- // Render
126
+ // Setup and render
57
127
  device.clear({ r: 0.1, g: 0.1, b: 0.1, a: 1.0 });
58
128
  shader.use();
59
- // ... rendering code ...
129
+ buffer.bind();
130
+ // ... configure attributes ...
131
+ gl.drawArrays(gl.TRIANGLES, 0, buffer.getVertexCount());
60
132
  device.present();
61
-
62
- // For headless rendering, capture the output
63
- const context = device.getRenderingContext();
64
- const pixels = context.readPixels();
65
133
  ```
66
134
 
67
- ## Examples
68
-
69
- ### Sprite Batch Rendering
135
+ ### Sprite Batch Rendering with Camera
70
136
 
71
137
  ```typescript
72
- import { SpriteBatchRenderer, Camera, Texture } from 'bloody-engine';
138
+ import { SpriteBatchRenderer, Camera, Texture, GraphicsDevice } from 'bloody-engine';
139
+
140
+ const device = new GraphicsDevice(800, 600);
141
+ const gl = device.getGLContext();
73
142
 
143
+ // Create shader (use built-in V2 shader for sprites)
144
+ const shader = device.createShader(vertexSource, fragmentSource);
145
+
146
+ // Create sprite batch renderer (capacity: 1000 sprites)
74
147
  const batchRenderer = new SpriteBatchRenderer(gl, shader, 1000);
75
- const camera = new Camera(0, 0, 1.0);
148
+ batchRenderer.setTexture(Texture.createGradient(gl, 256, 256));
149
+
150
+ // Create camera
151
+ const camera = new Camera(0, 0, 1.0); // x=0, y=0, zoom=1x
76
152
 
77
- // Add sprites
153
+ // Add sprites to batch
78
154
  batchRenderer.addQuad({
79
- x: 100,
80
- y: 100,
81
- z: 0,
82
- width: 64,
83
- height: 64,
155
+ x: 100, y: 100, z: 0,
156
+ width: 64, height: 64,
84
157
  rotation: 0,
85
158
  color: { r: 1, g: 1, b: 1, a: 1 },
86
- uvRect: { uMin: 0, vMin: 0, uMax: 1, vMax: 1 }
159
+ texIndex: 0
87
160
  });
88
161
 
89
- // Render
162
+ // Render with camera
163
+ device.clear({ r: 0.1, g: 0.1, b: 0.1, a: 1.0 });
90
164
  batchRenderer.render(camera);
165
+ device.present();
91
166
  ```
92
167
 
93
168
  ### Resource Loading
94
169
 
95
170
  ```typescript
96
- import { NodeResourceLoader } from 'bloody-engine';
97
-
98
- const loader = new NodeResourceLoader('./assets');
171
+ import {
172
+ ResourceLoaderFactory,
173
+ createResourcePipeline,
174
+ NodeTextureLoader
175
+ } from 'bloody-engine';
176
+
177
+ // Create resource pipeline
178
+ const pipeline = await createResourcePipeline({
179
+ concurrency: 5,
180
+ cache: true,
181
+ baseDir: process.cwd()
182
+ });
99
183
 
100
- // Load a shader
101
- const vertexSource = await loader.load('shaders/basic.vert');
102
- const fragmentSource = await loader.load('shaders/basic.frag');
184
+ // Load shaders
185
+ const shaders = await pipeline.loadShaders([
186
+ { name: 'basic', vertex: 'shaders/basic.vert', fragment: 'shaders/basic.frag' }
187
+ ]);
103
188
 
104
- // Batch load multiple resources
105
- const { succeeded, failed } = await loader.loadMultiple([
189
+ // Batch load resources
190
+ const { succeeded, failed } = await pipeline.loadMultiple([
106
191
  'textures/sprite1.png',
107
- 'textures/sprite2.png',
108
- 'shaders/shader.vert'
192
+ 'textures/sprite2.png'
109
193
  ]);
194
+
195
+ // Load texture from PNG
196
+ const textureLoader = new NodeTextureLoader();
197
+ const texture = await textureLoader.loadTexture(gl, 'textures/sprite.png');
198
+ ```
199
+
200
+ ### Game Loop with Fixed Timestep
201
+
202
+ ```typescript
203
+ import { Ticker, type TickerConfig } from 'bloody-engine';
204
+
205
+ const config: TickerConfig = {
206
+ targetFPS: 60,
207
+ fixedDeltaTime: 1 / 60, // 60 physics updates per second
208
+ maxFrameTime: 0.25 // Prevent spiral of death
209
+ };
210
+
211
+ const ticker = new Ticker(config);
212
+
213
+ ticker.start({
214
+ update: (deltaTime) => {
215
+ // Game logic update (fixed timestep)
216
+ console.log(`Update: ${deltaTime.toFixed(3)}s`);
217
+ },
218
+ render: (interpolation) => {
219
+ // Render with interpolation factor
220
+ console.log(`Render: interpolation=${interpolation.toFixed(3)}`);
221
+ }
222
+ });
223
+
224
+ // Get performance metrics
225
+ const metrics = ticker.getMetrics();
226
+ console.log(`FPS: ${metrics.fps}, Delta Time: ${metrics.deltaTime}s`);
227
+ ```
228
+
229
+ ### Entity System
230
+
231
+ ```typescript
232
+ import { Entity, EntityManager, type EntityState } from 'bloody-engine';
233
+
234
+ // Create entity
235
+ const entity = new Entity({
236
+ id: 'player-1',
237
+ x: 0, y: 0, z: 0,
238
+ rotation: 0,
239
+ type: 'player',
240
+ health: 100
241
+ });
242
+
243
+ // Create entity manager
244
+ const manager = new EntityManager();
245
+ manager.add(entity);
246
+
247
+ // Query entities
248
+ const players = manager.query({ type: 'player' });
249
+ const nearby = manager.queryInRegion(0, 0, 100);
250
+
251
+ // Update entity
252
+ entity.x += 10;
253
+ entity.updatedAt = Date.now();
254
+ manager.update(entity);
255
+ ```
256
+
257
+ ### Input System with Command Queue
258
+
259
+ ```typescript
260
+ import {
261
+ CommandQueue,
262
+ SDLInputSource,
263
+ createSDLInputSource,
264
+ CommandType
265
+ } from 'bloody-engine';
266
+
267
+ // Create command queue
268
+ const queue = new CommandQueue();
269
+
270
+ // Create SDL input source (requires SDL window)
271
+ const sdlWindow = new SDLWindow(800, 600, 'Game');
272
+ const inputSource = createSDLInputSource(sdlWindow, {
273
+ keyMapping: {
274
+ moveUp: ['w', 'arrowup'],
275
+ moveDown: ['s', 'arrowdown'],
276
+ moveLeft: ['a', 'arrowleft'],
277
+ moveRight: ['d', 'arrowright']
278
+ }
279
+ });
280
+
281
+ // Process input in game loop
282
+ while (running) {
283
+ // Collect input commands
284
+ inputSource.update(queue);
285
+
286
+ // Process commands
287
+ while (queue.hasCommands()) {
288
+ const command = queue.dequeue();
289
+ switch (command.type) {
290
+ case CommandType.Move:
291
+ handleMove(command);
292
+ break;
293
+ case CommandType.Attack:
294
+ handleAttack(command);
295
+ break;
296
+ }
297
+ }
298
+ }
299
+ ```
300
+
301
+ ### Networking - Client-Side Prediction
302
+
303
+ ```typescript
304
+ import {
305
+ createClientPredictor,
306
+ ClientPredictor,
307
+ type ClientInputMessage
308
+ } from 'bloody-engine';
309
+
310
+ // Create predictor with config
311
+ const predictor = createClientPredictor({
312
+ maxPredictedTicks: 100,
313
+ reconciliationDelay: 100 // ms
314
+ });
315
+
316
+ // Client loop: send input
317
+ const onInput = (input: MoveCommand) => {
318
+ const tick = currentTick;
319
+ predictor.addLocalInput(tick, input);
320
+
321
+ // Send to server
322
+ socket.send(JSON.stringify({
323
+ type: 'client_input',
324
+ tick,
325
+ input
326
+ } as ClientInputMessage));
327
+ };
328
+
329
+ // Receive server update
330
+ const onServerUpdate = (message: ServerStateUpdateMessage) => {
331
+ const result = predictor.reconcile(message);
332
+
333
+ if (result.corrected) {
334
+ console.log(`Reconciled: corrected=${result.corrected}, error=${result.error}`);
335
+ }
336
+ };
337
+ ```
338
+
339
+ ### Object Pooling for Performance
340
+
341
+ ```typescript
342
+ import { ObjectPool, type ObjectPoolConfig } from 'bloody-engine';
343
+
344
+ // Create pool for Vector3 objects
345
+ const pool = new ObjectPool<Vector3>({
346
+ initialSize: 100,
347
+ growthFactor: 2,
348
+ factory: () => ({ x: 0, y: 0, z: 0 }),
349
+ reset: (obj) => { obj.x = 0; obj.y = 0; obj.z = 0; }
350
+ });
351
+
352
+ // Acquire from pool
353
+ const vec = pool.acquire();
354
+ vec.x = 10; vec.y = 20; vec.z = 30;
355
+
356
+ // Return to pool when done
357
+ pool.release(vec);
358
+
359
+ // Get pool statistics
360
+ const stats = pool.getStats();
361
+ console.log(`Size: ${stats.size}, Active: ${stats.active}, Hits: ${stats.hits}`);
362
+ ```
363
+
364
+ ### Isometric Projection
365
+
366
+ ```typescript
367
+ import { ProjectionConfig, gridToScreen, screenToGrid } from 'bloody-engine';
368
+
369
+ // Configure isometric projection
370
+ const config = new ProjectionConfig({
371
+ tileWidth: 64,
372
+ tileHeight: 32,
373
+ angle: Math.PI / 6, // 30 degrees
374
+ screenWidth: 800,
375
+ screenHeight: 600
376
+ });
377
+
378
+ // Convert grid to screen coordinates
379
+ const gridPos = { xgrid: 5, ygrid: 3, zheight: 0 };
380
+ const screenPos = gridToScreen(gridPos, config);
381
+ console.log(`Screen: x=${screenPos.xscreen}, y=${screenPos.yscreen}`);
382
+
383
+ // Convert screen to grid coordinates
384
+ const gridPos2 = screenToGrid(screenPos, config);
385
+ ```
386
+
387
+ ### Texture Atlas for Sprite Sheets
388
+
389
+ ```typescript
390
+ import { TextureAtlas, AtlasLoader } from 'bloody-engine';
391
+
392
+ // Load sprite atlas
393
+ const atlas = await AtlasLoader.loadFromJSON(gl, 'atlas.json');
394
+
395
+ // Get sprite info
396
+ const sprite = atlas.getSprite('player_idle_01');
397
+
398
+ // Use UV rect for rendering
399
+ batchRenderer.addQuad({
400
+ x: 100, y: 100, z: 0,
401
+ width: sprite.pixelRect.width,
402
+ height: sprite.pixelRect.height,
403
+ uvRect: sprite.uvRect
404
+ });
405
+ ```
406
+
407
+ ## Advanced Examples
408
+
409
+ ### Networked Game Architecture
410
+
411
+ ```typescript
412
+ import {
413
+ SimulationLoop,
414
+ Entity,
415
+ ClientPredictor,
416
+ ServerReconciler,
417
+ StateSnapshot,
418
+ Ticker
419
+ } from 'bloody-engine';
420
+
421
+ // Server-side simulation
422
+ const serverSim = new SimulationLoop({
423
+ fixedDeltaTime: 1 / 60
424
+ });
425
+
426
+ // Client-side prediction
427
+ const clientPredictor = createClientPredictor({
428
+ maxPredictedTicks: 100
429
+ });
430
+
431
+ // Server reconciliation
432
+ const serverReconciler = createServerReconciler({
433
+ maxRewindTicks: 50
434
+ });
435
+
436
+ // Game loop on client
437
+ const ticker = new Ticker({ targetFPS: 60 });
438
+ ticker.start({
439
+ update: (deltaTime) => {
440
+ // 1. Collect input and send to server
441
+ const input = collectInput();
442
+ socket.send({ type: 'input', input, tick: currentTick });
443
+
444
+ // 2. Predict locally
445
+ clientPredictor.addLocalInput(currentTick, input);
446
+ const predictedState = predictState();
447
+
448
+ // 3. Handle server updates
449
+ onServerUpdate = (update) => {
450
+ clientPredictor.reconcile(update);
451
+ };
452
+ },
453
+ render: (interpolation) => {
454
+ renderGame(clientPredictor.getLatestState(), interpolation);
455
+ }
456
+ });
457
+ ```
458
+
459
+ ### Deterministic Simulation Testing
460
+
461
+ ```typescript
462
+ import { SimulationLoop, Entity } from 'bloody-engine';
463
+
464
+ // Create two simulations for testing determinism
465
+ const sim1 = new SimulationLoop({ fixedDeltaTime: 1 / 60, seed: 12345 });
466
+ const sim2 = new SimulationLoop({ fixedDeltaTime: 1 / 60, seed: 12345 });
467
+
468
+ // Add identical entities
469
+ sim1.addEntity(new Entity({ id: '1', x: 0, y: 0 }));
470
+ sim2.addEntity(new Entity({ id: '1', x: 0, y: 0 }));
471
+
472
+ // Run simulations
473
+ for (let i = 0; i < 1000; i++) {
474
+ sim1.update(1 / 60);
475
+ sim2.update(1 / 60);
476
+ }
477
+
478
+ // Verify determinism
479
+ const state1 = sim1.getStateSnapshot();
480
+ const state2 = sim2.getStateSnapshot();
481
+ console.log('Deterministic:', JSON.stringify(state1) === JSON.stringify(state2));
482
+ ```
483
+
484
+ ## Testing
485
+
486
+ The engine includes comprehensive tests for determinism and visual regression:
487
+
488
+ ```bash
489
+ # Run all tests
490
+ npm test
491
+
492
+ # Run specific test suites
493
+ npm run test:determinism # Test simulation determinism
494
+ npm run test:visual # Visual regression tests
495
+ npm run test:state-sync # State synchronization tests
496
+ npm run test:coverage # Generate coverage report
110
497
  ```
111
498
 
112
499
  ## Dependencies
@@ -115,8 +502,61 @@ const { succeeded, failed } = await loader.loadMultiple([
115
502
  - **@kmamal/sdl** - SDL2 bindings for window and input management
116
503
  - **pngjs** - PNG image decoding
117
504
 
505
+ ## Platform Support
506
+
507
+ | Platform | Status | Notes |
508
+ |----------|--------|-------|
509
+ | Node.js (Linux) | ✅ Full | Headless rendering + SDL window |
510
+ | Node.js (macOS) | ✅ Full | Headless rendering + SDL window |
511
+ | Node.js (Windows) | ✅ Full | Headless rendering + SDL window |
512
+ | Browser | ⚠️ Planned | WebGL rendering planned |
513
+
118
514
  ## Documentation
119
515
 
516
+ ### Source Code Organization
517
+
518
+ ```
519
+ src/
520
+ ├── core/ # Core graphics and utilities
521
+ │ ├── grahpic-device.ts
522
+ │ ├── shader.ts
523
+ │ ├── texture.ts
524
+ │ ├── buffer.ts
525
+ │ ├── object-pool.ts
526
+ │ └── ticker.ts
527
+ ├── rendering/ # Rendering systems
528
+ │ ├── batch-renderer.ts
529
+ │ ├── camera.ts
530
+ │ ├── projection.ts
531
+ │ └── spatial-hash.ts
532
+ ├── input/ # Input system (command queue)
533
+ │ ├── command-queue.ts
534
+ │ ├── sdl-input-source.ts
535
+ │ └── network-input-source.ts
536
+ ├── simulation/ # Game logic simulation
537
+ │ ├── entity.ts
538
+ │ ├── entity-manager.ts
539
+ │ └── simulation-loop.ts
540
+ ├── networking/ # Networking for multiplayer
541
+ │ ├── client-predictor.ts
542
+ │ ├── server-reconciler.ts
543
+ │ ├── state-snapshot.ts
544
+ │ └── binary-serializer.ts
545
+ └── platforms/
546
+ └── node/ # Node.js-specific implementations
547
+ ├── node-context.ts
548
+ ├── node-resource-loader.ts
549
+ └── sdl-window.ts
550
+ ```
551
+
552
+ ### Key Concepts
553
+
554
+ - **Separation of Concerns**: Rendering, input, simulation, and networking are completely separate systems
555
+ - **Deterministic Simulation**: Game logic runs in fixed timestep for consistency across clients
556
+ - **Command Pattern**: All input goes through a command queue for easy recording/replay
557
+ - **Client-Side Prediction**: Reduces perceived lag in networked games
558
+ - **Object Pooling**: Minimizes garbage collection for smooth performance
559
+
120
560
  For detailed documentation and architecture, see [docs/README.MD](docs/README.MD).
121
561
 
122
562
  ## Building
@@ -5237,15 +5237,13 @@ class StateSnapshot {
5237
5237
  * Serialize snapshot to binary format
5238
5238
  */
5239
5239
  toBinary() {
5240
- const { BinarySerializer: BinarySerializer2 } = require("./binary-serializer");
5241
- const serializer = new BinarySerializer2();
5240
+ const serializer = new BinarySerializer();
5242
5241
  serializer.writeUint32(this.tick);
5243
5242
  serializer.writeFloat64(this.timestamp);
5244
5243
  serializer.writeUint16(this.entities.size);
5245
5244
  for (const [entityId, state] of this.entities.entries()) {
5246
5245
  serializer.writeString(entityId);
5247
- const { EntitySerializer: EntitySerializer2 } = require("./entity-serializer");
5248
- const stateData = EntitySerializer2.serializeEntityState(state);
5246
+ const stateData = EntitySerializer.serializeEntityState(state);
5249
5247
  serializer.writeBytes(stateData);
5250
5248
  }
5251
5249
  return serializer.toBuffer();
@@ -5254,9 +5252,7 @@ class StateSnapshot {
5254
5252
  * Deserialize snapshot from binary format
5255
5253
  */
5256
5254
  static fromBinary(data) {
5257
- const { BinaryReader: BinaryReader2 } = require("./binary-serializer");
5258
- const { EntitySerializer: EntitySerializer2 } = require("./entity-serializer");
5259
- const reader = new BinaryReader2(data);
5255
+ const reader = new BinaryReader(data);
5260
5256
  const tick = reader.readUint32();
5261
5257
  const timestamp = reader.readFloat64();
5262
5258
  const entityCount = reader.readUint16();
@@ -5267,7 +5263,7 @@ class StateSnapshot {
5267
5263
  reader.setOffset(reader.getOffset() - 1);
5268
5264
  const stateDataLength = StateSnapshot.estimateEntityStateSize();
5269
5265
  const actualData = reader.readBytes(stateDataLength);
5270
- const state = EntitySerializer2.deserializeEntityState(actualData);
5266
+ const state = EntitySerializer.deserializeEntityState(actualData);
5271
5267
  entities.set(entityId, state);
5272
5268
  }
5273
5269
  return new StateSnapshot(tick, entities, timestamp);
@@ -1 +1 @@
1
- {"version":3,"file":"state-snapshot.d.ts","sourceRoot":"","sources":["../../../src/networking/state-snapshot.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AACnD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AACxD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AAE3D;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;IAC3B,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED;;GAEG;AACH,qBAAa,aAAc,YAAW,mBAAmB;IACvD,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;IAC5C,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;gBAEf,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,WAAW,CAAC,EAAE,SAAS,CAAC,EAAE,MAAM;IAMhF;;OAEG;IACH,MAAM,CAAC,YAAY,CACjB,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,EAAE,EAClB,OAAO,GAAE,eAAoB,GAC5B,aAAa;IAsBhB;;OAEG;IACH,MAAM,CAAC,OAAO,CACZ,IAAI,EAAE,MAAM,EACZ,SAAS,EAAE,GAAG,CAAC,MAAM,EAAE,WAAW,CAAC,EACnC,SAAS,CAAC,EAAE,MAAM,GACjB,aAAa;IAchB;;OAEG;IACH,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,WAAW,GAAG,SAAS;IAczD;;OAEG;IACH,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO;IAIpC;;OAEG;IACH,YAAY,IAAI,MAAM,EAAE;IAIxB;;OAEG;IACH,IAAI,IAAI,IAAI,MAAM,CAEjB;IAED;;OAEG;IACH,OAAO,IAAI,OAAO;IAIlB;;OAEG;IACH,MAAM,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,aAAa;IAe1C;;OAEG;IACH,KAAK,CAAC,KAAK,EAAE,aAAa,GAAG,aAAa;IA4B1C;;OAEG;IACH,KAAK,IAAI,aAAa;IAItB;;OAEG;IACH,OAAO,IAAI,mBAAmB;IAQ9B;;OAEG;IACH,MAAM,CAAC,SAAS,CAAC,KAAK,EAAE,mBAAmB,GAAG,aAAa;IAI3D;;OAEG;IACH,QAAQ,IAAI,UAAU;IA+BtB;;OAEG;IACH,MAAM,CAAC,UAAU,CAAC,IAAI,EAAE,UAAU,GAAG,aAAa;IAkClD;;;OAGG;IACH,OAAO,CAAC,MAAM,CAAC,uBAAuB;IAKtC;;OAEG;IACH,QAAQ,IAAI,MAAM;IAIlB;;OAEG;IACH,MAAM,CAAC,KAAK,EAAE,aAAa,GAAG,OAAO;CA+BtC"}
1
+ {"version":3,"file":"state-snapshot.d.ts","sourceRoot":"","sources":["../../../src/networking/state-snapshot.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AACnD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AACxD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AAI3D;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;IAC3B,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED;;GAEG;AACH,qBAAa,aAAc,YAAW,mBAAmB;IACvD,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;IAC5C,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;gBAEf,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,WAAW,CAAC,EAAE,SAAS,CAAC,EAAE,MAAM;IAMhF;;OAEG;IACH,MAAM,CAAC,YAAY,CACjB,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,EAAE,EAClB,OAAO,GAAE,eAAoB,GAC5B,aAAa;IAsBhB;;OAEG;IACH,MAAM,CAAC,OAAO,CACZ,IAAI,EAAE,MAAM,EACZ,SAAS,EAAE,GAAG,CAAC,MAAM,EAAE,WAAW,CAAC,EACnC,SAAS,CAAC,EAAE,MAAM,GACjB,aAAa;IAchB;;OAEG;IACH,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,WAAW,GAAG,SAAS;IAczD;;OAEG;IACH,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO;IAIpC;;OAEG;IACH,YAAY,IAAI,MAAM,EAAE;IAIxB;;OAEG;IACH,IAAI,IAAI,IAAI,MAAM,CAEjB;IAED;;OAEG;IACH,OAAO,IAAI,OAAO;IAIlB;;OAEG;IACH,MAAM,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,aAAa;IAe1C;;OAEG;IACH,KAAK,CAAC,KAAK,EAAE,aAAa,GAAG,aAAa;IA4B1C;;OAEG;IACH,KAAK,IAAI,aAAa;IAItB;;OAEG;IACH,OAAO,IAAI,mBAAmB;IAQ9B;;OAEG;IACH,MAAM,CAAC,SAAS,CAAC,KAAK,EAAE,mBAAmB,GAAG,aAAa;IAI3D;;OAEG;IACH,QAAQ,IAAI,UAAU;IAyBtB;;OAEG;IACH,MAAM,CAAC,UAAU,CAAC,IAAI,EAAE,UAAU,GAAG,aAAa;IA8BlD;;;OAGG;IACH,OAAO,CAAC,MAAM,CAAC,uBAAuB;IAKtC;;OAEG;IACH,QAAQ,IAAI,MAAM;IAIlB;;OAEG;IACH,MAAM,CAAC,KAAK,EAAE,aAAa,GAAG,OAAO;CA+BtC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bloody-engine",
3
- "version": "1.0.8",
3
+ "version": "1.0.10",
4
4
  "description": "A WebGL-based 2.5D graphics engine for isometric rendering",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -1,10 +0,0 @@
1
- /**
2
- * Determinism Test for Bloody Engine
3
- *
4
- * This test verifies that the simulation is deterministic:
5
- * - Runs two instances of the SimulationLoop with the same input seed
6
- * - Compares the state of all entities after 1000 ticks
7
- * - They must match perfectly
8
- */
9
- export {};
10
- //# sourceMappingURL=determinism.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"determinism.test.d.ts","sourceRoot":"","sources":["../../../src/tests/determinism.test.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG"}
@@ -1,5 +0,0 @@
1
- /**
2
- * Tests for 2.5D Isometric Projection Mathematics
3
- */
4
- export {};
5
- //# sourceMappingURL=projection.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"projection.test.d.ts","sourceRoot":"","sources":["../../../src/tests/projection.test.ts"],"names":[],"mappings":"AAAA;;GAEG"}
@@ -1,13 +0,0 @@
1
- /**
2
- * State Synchronization Integration Test
3
- *
4
- * Tests the complete state synchronization pipeline:
5
- * 1. Binary serialization
6
- * 2. State snapshots
7
- * 3. Client-side prediction
8
- * 4. Server reconciliation
9
- *
10
- * Run with: npm run test:state-sync
11
- */
12
- export {};
13
- //# sourceMappingURL=state-sync.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"state-sync.test.d.ts","sourceRoot":"","sources":["../../../src/tests/state-sync.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG"}
@@ -1,13 +0,0 @@
1
- /**
2
- * Visual Regression Test for Bloody Engine
3
- *
4
- * This test:
5
- * 1. Initializes the engine in headless mode
6
- * 2. Loads a test scene
7
- * 3. Renders one frame
8
- * 4. Captures the framebuffer using gl.readPixels
9
- * 5. Saves as output.png
10
- * 6. Compares against reference.png (if exists)
11
- */
12
- export {};
13
- //# sourceMappingURL=visual-regression.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"visual-regression.test.d.ts","sourceRoot":"","sources":["../../../src/tests/visual-regression.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG"}