@woosh/meep-engine 2.165.0 → 2.165.2

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.
Files changed (205) hide show
  1. package/README.md +137 -108
  2. package/build/bundle-worker-image-decoder.js +1 -1
  3. package/package.json +1 -1
  4. package/samples/generation/SampleGenerator0.js +3 -3
  5. package/samples/generation/filters/SampleGroundMoistureFilter.js +63 -56
  6. package/samples/generation/filters/SampleNoise20_0.js +6 -1
  7. package/samples/generation/themes/SampleTheme0.js +47 -47
  8. package/src/core/color/YCoCg/rgb_to_ycocg.d.ts +17 -0
  9. package/src/core/color/YCoCg/rgb_to_ycocg.d.ts.map +1 -0
  10. package/src/core/color/YCoCg/rgb_to_ycocg.js +20 -0
  11. package/src/core/color/YCoCg/ycocg_to_rgb.d.ts +14 -0
  12. package/src/core/color/YCoCg/ycocg_to_rgb.d.ts.map +1 -0
  13. package/src/core/color/YCoCg/ycocg_to_rgb.js +17 -0
  14. package/src/engine/REVIEW_2026_07_03.md +211 -0
  15. package/src/engine/animation/curve/actionProcessorOperations/curveActions.d.ts.map +1 -1
  16. package/src/engine/animation/curve/actionProcessorOperations/curveActions.js +3 -2
  17. package/src/engine/animation/curve/compression/sample_animation_curve_to_float_array.js +1 -1
  18. package/src/engine/animation/keyed2/AnimationTrackPlayback.d.ts.map +1 -1
  19. package/src/engine/animation/keyed2/AnimationTrackPlayback.js +3 -1
  20. package/src/engine/asset/loaders/image/png/filter/png_filter_unFilterNone.js +2 -2
  21. package/src/engine/asset/preloader/AssetPreloader.d.ts.map +1 -1
  22. package/src/engine/asset/preloader/AssetPreloader.js +6 -0
  23. package/src/engine/control/first-person/sensors/FirstPersonSensorsSystem.d.ts.map +1 -1
  24. package/src/engine/control/first-person/sensors/FirstPersonSensorsSystem.js +5 -2
  25. package/src/engine/ecs/Entity.js +1 -1
  26. package/src/engine/ecs/EntityComponentDataset.d.ts.map +1 -1
  27. package/src/engine/ecs/EntityComponentDataset.js +1 -0
  28. package/src/engine/ecs/EntityManager.d.ts.map +1 -1
  29. package/src/engine/ecs/EntityManager.js +12 -8
  30. package/src/engine/ecs/EntityObserver.js +1 -1
  31. package/src/engine/ecs/System.d.ts.map +1 -1
  32. package/src/engine/ecs/System.js +4 -0
  33. package/src/engine/ecs/animation/AnimationClip.js +1 -1
  34. package/src/engine/ecs/attachment/AttachmentSystem.js +2 -2
  35. package/src/engine/ecs/attachment/TransformAttachmentBinding.d.ts.map +1 -1
  36. package/src/engine/ecs/attachment/TransformAttachmentBinding.js +11 -0
  37. package/src/engine/ecs/fow/FogOfWar.js +2 -2
  38. package/src/engine/ecs/fow/shader/screenSpaceFogOfWarShader.d.ts.map +1 -1
  39. package/src/engine/ecs/fow/shader/screenSpaceFogOfWarShader.js +27 -9
  40. package/src/engine/ecs/gui/hud/HeadsUpDisplaySystem.js +1 -1
  41. package/src/engine/ecs/gui/position/ViewportPosition.d.ts +3 -1
  42. package/src/engine/ecs/gui/position/ViewportPosition.d.ts.map +1 -1
  43. package/src/engine/ecs/gui/position/ViewportPosition.js +4 -1
  44. package/src/engine/ecs/storage/binary/BinarySerializationRegistry.d.ts +10 -0
  45. package/src/engine/ecs/storage/binary/BinarySerializationRegistry.d.ts.map +1 -1
  46. package/src/engine/ecs/storage/binary/BinarySerializationRegistry.js +43 -0
  47. package/src/engine/ecs/storage/binary/object-v2/BinaryObjectDeSerializer.d.ts +93 -0
  48. package/src/engine/ecs/storage/binary/object-v2/BinaryObjectDeSerializer.d.ts.map +1 -0
  49. package/src/engine/ecs/storage/binary/object-v2/BinaryObjectDeSerializer.js +315 -0
  50. package/src/engine/ecs/storage/binary/object-v2/BinaryObjectSerializer.d.ts +48 -0
  51. package/src/engine/ecs/storage/binary/object-v2/BinaryObjectSerializer.d.ts.map +1 -0
  52. package/src/engine/ecs/storage/binary/object-v2/BinaryObjectSerializer.js +331 -0
  53. package/src/engine/ecs/storage/binary/object-v2/DESIGN.md +199 -0
  54. package/src/engine/ecs/storage/binary/object-v2/ObjectBinaryFormat.d.ts +53 -0
  55. package/src/engine/ecs/storage/binary/object-v2/ObjectBinaryFormat.d.ts.map +1 -0
  56. package/src/engine/ecs/storage/binary/object-v2/ObjectBinaryFormat.js +57 -0
  57. package/src/engine/ecs/storage/binary/object-v2/ObjectSerializationAdapter.d.ts +53 -0
  58. package/src/engine/ecs/storage/binary/object-v2/ObjectSerializationAdapter.d.ts.map +1 -0
  59. package/src/engine/ecs/storage/binary/object-v2/ObjectSerializationAdapter.js +56 -0
  60. package/src/engine/ecs/storage/binary/object-v2/README.md +110 -0
  61. package/src/engine/ecs/storage/binary/object-v2/objectStringCodec.d.ts +13 -0
  62. package/src/engine/ecs/storage/binary/object-v2/objectStringCodec.d.ts.map +1 -0
  63. package/src/engine/ecs/storage/binary/object-v2/objectStringCodec.js +48 -0
  64. package/src/engine/ecs/storage/binary/object-v2/serializerTestHarness.d.ts +29 -0
  65. package/src/engine/ecs/storage/binary/object-v2/serializerTestHarness.d.ts.map +1 -0
  66. package/src/engine/ecs/storage/binary/object-v2/serializerTestHarness.js +44 -0
  67. package/src/engine/ecs/system_validate_class.d.ts.map +1 -1
  68. package/src/engine/ecs/system_validate_class.js +9 -2
  69. package/src/engine/graphics/camera/makeScreenScissorFrustum.d.ts.map +1 -1
  70. package/src/engine/graphics/camera/makeScreenScissorFrustum.js +11 -10
  71. package/src/engine/graphics/canvas/canvas2d_draw_linear_scale.d.ts.map +1 -1
  72. package/src/engine/graphics/canvas/canvas2d_draw_linear_scale.js +3 -1
  73. package/src/engine/graphics/ecs/animation/animator/graph/definition/serialization/readAnimationGraphDefinitionFromJSON.d.ts +1 -1
  74. package/src/engine/graphics/ecs/animation/animator/graph/definition/serialization/readAnimationGraphDefinitionFromJSON.d.ts.map +1 -1
  75. package/src/engine/graphics/ecs/animation/animator/graph/definition/serialization/readAnimationGraphDefinitionFromJSON.js +2 -2
  76. package/src/engine/graphics/ecs/animation/animator/graph/definition/serialization/writeAnimationGraphDefinitionToJSON.d.ts.map +1 -1
  77. package/src/engine/graphics/ecs/animation/animator/graph/definition/serialization/writeAnimationGraphDefinitionToJSON.js +2 -0
  78. package/src/engine/graphics/ecs/camera/Camera.d.ts.map +1 -1
  79. package/src/engine/graphics/ecs/camera/Camera.js +4 -0
  80. package/src/engine/graphics/ecs/camera/auto_set_camera_clipping_planes.d.ts.map +1 -1
  81. package/src/engine/graphics/ecs/camera/auto_set_camera_clipping_planes.js +7 -2
  82. package/src/engine/graphics/ecs/camera/set_camera_aspect_ratio.js +1 -1
  83. package/src/engine/graphics/ecs/highlight/system/ShadedGeometryHighlightSystem.d.ts.map +1 -1
  84. package/src/engine/graphics/ecs/highlight/system/ShadedGeometryHighlightSystem.js +4 -1
  85. package/src/engine/graphics/ecs/light/binding/LightBinding.js +2 -2
  86. package/src/engine/graphics/ecs/mesh/MeshSystem.js +1 -1
  87. package/src/engine/graphics/ecs/mesh/SkeletonUtils.js +1 -1
  88. package/src/engine/graphics/ecs/mesh-v2/sg_hierarchy_compute_bounding_box_via_parent_entity.js +1 -1
  89. package/src/engine/graphics/ecs/water/WaterSystem.d.ts +6 -0
  90. package/src/engine/graphics/ecs/water/WaterSystem.d.ts.map +1 -1
  91. package/src/engine/graphics/ecs/water/WaterSystem.js +12 -1
  92. package/src/engine/graphics/geometry/buffered/ensureGeometryBoundingSphere.js +1 -1
  93. package/src/engine/graphics/geometry/buffered/query/bvh32_geometry_nearest.d.ts.map +1 -1
  94. package/src/engine/graphics/geometry/buffered/query/bvh32_geometry_nearest.js +0 -15
  95. package/src/engine/graphics/geometry/instancing/InstancedMeshGroup.js +10 -10
  96. package/src/engine/graphics/geometry/optimization/merge/merge_geometry_hierarchy.js +1 -1
  97. package/src/engine/graphics/material/SplatMaterial.js +1 -1
  98. package/src/engine/graphics/particles/particular/engine/emitter/ParticleEmitter.d.ts.map +1 -1
  99. package/src/engine/graphics/particles/particular/engine/emitter/ParticleEmitter.js +3 -2
  100. package/src/engine/graphics/particles/particular/engine/emitter/ParticlePool.js +1 -1
  101. package/src/engine/graphics/particles/particular/group/ParticleGroup.d.ts.map +1 -1
  102. package/src/engine/graphics/particles/particular/group/ParticleGroup.js +3 -2
  103. package/src/engine/graphics/render/forward_plus/plugin/ForwardPlusRenderingPlugin.js +1 -1
  104. package/src/engine/graphics/sh3/gi/material/MaterialTransformer.d.ts +1 -8
  105. package/src/engine/graphics/sh3/gi/material/MaterialTransformer.d.ts.map +1 -1
  106. package/src/engine/graphics/sh3/gi/material/MaterialTransformer.js +2 -14
  107. package/src/engine/graphics/sh3/gi/material/ProbeResolutionStage.d.ts +9 -0
  108. package/src/engine/graphics/sh3/gi/material/ProbeResolutionStage.d.ts.map +1 -0
  109. package/src/engine/graphics/sh3/gi/material/ProbeResolutionStage.js +14 -0
  110. package/src/engine/graphics/sh3/lightmap/bake_lightmap_for_scene.d.ts.map +1 -1
  111. package/src/engine/graphics/sh3/lightmap/bake_lightmap_for_scene.js +4 -1
  112. package/src/engine/graphics/sh3/lpg/LightProbeGrid.d.ts +69 -0
  113. package/src/engine/graphics/sh3/lpg/LightProbeGrid.d.ts.map +1 -0
  114. package/src/engine/graphics/sh3/lpg/LightProbeGrid.js +173 -0
  115. package/src/engine/graphics/sh3/lpg/LightProbeGridBaker.d.ts +24 -0
  116. package/src/engine/graphics/sh3/lpg/LightProbeGridBaker.d.ts.map +1 -0
  117. package/src/engine/graphics/sh3/lpg/LightProbeGridBaker.js +88 -0
  118. package/src/engine/graphics/sh3/lpg/build_light_probe_grid_for_scene.d.ts +20 -0
  119. package/src/engine/graphics/sh3/lpg/build_light_probe_grid_for_scene.d.ts.map +1 -0
  120. package/src/engine/graphics/sh3/lpg/build_light_probe_grid_for_scene.js +79 -0
  121. package/src/engine/graphics/sh3/lpg/light_probe_grid_obtain_storage_cached.d.ts +11 -0
  122. package/src/engine/graphics/sh3/lpg/light_probe_grid_obtain_storage_cached.d.ts.map +1 -0
  123. package/src/engine/graphics/sh3/lpg/light_probe_grid_obtain_storage_cached.js +84 -0
  124. package/src/engine/graphics/sh3/lpg/light_probe_grid_textures.d.ts +29 -0
  125. package/src/engine/graphics/sh3/lpg/light_probe_grid_textures.d.ts.map +1 -0
  126. package/src/engine/graphics/sh3/lpg/light_probe_grid_textures.js +160 -0
  127. package/src/engine/graphics/sh3/lpg/material/LightProbeGridMaterialTransformer.d.ts +23 -0
  128. package/src/engine/graphics/sh3/lpg/material/LightProbeGridMaterialTransformer.d.ts.map +1 -0
  129. package/src/engine/graphics/sh3/lpg/material/LightProbeGridMaterialTransformer.js +228 -0
  130. package/src/engine/graphics/sh3/lpg/material/chunk_lpg_get_irradiance_at.d.ts +2 -0
  131. package/src/engine/graphics/sh3/lpg/material/chunk_lpg_get_irradiance_at.d.ts.map +1 -0
  132. package/src/engine/graphics/sh3/lpg/material/chunk_lpg_get_irradiance_at.js +24 -0
  133. package/src/engine/graphics/sh3/lpg/material/common.d.ts +3 -0
  134. package/src/engine/graphics/sh3/lpg/material/common.d.ts.map +1 -0
  135. package/src/engine/graphics/sh3/lpg/material/common.js +73 -0
  136. package/src/engine/graphics/sh3/lpg/material/space_fragment/build_fragment_shader.d.ts +6 -0
  137. package/src/engine/graphics/sh3/lpg/material/space_fragment/build_fragment_shader.d.ts.map +1 -0
  138. package/src/engine/graphics/sh3/lpg/material/space_fragment/build_fragment_shader.js +42 -0
  139. package/src/engine/graphics/sh3/lpg/material/space_fragment/build_vertex_shader.d.ts +6 -0
  140. package/src/engine/graphics/sh3/lpg/material/space_fragment/build_vertex_shader.d.ts.map +1 -0
  141. package/src/engine/graphics/sh3/lpg/material/space_fragment/build_vertex_shader.js +49 -0
  142. package/src/engine/graphics/sh3/lpg/material/space_fragment/space_fragment_transform_shader.d.ts +9 -0
  143. package/src/engine/graphics/sh3/lpg/material/space_fragment/space_fragment_transform_shader.d.ts.map +1 -0
  144. package/src/engine/graphics/sh3/lpg/material/space_fragment/space_fragment_transform_shader.js +12 -0
  145. package/src/engine/graphics/sh3/lpg/material/space_vertex/build_fragment_shader.d.ts +6 -0
  146. package/src/engine/graphics/sh3/lpg/material/space_vertex/build_fragment_shader.d.ts.map +1 -0
  147. package/src/engine/graphics/sh3/lpg/material/space_vertex/build_fragment_shader.js +30 -0
  148. package/src/engine/graphics/sh3/lpg/material/space_vertex/build_vertex_shader.d.ts +6 -0
  149. package/src/engine/graphics/sh3/lpg/material/space_vertex/build_vertex_shader.d.ts.map +1 -0
  150. package/src/engine/graphics/sh3/lpg/material/space_vertex/build_vertex_shader.js +41 -0
  151. package/src/engine/graphics/sh3/lpg/material/space_vertex/preamble.frag.d.ts +3 -0
  152. package/src/engine/graphics/sh3/lpg/material/space_vertex/preamble.frag.d.ts.map +1 -0
  153. package/src/engine/graphics/sh3/lpg/material/space_vertex/preamble.frag.js +15 -0
  154. package/src/engine/graphics/sh3/lpg/material/space_vertex/preamble.vert.d.ts +3 -0
  155. package/src/engine/graphics/sh3/lpg/material/space_vertex/preamble.vert.d.ts.map +1 -0
  156. package/src/engine/graphics/sh3/lpg/material/space_vertex/preamble.vert.js +9 -0
  157. package/src/engine/graphics/sh3/lpg/material/space_vertex/space_vertex_transform_shader.d.ts +9 -0
  158. package/src/engine/graphics/sh3/lpg/material/space_vertex/space_vertex_transform_shader.d.ts.map +1 -0
  159. package/src/engine/graphics/sh3/lpg/material/space_vertex/space_vertex_transform_shader.js +12 -0
  160. package/src/engine/graphics/sh3/lpg/serialization/LightProbeGridSerializationAdapter.d.ts +20 -0
  161. package/src/engine/graphics/sh3/lpg/serialization/LightProbeGridSerializationAdapter.d.ts.map +1 -0
  162. package/src/engine/graphics/sh3/lpg/serialization/LightProbeGridSerializationAdapter.js +59 -0
  163. package/src/engine/graphics/sh3/path_tracer/material/MaterialConverter.d.ts.map +1 -1
  164. package/src/engine/graphics/sh3/path_tracer/material/MaterialConverter.js +8 -0
  165. package/src/engine/graphics/sh3/prototypeLightProbeGrid.d.ts +2 -0
  166. package/src/engine/graphics/sh3/prototypeLightProbeGrid.d.ts.map +1 -0
  167. package/src/engine/graphics/sh3/prototypeLightProbeGrid.js +170 -0
  168. package/src/engine/graphics/texture/atlas/AtlasLookupTexture.js +1 -1
  169. package/src/engine/graphics/texture/atlas/CachingTextureAtlas.js +1 -1
  170. package/src/engine/graphics/texture/sampler/resize/sampler2d_scale_down_lanczos.js +1 -1
  171. package/src/engine/graphics/texture/sampler/sampler2d_copy_with_margins.js +3 -3
  172. package/src/engine/graphics/util/build_max_height_pyramid.d.ts.map +1 -1
  173. package/src/engine/graphics/util/build_max_height_pyramid.js +5 -2
  174. package/src/engine/grid/transform2grid/Transform2GridPositionSystem.js +1 -1
  175. package/src/engine/input/ecs/components/InputBinding.d.ts +7 -1
  176. package/src/engine/input/ecs/components/InputBinding.d.ts.map +1 -1
  177. package/src/engine/input/ecs/components/InputBinding.js +8 -1
  178. package/src/engine/input/ecs/systems/InputControllerSystem.js +1 -1
  179. package/src/engine/intelligence/behavior/decorator/OverrideContextBehavior.d.ts +2 -1
  180. package/src/engine/intelligence/behavior/decorator/OverrideContextBehavior.d.ts.map +1 -1
  181. package/src/engine/intelligence/behavior/decorator/OverrideContextBehavior.js +6 -2
  182. package/src/engine/intelligence/behavior/selector/WeightedElement.js +1 -1
  183. package/src/engine/knowledge/database/StaticKnowledgeDatabase.d.ts.map +1 -1
  184. package/src/engine/knowledge/database/StaticKnowledgeDatabase.js +2 -4
  185. package/src/engine/logging/elastic/ElasticSearchLogger.d.ts +1 -2
  186. package/src/engine/logging/elastic/ElasticSearchLogger.d.ts.map +1 -1
  187. package/src/engine/logging/elastic/ElasticSearchLogger.js +14 -10
  188. package/src/engine/navigation/ecs/path_following/PathFollower.js +1 -1
  189. package/src/engine/navigation/grid/find_path_on_grid_astar.d.ts.map +1 -1
  190. package/src/engine/navigation/grid/find_path_on_grid_astar.js +5 -2
  191. package/src/engine/network/orchestrator/ServerAuthoritativeServer.d.ts +1 -1
  192. package/src/engine/network/orchestrator/ServerAuthoritativeServer.d.ts.map +1 -1
  193. package/src/engine/network/orchestrator/ServerAuthoritativeServer.js +17 -0
  194. package/src/engine/physics/fluid/ecs/FluidObstacleSystem.d.ts +4 -4
  195. package/src/engine/physics/fluid/ecs/FluidSystem.d.ts +3 -3
  196. package/src/engine/scene/SceneManager.d.ts.map +1 -1
  197. package/src/engine/scene/SceneManager.js +4 -2
  198. package/src/engine/simulation/Ticker.d.ts.map +1 -1
  199. package/src/engine/simulation/Ticker.js +9 -0
  200. package/src/engine/sound/ecs/emitter/SoundEmitterSystem.d.ts.map +1 -1
  201. package/src/engine/sound/ecs/emitter/SoundEmitterSystem.js +6 -1
  202. package/src/engine/sound/material/concrete/json/serializeSoundMaterialToJSON.js +1 -1
  203. package/src/generation/theme/ThemeEngine.d.ts +9 -0
  204. package/src/generation/theme/ThemeEngine.d.ts.map +1 -1
  205. package/src/generation/theme/ThemeEngine.js +37 -2
@@ -0,0 +1,315 @@
1
+ import { assert } from "../../../../../core/assert.js";
2
+ import { BinaryBuffer } from "../../../../../core/binary/BinaryBuffer.js";
3
+ import { executeBinaryClassUpgraderChain } from "../executeBinaryClassUpgraderChain.js";
4
+ import { readObjectString } from "./objectStringCodec.js";
5
+ import {
6
+ OBJECT_FORMAT_VERSION,
7
+ OBJECT_MAGIC,
8
+ TAG_ADAPTER_OBJECT,
9
+ TAG_ARRAY,
10
+ TAG_BIGINT,
11
+ TAG_FALSE,
12
+ TAG_FLOAT,
13
+ TAG_NEG_INT,
14
+ TAG_NULL,
15
+ TAG_PLAIN_OBJECT,
16
+ TAG_POS_INT,
17
+ TAG_REF,
18
+ TAG_REFLECT_OBJECT,
19
+ TAG_STRING,
20
+ TAG_TRUE,
21
+ TAG_UNDEFINED
22
+ } from "./ObjectBinaryFormat.js";
23
+
24
+ /**
25
+ * A resolved class-table entry. Migration is resolved lazily, on the first adapter-encoded object of the class,
26
+ * because whether a class was written via an adapter (and therefore whether the stored version needs migrating) is
27
+ * a property of the object tag in the body, not of the reader's registry.
28
+ *
29
+ * @typedef {Object} ResolvedClass
30
+ * @property {string} typeName
31
+ * @property {number} version version the data was written with
32
+ * @property {BinaryClassSerializationAdapter|undefined} adapter registered adapter, or undefined
33
+ * @property {Function|undefined} Klass constructor to instantiate, or undefined if unresolvable
34
+ * @property {BinaryClassUpgrader[]|null} migrators cached migrator chain (null = none needed)
35
+ * @property {boolean} migratorsResolved whether the migrator chain has been computed yet
36
+ */
37
+
38
+ /**
39
+ * Reader half of the general object-graph binary serializer. Consumes documents produced by
40
+ * {@link BinaryObjectSerializer}.
41
+ *
42
+ * Needs:
43
+ * - a {@link BinarySerializationRegistry} for hand-written adapters and version migrators;
44
+ * - a {@link ModuleRegistry} mapping `typeName -> class` so reflective (adapter-less) class instances can be
45
+ * reconstructed. It may be omitted if the data contains no reflective class instances (plain objects, arrays and
46
+ * adapter-backed classes need no module registry).
47
+ *
48
+ * @author Alex Goldring
49
+ * @copyright Company Named Limited (c) 2026
50
+ */
51
+ export class BinaryObjectDeSerializer {
52
+
53
+ /**
54
+ * @type {BinarySerializationRegistry|null}
55
+ */
56
+ #registry = null;
57
+
58
+ /**
59
+ * @type {ModuleRegistry|null}
60
+ */
61
+ #modules = null;
62
+
63
+ /**
64
+ * index -> reconstructed object/array, for resolving back-references and cycles.
65
+ * @type {Array<Object>}
66
+ */
67
+ #refs = [];
68
+
69
+ /**
70
+ * @type {ResolvedClass[]}
71
+ */
72
+ #classes = [];
73
+
74
+ /**
75
+ * @type {Array<string[]>}
76
+ */
77
+ #shapes = [];
78
+
79
+ /**
80
+ * @param {BinarySerializationRegistry} registry
81
+ * @param {ModuleRegistry} [modules] required only if the data contains reflective (adapter-less) class instances
82
+ */
83
+ constructor(registry, modules) {
84
+ this.setRegistry(registry);
85
+ this.setModuleRegistry(modules);
86
+ }
87
+
88
+ /**
89
+ * @param {BinarySerializationRegistry} registry
90
+ */
91
+ setRegistry(registry) {
92
+ assert.defined(registry, 'registry');
93
+ assert.ok(registry.isBinarySerializationRegistry, 'registry is not a BinarySerializationRegistry');
94
+
95
+ this.#registry = registry;
96
+ }
97
+
98
+ /**
99
+ * @param {ModuleRegistry} [modules]
100
+ */
101
+ setModuleRegistry(modules) {
102
+ this.#modules = modules === undefined ? null : modules;
103
+ }
104
+
105
+ /**
106
+ * Deserialize a complete document written by {@link BinaryObjectSerializer.serialize}.
107
+ *
108
+ * @template T
109
+ * @param {BinaryBuffer} buffer source, read at the current {@link BinaryBuffer.position}
110
+ * @returns {T}
111
+ */
112
+ deserialize(buffer) {
113
+ const magic = buffer.readUint16();
114
+
115
+ if (magic !== OBJECT_MAGIC) {
116
+ throw new Error(`Not an object-graph stream: expected magic 0x${OBJECT_MAGIC.toString(16).toUpperCase()}, read 0x${magic.toString(16).toUpperCase()}`);
117
+ }
118
+
119
+ const formatVersion = buffer.readUint8();
120
+
121
+ if (formatVersion !== OBJECT_FORMAT_VERSION) {
122
+ throw new Error(`Unsupported object-graph format version ${formatVersion}, this build supports ${OBJECT_FORMAT_VERSION}`);
123
+ }
124
+
125
+ this.#refs = [];
126
+ this.#classes = [];
127
+ this.#shapes = [];
128
+
129
+ // class table
130
+ const classCount = buffer.readUintVar();
131
+ for (let i = 0; i < classCount; i++) {
132
+ const typeName = readObjectString(buffer);
133
+ const version = buffer.readUintVar();
134
+ this.#classes.push(this.#resolveClass(typeName, version));
135
+ }
136
+
137
+ // shape table
138
+ const shapeCount = buffer.readUintVar();
139
+ for (let i = 0; i < shapeCount; i++) {
140
+ const fieldCount = buffer.readUintVar();
141
+ const names = new Array(fieldCount);
142
+ for (let j = 0; j < fieldCount; j++) {
143
+ names[j] = readObjectString(buffer);
144
+ }
145
+ this.#shapes.push(names);
146
+ }
147
+
148
+ return this.readValue(buffer);
149
+ }
150
+
151
+ /**
152
+ * Resolve a class name to its adapter and/or constructor. Does not resolve migrators — that is deferred to the
153
+ * first adapter-encoded object of the class (see {@link ResolvedClass}).
154
+ *
155
+ * @param {string} typeName
156
+ * @param {number} version
157
+ * @returns {ResolvedClass}
158
+ */
159
+ #resolveClass(typeName, version) {
160
+ const adapter = this.#registry.getAdapter(typeName);
161
+
162
+ let Klass;
163
+
164
+ if (adapter !== undefined) {
165
+ Klass = adapter.klass;
166
+ } else if (this.#modules !== null && this.#modules.has(typeName)) {
167
+ Klass = this.#modules.get(typeName);
168
+ } else {
169
+ Klass = undefined;
170
+ }
171
+
172
+ return { typeName, version, adapter, Klass, migrators: null, migratorsResolved: false };
173
+ }
174
+
175
+ /**
176
+ * Read a single value. Nesting adapters call this to deserialize a child of any type.
177
+ *
178
+ * @template T
179
+ * @param {BinaryBuffer} buffer
180
+ * @returns {T}
181
+ */
182
+ readValue(buffer) {
183
+ const tag = buffer.readUint8();
184
+
185
+ switch (tag) {
186
+ case TAG_NULL:
187
+ return null;
188
+ case TAG_UNDEFINED:
189
+ return undefined;
190
+ case TAG_FALSE:
191
+ return false;
192
+ case TAG_TRUE:
193
+ return true;
194
+ case TAG_POS_INT:
195
+ return buffer.readUintVar();
196
+ case TAG_NEG_INT:
197
+ return -buffer.readUintVar();
198
+ case TAG_FLOAT:
199
+ return buffer.readFloat64();
200
+ case TAG_STRING:
201
+ return readObjectString(buffer);
202
+ case TAG_BIGINT:
203
+ return BigInt(readObjectString(buffer));
204
+ case TAG_REF:
205
+ return this.#refs[buffer.readUintVar()];
206
+ case TAG_ARRAY:
207
+ return this.#readArray(buffer);
208
+ case TAG_PLAIN_OBJECT: {
209
+ const shapeIdx = buffer.readUintVar();
210
+ return this.#readReflected(buffer, {}, shapeIdx);
211
+ }
212
+ case TAG_REFLECT_OBJECT: {
213
+ const record = this.#classes[buffer.readUintVar()];
214
+ const shapeIdx = buffer.readUintVar();
215
+
216
+ if (record.Klass === undefined) {
217
+ throw new Error(`Cannot reconstruct reflective class '${record.typeName}': it is not in the module registry and has no registered adapter`);
218
+ }
219
+
220
+ return this.#readReflected(buffer, new record.Klass(), shapeIdx);
221
+ }
222
+ case TAG_ADAPTER_OBJECT:
223
+ return this.#readAdapterObject(buffer);
224
+ default:
225
+ throw new Error(`Unknown object-graph value tag ${tag}`);
226
+ }
227
+ }
228
+
229
+ /**
230
+ * @param {BinaryBuffer} buffer
231
+ * @returns {Array<*>}
232
+ */
233
+ #readArray(buffer) {
234
+ const length = buffer.readUintVar();
235
+
236
+ const array = [];
237
+ // register before filling so a cyclic element can refer back to this array
238
+ this.#refs.push(array);
239
+
240
+ for (let i = 0; i < length; i++) {
241
+ array.push(this.readValue(buffer));
242
+ }
243
+
244
+ return array;
245
+ }
246
+
247
+ /**
248
+ * @template T
249
+ * @param {BinaryBuffer} buffer
250
+ * @param {T} target freshly-constructed instance (or {}) to populate
251
+ * @param {number} shapeIdx
252
+ * @returns {T}
253
+ */
254
+ #readReflected(buffer, target, shapeIdx) {
255
+ // register before filling so a cyclic field can refer back to this object
256
+ this.#refs.push(target);
257
+
258
+ const names = this.#shapes[shapeIdx];
259
+
260
+ for (let i = 0; i < names.length; i++) {
261
+ target[names[i]] = this.readValue(buffer);
262
+ }
263
+
264
+ return target;
265
+ }
266
+
267
+ /**
268
+ * @param {BinaryBuffer} buffer
269
+ * @returns {Object}
270
+ */
271
+ #readAdapterObject(buffer) {
272
+ const record = this.#classes[buffer.readUintVar()];
273
+
274
+ if (record.adapter === undefined) {
275
+ throw new Error(`Cannot read adapter-encoded object of class '${record.typeName}': no adapter is registered`);
276
+ }
277
+
278
+ if (!record.migratorsResolved) {
279
+ if (record.version !== record.adapter.version) {
280
+ // migrate up OR down to the adapter's current version
281
+ const chain = this.#registry.getUpgradersChain(record.typeName, record.version, record.adapter.version);
282
+
283
+ if (chain === null) {
284
+ throw new Error(`No migration path for class '${record.typeName}' from version ${record.version} to ${record.adapter.version}`);
285
+ }
286
+
287
+ record.migrators = chain;
288
+ }
289
+
290
+ record.migratorsResolved = true;
291
+ }
292
+
293
+ const value = new record.Klass();
294
+ // register before the adapter reads, so a cyclic reference inside the payload resolves to this instance
295
+ this.#refs.push(value);
296
+
297
+ let payloadBuffer = buffer;
298
+
299
+ if (record.migrators !== null) {
300
+ // fresh scratch buffers keep migration re-entrant if the payload itself nests an object needing migration
301
+ payloadBuffer = executeBinaryClassUpgraderChain(record.migrators, buffer, new BinaryBuffer(), new BinaryBuffer());
302
+ }
303
+
304
+ record.adapter.initialize(this);
305
+ record.adapter.deserialize(payloadBuffer, value);
306
+
307
+ return value;
308
+ }
309
+ }
310
+
311
+ /**
312
+ * @readonly
313
+ * @type {boolean}
314
+ */
315
+ BinaryObjectDeSerializer.prototype.isBinaryObjectDeSerializer = true;
@@ -0,0 +1,48 @@
1
+ /**
2
+ * Writer half of the general object-graph binary serializer. See {@link BinaryObjectDeSerializer} for the reader
3
+ * and `DESIGN.md` for the wire format and rationale.
4
+ *
5
+ * Serializes an arbitrary value — primitives, arrays, plain objects and class instances — with **no per-class
6
+ * setup required**. Class instances are serialized by reflection over their own enumerable fields by default; if a
7
+ * class has a hand-written adapter registered in the {@link BinarySerializationRegistry}, that adapter is used
8
+ * instead (compact, custom, versioned). Shared references and cycles are preserved via first-seen object indices.
9
+ *
10
+ * Class names and reflective field-name sets are interned into two tables that are written ahead of the body, so
11
+ * repeated types cost their name once. The body is built into a scratch buffer first and copied in after the
12
+ * tables — the only extra work versus single-pass is that final byte copy.
13
+ *
14
+ * @author Alex Goldring
15
+ * @copyright Company Named Limited (c) 2026
16
+ */
17
+ export class BinaryObjectSerializer {
18
+ /**
19
+ * @param {BinarySerializationRegistry} registry
20
+ */
21
+ constructor(registry: BinarySerializationRegistry);
22
+ /**
23
+ * @param {BinarySerializationRegistry} registry
24
+ */
25
+ setRegistry(registry: BinarySerializationRegistry): void;
26
+ /**
27
+ * Serialize `value` and its whole object graph into `buffer` as a complete document (header + tables + body).
28
+ *
29
+ * @param {BinaryBuffer} buffer target, written at the current {@link BinaryBuffer.position}
30
+ * @param {*} value any value; objects may be plain, class instances (reflective or adapter-backed) or arrays
31
+ */
32
+ serialize(buffer: BinaryBuffer, value: any): void;
33
+ /**
34
+ * Write a single value. Nesting adapters call this to serialize a child of any type (including `null`).
35
+ *
36
+ * @param {BinaryBuffer} buffer
37
+ * @param {*} value
38
+ */
39
+ writeValue(buffer: BinaryBuffer, value: any): void;
40
+ /**
41
+ * @readonly
42
+ * @type {boolean}
43
+ */
44
+ readonly isBinaryObjectSerializer: boolean;
45
+ #private;
46
+ }
47
+ import { BinaryBuffer } from "../../../../../core/binary/BinaryBuffer.js";
48
+ //# sourceMappingURL=BinaryObjectSerializer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BinaryObjectSerializer.d.ts","sourceRoot":"","sources":["../../../../../../../src/engine/ecs/storage/binary/object-v2/BinaryObjectSerializer.js"],"names":[],"mappings":"AA6BA;;;;;;;;;;;;;;;GAeG;AACH;IA4CI;;OAEG;IACH,mDAEC;IAED;;OAEG;IACH,yDAKC;IAWD;;;;;OAKG;IACH,kBAHW,YAAY,oBAiCtB;IAqCD;;;;;OAKG;IACH,mBAHW,YAAY,oBA2GtB;IA4BL;;;OAGG;IACH,mCAFU,OAAO,CAEwC;;CANxD;6BAnU4B,4CAA4C"}
@@ -0,0 +1,331 @@
1
+ import { assert } from "../../../../../core/assert.js";
2
+ import { BinaryBuffer } from "../../../../../core/binary/BinaryBuffer.js";
3
+ import { writeObjectString } from "./objectStringCodec.js";
4
+ import {
5
+ OBJECT_FORMAT_VERSION,
6
+ OBJECT_MAGIC,
7
+ TAG_ADAPTER_OBJECT,
8
+ TAG_ARRAY,
9
+ TAG_BIGINT,
10
+ TAG_FALSE,
11
+ TAG_FLOAT,
12
+ TAG_NEG_INT,
13
+ TAG_NULL,
14
+ TAG_PLAIN_OBJECT,
15
+ TAG_POS_INT,
16
+ TAG_REF,
17
+ TAG_REFLECT_OBJECT,
18
+ TAG_STRING,
19
+ TAG_TRUE,
20
+ TAG_UNDEFINED
21
+ } from "./ObjectBinaryFormat.js";
22
+
23
+ /**
24
+ * Largest integer magnitude that {@link BinaryBuffer.writeUintVar} accepts; larger integers fall back to float64.
25
+ * @readonly
26
+ * @type {number}
27
+ */
28
+ const MAX_VARINT = 2147483647;
29
+
30
+ /**
31
+ * Writer half of the general object-graph binary serializer. See {@link BinaryObjectDeSerializer} for the reader
32
+ * and `DESIGN.md` for the wire format and rationale.
33
+ *
34
+ * Serializes an arbitrary value — primitives, arrays, plain objects and class instances — with **no per-class
35
+ * setup required**. Class instances are serialized by reflection over their own enumerable fields by default; if a
36
+ * class has a hand-written adapter registered in the {@link BinarySerializationRegistry}, that adapter is used
37
+ * instead (compact, custom, versioned). Shared references and cycles are preserved via first-seen object indices.
38
+ *
39
+ * Class names and reflective field-name sets are interned into two tables that are written ahead of the body, so
40
+ * repeated types cost their name once. The body is built into a scratch buffer first and copied in after the
41
+ * tables — the only extra work versus single-pass is that final byte copy.
42
+ *
43
+ * @author Alex Goldring
44
+ * @copyright Company Named Limited (c) 2026
45
+ */
46
+ export class BinaryObjectSerializer {
47
+
48
+ /**
49
+ * Adapter + migrator + class-name registry.
50
+ * @type {BinarySerializationRegistry|null}
51
+ */
52
+ #registry = null;
53
+
54
+ /**
55
+ * Scratch buffer the value graph (body) is written into before it is copied in after the tables.
56
+ * @type {BinaryBuffer}
57
+ */
58
+ #body = new BinaryBuffer();
59
+
60
+ /**
61
+ * Object/array instance -> its assigned index, for reference de-duplication and cycle detection.
62
+ * @type {Map<Object, number>}
63
+ */
64
+ #refs = new Map();
65
+
66
+ /**
67
+ * typeName -> class-table index.
68
+ * @type {Map<string, number>}
69
+ */
70
+ #classIndex = new Map();
71
+
72
+ /**
73
+ * Ordered class-table records, flushed ahead of the body.
74
+ * @type {Array<{typeName:string, version:number}>}
75
+ */
76
+ #classList = [];
77
+
78
+ /**
79
+ * shape key (JSON of the field-name list) -> shape-table index.
80
+ * @type {Map<string, number>}
81
+ */
82
+ #shapeIndex = new Map();
83
+
84
+ /**
85
+ * Ordered shape-table records (each an ordered field-name list), flushed ahead of the body.
86
+ * @type {Array<string[]>}
87
+ */
88
+ #shapeList = [];
89
+
90
+ /**
91
+ * @param {BinarySerializationRegistry} registry
92
+ */
93
+ constructor(registry) {
94
+ this.setRegistry(registry);
95
+ }
96
+
97
+ /**
98
+ * @param {BinarySerializationRegistry} registry
99
+ */
100
+ setRegistry(registry) {
101
+ assert.defined(registry, 'registry');
102
+ assert.ok(registry.isBinarySerializationRegistry, 'registry is not a BinarySerializationRegistry');
103
+
104
+ this.#registry = registry;
105
+ }
106
+
107
+ #reset() {
108
+ this.#body.position = 0;
109
+ this.#refs.clear();
110
+ this.#classIndex.clear();
111
+ this.#classList.length = 0;
112
+ this.#shapeIndex.clear();
113
+ this.#shapeList.length = 0;
114
+ }
115
+
116
+ /**
117
+ * Serialize `value` and its whole object graph into `buffer` as a complete document (header + tables + body).
118
+ *
119
+ * @param {BinaryBuffer} buffer target, written at the current {@link BinaryBuffer.position}
120
+ * @param {*} value any value; objects may be plain, class instances (reflective or adapter-backed) or arrays
121
+ */
122
+ serialize(buffer, value) {
123
+ this.#reset();
124
+
125
+ // build the body first so the interning tables are complete before we emit them
126
+ this.writeValue(this.#body, value);
127
+
128
+ // header
129
+ buffer.writeUint16(OBJECT_MAGIC);
130
+ buffer.writeUint8(OBJECT_FORMAT_VERSION);
131
+
132
+ // class table
133
+ buffer.writeUintVar(this.#classList.length);
134
+ for (let i = 0; i < this.#classList.length; i++) {
135
+ const record = this.#classList[i];
136
+ writeObjectString(buffer, record.typeName);
137
+ buffer.writeUintVar(record.version);
138
+ }
139
+
140
+ // shape table
141
+ buffer.writeUintVar(this.#shapeList.length);
142
+ for (let i = 0; i < this.#shapeList.length; i++) {
143
+ const names = this.#shapeList[i];
144
+ buffer.writeUintVar(names.length);
145
+ for (let j = 0; j < names.length; j++) {
146
+ writeObjectString(buffer, names[j]);
147
+ }
148
+ }
149
+
150
+ // body
151
+ buffer.writeBytes(this.#body.raw_bytes, 0, this.#body.position);
152
+ }
153
+
154
+ /**
155
+ * @param {string} typeName
156
+ * @param {number} version
157
+ * @returns {number} class-table index
158
+ */
159
+ #internClass(typeName, version) {
160
+ let index = this.#classIndex.get(typeName);
161
+
162
+ if (index === undefined) {
163
+ index = this.#classList.length;
164
+ this.#classList.push({ typeName, version });
165
+ this.#classIndex.set(typeName, index);
166
+ }
167
+
168
+ return index;
169
+ }
170
+
171
+ /**
172
+ * @param {string[]} names ordered field names
173
+ * @returns {number} shape-table index
174
+ */
175
+ #internShape(names) {
176
+ const key = JSON.stringify(names);
177
+
178
+ let index = this.#shapeIndex.get(key);
179
+
180
+ if (index === undefined) {
181
+ index = this.#shapeList.length;
182
+ this.#shapeList.push(names);
183
+ this.#shapeIndex.set(key, index);
184
+ }
185
+
186
+ return index;
187
+ }
188
+
189
+ /**
190
+ * Write a single value. Nesting adapters call this to serialize a child of any type (including `null`).
191
+ *
192
+ * @param {BinaryBuffer} buffer
193
+ * @param {*} value
194
+ */
195
+ writeValue(buffer, value) {
196
+ if (value === null) {
197
+ buffer.writeUint8(TAG_NULL);
198
+ return;
199
+ }
200
+
201
+ const type = typeof value;
202
+
203
+ switch (type) {
204
+ case "undefined":
205
+ buffer.writeUint8(TAG_UNDEFINED);
206
+ return;
207
+ case "boolean":
208
+ buffer.writeUint8(value ? TAG_TRUE : TAG_FALSE);
209
+ return;
210
+ case "number":
211
+ if (Number.isInteger(value) && value >= -MAX_VARINT && value <= MAX_VARINT) {
212
+ if (value >= 0) {
213
+ buffer.writeUint8(TAG_POS_INT);
214
+ buffer.writeUintVar(value);
215
+ } else {
216
+ buffer.writeUint8(TAG_NEG_INT);
217
+ buffer.writeUintVar(-value);
218
+ }
219
+ } else {
220
+ buffer.writeUint8(TAG_FLOAT);
221
+ buffer.writeFloat64(value);
222
+ }
223
+ return;
224
+ case "string":
225
+ buffer.writeUint8(TAG_STRING);
226
+ writeObjectString(buffer, value);
227
+ return;
228
+ case "bigint":
229
+ buffer.writeUint8(TAG_BIGINT);
230
+ writeObjectString(buffer, value.toString());
231
+ return;
232
+ case "function":
233
+ throw new Error("Cannot serialize a function value");
234
+ case "symbol":
235
+ throw new Error("Cannot serialize a symbol value");
236
+ default:
237
+ // object, handled below
238
+ }
239
+
240
+ // from here `value` is a non-null object (or array)
241
+
242
+ const existingIndex = this.#refs.get(value);
243
+
244
+ if (existingIndex !== undefined) {
245
+ // seen before — emit a back-reference (handles shared references and cycles)
246
+ buffer.writeUint8(TAG_REF);
247
+ buffer.writeUintVar(existingIndex);
248
+ return;
249
+ }
250
+
251
+ // assign this instance its index BEFORE writing contents, so a cyclic child can refer back to it
252
+ this.#refs.set(value, this.#refs.size);
253
+
254
+ if (Array.isArray(value)) {
255
+ buffer.writeUint8(TAG_ARRAY);
256
+ buffer.writeUintVar(value.length);
257
+ for (let i = 0; i < value.length; i++) {
258
+ this.writeValue(buffer, value[i]);
259
+ }
260
+ return;
261
+ }
262
+
263
+ const prototype = Object.getPrototypeOf(value);
264
+ const ctor = prototype === null ? undefined : prototype.constructor;
265
+
266
+ // prefer the adapter-registered name (survives minification, keyed on the constructor), then the class's
267
+ // own static typeName (the deliberate escape hatch from name mangling). The typeName must be OWN, not
268
+ // inherited: a subclass without its own typeName would otherwise be misclassified as its ancestor.
269
+ let typeName = this.#registry.getClassName(ctor);
270
+ if (typeName === undefined && ctor !== undefined && Object.prototype.hasOwnProperty.call(ctor, "typeName")) {
271
+ typeName = ctor.typeName;
272
+ }
273
+
274
+ if (typeName !== undefined && typeName !== null) {
275
+ const adapter = this.#registry.getAdapter(typeName);
276
+
277
+ if (adapter !== undefined) {
278
+ // hand-written adapter takes over the payload layout for this class
279
+ const classIdx = this.#internClass(typeName, adapter.version);
280
+ buffer.writeUint8(TAG_ADAPTER_OBJECT);
281
+ buffer.writeUintVar(classIdx);
282
+ adapter.initialize(this);
283
+ adapter.serialize(buffer, value);
284
+ return;
285
+ }
286
+
287
+ // reflective class instance — reconstructed via the module registry on read
288
+ this.#writeReflected(buffer, TAG_REFLECT_OBJECT, this.#internClass(typeName, 0), value);
289
+ return;
290
+ }
291
+
292
+ if (prototype === Object.prototype || prototype === null) {
293
+ // plain object — reconstructed as {} on read
294
+ this.#writeReflected(buffer, TAG_PLAIN_OBJECT, -1, value);
295
+ return;
296
+ }
297
+
298
+ throw new Error(`Cannot serialize instance of '${ctor && ctor.name}': it has no registered adapter and no static 'typeName'. Add a static typeName (so it survives minification) or register an adapter.`);
299
+ }
300
+
301
+ /**
302
+ * Write a reflective object body: `[classIdx] shapeIdx value*`.
303
+ *
304
+ * @param {BinaryBuffer} buffer
305
+ * @param {number} tag {@link TAG_REFLECT_OBJECT} or {@link TAG_PLAIN_OBJECT}
306
+ * @param {number} classIdx class-table index, or -1 for a plain object (not written)
307
+ * @param {Object} value
308
+ */
309
+ #writeReflected(buffer, tag, classIdx, value) {
310
+ const names = Object.keys(value);
311
+ const shapeIdx = this.#internShape(names);
312
+
313
+ buffer.writeUint8(tag);
314
+
315
+ if (classIdx >= 0) {
316
+ buffer.writeUintVar(classIdx);
317
+ }
318
+
319
+ buffer.writeUintVar(shapeIdx);
320
+
321
+ for (let i = 0; i < names.length; i++) {
322
+ this.writeValue(buffer, value[names[i]]);
323
+ }
324
+ }
325
+ }
326
+
327
+ /**
328
+ * @readonly
329
+ * @type {boolean}
330
+ */
331
+ BinaryObjectSerializer.prototype.isBinaryObjectSerializer = true;