@woosh/meep-engine 2.168.0 → 2.169.0

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 (295) hide show
  1. package/README.md +2 -2
  2. package/build/bundle-worker-image-decoder.js +1 -1
  3. package/package.json +1 -1
  4. package/src/REVIEW_2026_08_06/adv-core.md +511 -0
  5. package/src/REVIEW_2026_08_06/adv-gfx.md +480 -0
  6. package/src/REVIEW_2026_08_06/adv-view.md +446 -0
  7. package/src/REVIEW_2026_08_06/api-core.md +296 -0
  8. package/src/REVIEW_2026_08_06/api-engine.md +195 -0
  9. package/src/REVIEW_2026_08_06/bvh-phys-sound-net.md +507 -0
  10. package/src/REVIEW_2026_08_06/core-binary.md +348 -0
  11. package/src/REVIEW_2026_08_06/core-collection.md +376 -0
  12. package/src/REVIEW_2026_08_06/core-math.md +221 -0
  13. package/src/REVIEW_2026_08_06/core-process.md +266 -0
  14. package/src/REVIEW_2026_08_06/core-science.md +223 -0
  15. package/src/REVIEW_2026_08_06/engine-ai-nav.md +279 -0
  16. package/src/REVIEW_2026_08_06/engine-animation.md +167 -0
  17. package/src/REVIEW_2026_08_06/engine-asset.md +166 -0
  18. package/src/REVIEW_2026_08_06/engine-ecs.md +920 -0
  19. package/src/REVIEW_2026_08_06/engine-input.md +197 -0
  20. package/src/REVIEW_2026_08_06/engine-misc.md +248 -0
  21. package/src/REVIEW_2026_08_06/engine-terrain.md +52 -0
  22. package/src/REVIEW_2026_08_06/generation.md +176 -0
  23. package/src/REVIEW_2026_08_06/geom-2d.md +434 -0
  24. package/src/REVIEW_2026_08_06/geom-3d.md +117 -0
  25. package/src/REVIEW_2026_08_06/gfx-gi.md +143 -0
  26. package/src/REVIEW_2026_08_06/gfx-render.md +740 -0
  27. package/src/REVIEW_2026_08_06/gfx-texture.md +690 -0
  28. package/src/REVIEW_2026_08_06/prior-criticals.md +49 -0
  29. package/src/REVIEW_2026_08_06/prior-highs.md +138 -0
  30. package/src/REVIEW_2026_08_06/test-gaps.md +364 -0
  31. package/src/REVIEW_2026_08_06/view.md +667 -0
  32. package/src/REVIEW_2026_08_06.md +571 -0
  33. package/src/core/binary/BinaryBuffer.d.ts.map +1 -1
  34. package/src/core/binary/BinaryBuffer.js +12 -1
  35. package/src/core/binary/BitImage2.d.ts +5 -1
  36. package/src/core/binary/BitImage2.d.ts.map +1 -1
  37. package/src/core/binary/BitImage2.js +5 -1
  38. package/src/core/bvh8/build/NodeProxy.d.ts.map +1 -1
  39. package/src/core/bvh8/build/NodeProxy.js +314 -308
  40. package/src/core/collection/list/List.d.ts +15 -0
  41. package/src/core/collection/list/List.d.ts.map +1 -1
  42. package/src/core/collection/list/List.js +34 -0
  43. package/src/core/collection/list/SortedListProjection.d.ts.map +1 -1
  44. package/src/core/collection/list/SortedListProjection.js +4 -1
  45. package/src/core/collection/map/BiMap.d.ts +25 -2
  46. package/src/core/collection/map/BiMap.d.ts.map +1 -1
  47. package/src/core/collection/map/BiMap.js +57 -3
  48. package/src/core/debug/matchers/IsAnything.d.ts.map +1 -1
  49. package/src/core/debug/matchers/IsAnything.js +5 -1
  50. package/src/core/events/signal/Signal.d.ts.map +1 -1
  51. package/src/core/events/signal/Signal.js +3 -1
  52. package/src/core/geom/2d/polygon/TRIANGULATION_DESIGN.md +433 -0
  53. package/src/core/geom/2d/polygon/polygon2_is_counter_clockwise.d.ts +31 -0
  54. package/src/core/geom/2d/polygon/polygon2_is_counter_clockwise.d.ts.map +1 -0
  55. package/src/core/geom/2d/polygon/polygon2_is_counter_clockwise.js +84 -0
  56. package/src/core/geom/2d/polygon/polygon2_signed_area.d.ts +24 -2
  57. package/src/core/geom/2d/polygon/polygon2_signed_area.d.ts.map +1 -1
  58. package/src/core/geom/2d/polygon/polygon2_signed_area.js +52 -34
  59. package/src/core/geom/2d/polygon/polygon2_triangulate.corpus.d.ts +28 -0
  60. package/src/core/geom/2d/polygon/polygon2_triangulate.corpus.d.ts.map +1 -0
  61. package/src/core/geom/2d/polygon/polygon2_triangulate.corpus.js +86 -0
  62. package/src/core/geom/2d/polygon/polygon2_triangulate.d.ts +40 -0
  63. package/src/core/geom/2d/polygon/polygon2_triangulate.d.ts.map +1 -0
  64. package/src/core/geom/2d/polygon/polygon2_triangulate.js +1280 -0
  65. package/src/core/geom/2d/polygon/polygon2_triangulation_deviation.d.ts +28 -0
  66. package/src/core/geom/2d/polygon/polygon2_triangulation_deviation.d.ts.map +1 -0
  67. package/src/core/geom/2d/polygon/polygon2_triangulation_deviation.js +77 -0
  68. package/src/core/geom/2d/triangle/tri2_rasterize_conservative.d.ts +6 -3
  69. package/src/core/geom/2d/triangle/tri2_rasterize_conservative.d.ts.map +1 -1
  70. package/src/core/geom/2d/triangle/tri2_rasterize_conservative.js +26 -13
  71. package/src/core/geom/2d/triangle/tri2_signed_area.d.ts +17 -1
  72. package/src/core/geom/2d/triangle/tri2_signed_area.d.ts.map +1 -1
  73. package/src/core/geom/2d/triangle/tri2_signed_area.js +35 -23
  74. package/src/core/geom/2d/v2_morton_encode.d.ts +20 -0
  75. package/src/core/geom/2d/v2_morton_encode.d.ts.map +1 -0
  76. package/src/core/geom/2d/v2_morton_encode.js +23 -0
  77. package/src/core/geom/3d/atlas/segment/atlas_merge_charts.d.ts.map +1 -1
  78. package/src/core/geom/3d/atlas/segment/atlas_merge_charts.js +4 -1
  79. package/src/core/geom/3d/polygon/polygon3_compute_normal.d.ts +27 -0
  80. package/src/core/geom/3d/polygon/polygon3_compute_normal.d.ts.map +1 -0
  81. package/src/core/geom/3d/polygon/polygon3_compute_normal.js +60 -0
  82. package/src/core/geom/3d/polygon/polygon3_triangulate.d.ts +34 -0
  83. package/src/core/geom/3d/polygon/polygon3_triangulate.d.ts.map +1 -0
  84. package/src/core/geom/3d/polygon/polygon3_triangulate.js +94 -0
  85. package/src/core/geom/3d/quaternion/quat3_multiply.d.ts +8 -2
  86. package/src/core/geom/3d/quaternion/quat3_multiply.d.ts.map +1 -1
  87. package/src/core/geom/3d/quaternion/quat3_multiply.js +8 -2
  88. package/src/core/geom/3d/shape/ConvexHullShape3D.d.ts.map +1 -1
  89. package/src/core/geom/3d/shape/ConvexHullShape3D.js +32 -2
  90. package/src/core/geom/3d/topology/struct/binary/io/face/bt_face_triangulate.d.ts +23 -6
  91. package/src/core/geom/3d/topology/struct/binary/io/face/bt_face_triangulate.d.ts.map +1 -1
  92. package/src/core/geom/3d/topology/struct/binary/io/face/bt_face_triangulate.js +268 -124
  93. package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_assert_valid.d.ts +17 -0
  94. package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_assert_valid.d.ts.map +1 -0
  95. package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_assert_valid.js +44 -0
  96. package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_count_edge_faces.d.ts +20 -0
  97. package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_count_edge_faces.d.ts.map +1 -0
  98. package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_count_edge_faces.js +40 -0
  99. package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_is_closed.d.ts +19 -0
  100. package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_is_closed.d.ts.map +1 -0
  101. package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_is_closed.js +34 -0
  102. package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_is_manifold.d.ts +22 -0
  103. package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_is_manifold.d.ts.map +1 -0
  104. package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_is_manifold.js +37 -0
  105. package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_validate.d.ts +87 -0
  106. package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_validate.d.ts.map +1 -0
  107. package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_validate.js +599 -0
  108. package/src/core/geom/3d/triangle/tri3_compute_signed_volume.d.ts +32 -0
  109. package/src/core/geom/3d/triangle/tri3_compute_signed_volume.d.ts.map +1 -1
  110. package/src/core/geom/3d/triangle/tri3_compute_signed_volume.js +66 -7
  111. package/src/core/geom/3d/triangle/tri3_mesh_compute_signed_volume.d.ts +22 -1
  112. package/src/core/geom/3d/triangle/tri3_mesh_compute_signed_volume.d.ts.map +1 -1
  113. package/src/core/geom/3d/triangle/tri3_mesh_compute_signed_volume.js +83 -38
  114. package/src/core/geom/MANIFOLD_COMPARISON_2026_08_01.md +554 -0
  115. package/src/core/geom/vec3/v3_cotangent.d.ts +6 -2
  116. package/src/core/geom/vec3/v3_cotangent.d.ts.map +1 -1
  117. package/src/core/geom/vec3/v3_cotangent.js +6 -2
  118. package/src/core/geom/vec3/v3_cross.d.ts +6 -2
  119. package/src/core/geom/vec3/v3_cross.d.ts.map +1 -1
  120. package/src/core/geom/vec3/v3_cross.js +6 -2
  121. package/src/core/geom/vec3/v3_multiply.d.ts +6 -2
  122. package/src/core/geom/vec3/v3_multiply.d.ts.map +1 -1
  123. package/src/core/geom/vec3/v3_multiply.js +6 -2
  124. package/src/core/geom/vec3/v3_subtract.d.ts +6 -2
  125. package/src/core/geom/vec3/v3_subtract.d.ts.map +1 -1
  126. package/src/core/geom/vec3/v3_subtract.js +6 -2
  127. package/src/core/localization/Localization.js +1 -1
  128. package/src/core/math/random/randomSeed.d.ts +13 -0
  129. package/src/core/math/random/randomSeed.d.ts.map +1 -0
  130. package/src/core/math/random/randomSeed.js +16 -0
  131. package/src/core/math/spline/spline3_hermite_apply_transform.d.ts +50 -0
  132. package/src/core/math/spline/spline3_hermite_apply_transform.d.ts.map +1 -0
  133. package/src/core/math/spline/spline3_hermite_apply_transform.js +107 -0
  134. package/src/core/math/spline/spline3_hermite_reverse.d.ts +34 -0
  135. package/src/core/math/spline/spline3_hermite_reverse.d.ts.map +1 -0
  136. package/src/core/math/spline/spline3_hermite_reverse.js +49 -0
  137. package/src/core/math/statistics/hammersley_sequence.d.ts +17 -4
  138. package/src/core/math/statistics/hammersley_sequence.d.ts.map +1 -1
  139. package/src/core/math/statistics/hammersley_sequence.js +25 -16
  140. package/src/core/process/Future.d.ts.map +1 -1
  141. package/src/core/process/Future.js +12 -0
  142. package/src/core/process/PromiseWatcher.d.ts.map +1 -1
  143. package/src/core/process/PromiseWatcher.js +9 -2
  144. package/src/core/process/executor/ConcurrentExecutor.d.ts.map +1 -1
  145. package/src/core/process/executor/ConcurrentExecutor.js +12 -2
  146. package/src/core/process/worker/WorkerProxy.d.ts.map +1 -1
  147. package/src/core/process/worker/WorkerProxy.js +5 -2
  148. package/src/core/process/worker/extractTransferables.d.ts.map +1 -1
  149. package/src/core/process/worker/extractTransferables.js +4 -1
  150. package/src/engine/Engine.d.ts +12 -12
  151. package/src/engine/Engine.d.ts.map +1 -1
  152. package/src/engine/Engine.js +149 -10
  153. package/src/engine/EngineHarness.d.ts.map +1 -1
  154. package/src/engine/EngineHarness.js +4 -1
  155. package/src/engine/asset/loaders/ArrayBufferLoader.d.ts.map +1 -1
  156. package/src/engine/asset/loaders/ArrayBufferLoader.js +7 -0
  157. package/src/engine/ecs/speaker/lines/sets/LineSetDescription.d.ts.map +1 -1
  158. package/src/engine/ecs/speaker/lines/sets/LineSetDescription.js +3 -1
  159. package/src/engine/ecs/terrain/ecs/TerrainSystem.d.ts.map +1 -1
  160. package/src/engine/ecs/terrain/ecs/TerrainSystem.js +4 -1
  161. package/src/engine/ecs/terrain/tiles/TerrainTileManager.d.ts +29 -0
  162. package/src/engine/ecs/terrain/tiles/TerrainTileManager.d.ts.map +1 -1
  163. package/src/engine/ecs/terrain/tiles/TerrainTileManager.js +84 -23
  164. package/src/engine/graphics/CONTEXT_LOSS_RECOVERY_PLAN.md +446 -0
  165. package/src/engine/graphics/GraphicsEngine.d.ts +56 -7
  166. package/src/engine/graphics/GraphicsEngine.d.ts.map +1 -1
  167. package/src/engine/graphics/GraphicsEngine.js +196 -24
  168. package/src/engine/graphics/context/WebGLContextFailureReason.d.ts +9 -0
  169. package/src/engine/graphics/context/WebGLContextFailureReason.d.ts.map +1 -0
  170. package/src/engine/graphics/context/WebGLContextFailureReason.js +17 -0
  171. package/src/engine/graphics/context/WebGLContextMonitor.d.ts +106 -0
  172. package/src/engine/graphics/context/WebGLContextMonitor.d.ts.map +1 -0
  173. package/src/engine/graphics/context/WebGLContextMonitor.js +341 -0
  174. package/src/engine/graphics/context/WebGLContextState.d.ts +14 -0
  175. package/src/engine/graphics/context/WebGLContextState.d.ts.map +1 -0
  176. package/src/engine/graphics/context/WebGLContextState.js +24 -0
  177. package/src/engine/graphics/context/testWebGLContextLoss.d.ts +2 -0
  178. package/src/engine/graphics/context/testWebGLContextLoss.d.ts.map +1 -0
  179. package/src/engine/graphics/context/testWebGLContextLoss.js +696 -0
  180. package/src/engine/graphics/ecs/camera/serialization/CameraSerializationAdapter.d.ts.map +1 -1
  181. package/src/engine/graphics/ecs/camera/serialization/CameraSerializationAdapter.js +68 -32
  182. package/src/engine/graphics/ecs/camera/serialization/CameraSerializationUpgrader_0_1.d.ts +14 -0
  183. package/src/engine/graphics/ecs/camera/serialization/CameraSerializationUpgrader_0_1.d.ts.map +1 -0
  184. package/src/engine/graphics/ecs/camera/serialization/CameraSerializationUpgrader_0_1.js +41 -0
  185. package/src/engine/graphics/ecs/decal/v2/FPDecalSystem.js +1 -1
  186. package/src/engine/graphics/ecs/mesh-v2/ShadedGeometrySystem.d.ts.map +1 -1
  187. package/src/engine/graphics/ecs/mesh-v2/ShadedGeometrySystem.js +5 -0
  188. package/src/engine/graphics/ecs/trail2d/Trail2D.d.ts +5 -1
  189. package/src/engine/graphics/ecs/trail2d/Trail2D.d.ts.map +1 -1
  190. package/src/engine/graphics/ecs/trail2d/Trail2D.js +15 -0
  191. package/src/engine/graphics/ecs/trail2d/Trail2DSystem.d.ts +1 -1
  192. package/src/engine/graphics/ecs/trail2d/Trail2DSystem.d.ts.map +1 -1
  193. package/src/engine/graphics/ecs/trail2d/Trail2DSystem.js +2 -1
  194. package/src/engine/graphics/ecs/trail3d/Trail3D.d.ts +4 -1
  195. package/src/engine/graphics/ecs/trail3d/Trail3D.d.ts.map +1 -1
  196. package/src/engine/graphics/ecs/trail3d/Trail3D.js +488 -476
  197. package/src/engine/graphics/ecs/trail3d/Trail3DSystem.d.ts +1 -1
  198. package/src/engine/graphics/ecs/trail3d/Trail3DSystem.d.ts.map +1 -1
  199. package/src/engine/graphics/ecs/trail3d/Trail3DSystem.js +280 -253
  200. package/src/engine/graphics/geometry/MikkT/BuildNeighborsFast.d.ts.map +1 -1
  201. package/src/engine/graphics/geometry/MikkT/BuildNeighborsFast.js +3 -2
  202. package/src/engine/graphics/geometry/MikkT/GenerateSharedVerticesIndexList.d.ts.map +1 -1
  203. package/src/engine/graphics/geometry/MikkT/GenerateSharedVerticesIndexList.js +3 -1
  204. package/src/engine/graphics/geometry/computeMeshSurfaceArea.js +1 -1
  205. package/src/engine/graphics/load_and_set_cubemap_v0.d.ts +5 -0
  206. package/src/engine/graphics/load_and_set_cubemap_v0.d.ts.map +1 -1
  207. package/src/engine/graphics/load_and_set_cubemap_v0.js +26 -21
  208. package/src/engine/graphics/particles/particular/group/ParticleGroup.d.ts.map +1 -1
  209. package/src/engine/graphics/particles/particular/group/ParticleGroup.js +19 -8
  210. package/src/engine/graphics/particles/particular/group/optimizeCommandQueue.js +1 -1
  211. package/src/engine/graphics/texture/atlas/AtlasLookupTexture.d.ts.map +1 -1
  212. package/src/engine/graphics/texture/atlas/AtlasLookupTexture.js +10 -3
  213. package/src/engine/graphics/texture/atlas/TextureAtlas.d.ts.map +1 -1
  214. package/src/engine/graphics/texture/atlas/TextureAtlas.js +4 -1
  215. package/src/engine/graphics/texture/atlas/gpu/WebGLTextureAtlas.d.ts.map +1 -1
  216. package/src/engine/graphics/texture/atlas/gpu/WebGLTextureAtlas.js +11 -0
  217. package/src/engine/graphics/texture/cubemap/load_environment_map.d.ts.map +1 -1
  218. package/src/engine/graphics/texture/cubemap/load_environment_map.js +5 -2
  219. package/src/engine/graphics/texture/sampler/distance/computeSignedDistanceField_Chamfer.d.ts.map +1 -1
  220. package/src/engine/graphics/texture/sampler/distance/computeSignedDistanceField_Chamfer.js +26 -18
  221. package/src/engine/graphics/texture/sampler/filter/sampler2d_blur_gaussian.d.ts +15 -2
  222. package/src/engine/graphics/texture/sampler/filter/sampler2d_blur_gaussian.d.ts.map +1 -1
  223. package/src/engine/graphics/texture/sampler/filter/sampler2d_blur_gaussian.js +29 -3
  224. package/src/engine/graphics/texture/sampler/resize/sampler2d_scale_down_lanczos.d.ts +11 -1
  225. package/src/engine/graphics/texture/sampler/resize/sampler2d_scale_down_lanczos.d.ts.map +1 -1
  226. package/src/engine/graphics/texture/sampler/resize/sampler2d_scale_down_lanczos.js +158 -171
  227. package/src/engine/graphics/texture/sampler/sampler2d_paint.js +1 -1
  228. package/src/engine/graphics/texture/sampler/util/bitSet2Sampler2D.js +2 -2
  229. package/src/engine/input/ecs/util/TopDownCameraControllerHelper.d.ts.map +1 -1
  230. package/src/engine/input/ecs/util/TopDownCameraControllerHelper.js +10 -3
  231. package/src/engine/navigation/ecs/components/PathSerializationUpgrader_2_3.d.ts +14 -0
  232. package/src/engine/navigation/ecs/components/PathSerializationUpgrader_2_3.d.ts.map +1 -0
  233. package/src/engine/navigation/ecs/components/PathSerializationUpgrader_2_3.js +38 -0
  234. package/src/engine/network/orchestrator/ServerAuthoritativeClient.d.ts.map +1 -1
  235. package/src/engine/network/orchestrator/ServerAuthoritativeClient.js +433 -425
  236. package/src/engine/physics/constraint/solve_constraints.d.ts +4 -1
  237. package/src/engine/physics/constraint/solve_constraints.d.ts.map +1 -1
  238. package/src/engine/physics/constraint/solve_constraints.js +38 -13
  239. package/src/engine/physics/contact/ManifoldStore.d.ts +15 -3
  240. package/src/engine/physics/contact/ManifoldStore.d.ts.map +1 -1
  241. package/src/engine/physics/contact/ManifoldStore.js +15 -3
  242. package/src/engine/physics/ecs/Joint.d.ts +7 -4
  243. package/src/engine/physics/ecs/Joint.d.ts.map +1 -1
  244. package/src/engine/physics/ecs/Joint.js +7 -4
  245. package/src/engine/physics/ecs/PhysicsSystem.d.ts +14 -0
  246. package/src/engine/physics/ecs/PhysicsSystem.d.ts.map +1 -1
  247. package/src/engine/physics/ecs/PhysicsSystem.js +16 -0
  248. package/src/engine/physics/fluid/ecs/FluidObstacleSystem.d.ts +4 -4
  249. package/src/engine/physics/fluid/ecs/FluidSystem.d.ts +3 -3
  250. package/src/engine/physics/narrowphase/convex_convex_manifold.d.ts +15 -7
  251. package/src/engine/physics/narrowphase/convex_convex_manifold.d.ts.map +1 -1
  252. package/src/engine/physics/narrowphase/convex_convex_manifold.js +33 -10
  253. package/src/engine/physics/narrowphase/refine_ray_concave.d.ts +6 -2
  254. package/src/engine/physics/narrowphase/refine_ray_concave.d.ts.map +1 -1
  255. package/src/engine/physics/narrowphase/refine_ray_concave.js +6 -2
  256. package/src/engine/physics/narrowphase/refine_ray_hit.d.ts +6 -2
  257. package/src/engine/physics/narrowphase/refine_ray_hit.d.ts.map +1 -1
  258. package/src/engine/physics/narrowphase/refine_ray_hit.js +6 -2
  259. package/src/engine/physics/queries/raycast.d.ts.map +1 -1
  260. package/src/engine/physics/queries/raycast.js +11 -4
  261. package/src/engine/save/storage/IndexedDBStorage.d.ts.map +1 -1
  262. package/src/engine/save/storage/IndexedDBStorage.js +21 -3
  263. package/src/engine/simulation/Ticker.d.ts +12 -0
  264. package/src/engine/simulation/Ticker.d.ts.map +1 -1
  265. package/src/engine/simulation/Ticker.js +18 -0
  266. package/src/engine/sound/simulation/AcousticSimulator.d.ts.map +1 -1
  267. package/src/engine/sound/simulation/AcousticSimulator.js +9 -1
  268. package/src/engine/sound/simulation/core/VolumeField.d.ts +6 -2
  269. package/src/engine/sound/simulation/core/VolumeField.d.ts.map +1 -1
  270. package/src/engine/sound/simulation/core/VolumeField.js +6 -2
  271. package/src/engine/sound/simulation/probe/AcousticProbeField.d.ts +6 -2
  272. package/src/engine/sound/simulation/probe/AcousticProbeField.d.ts.map +1 -1
  273. package/src/engine/sound/simulation/probe/AcousticProbeField.js +6 -2
  274. package/src/engine/sound/simulation/probe/acoustic_probe_transfer.d.ts +6 -2
  275. package/src/engine/sound/simulation/probe/acoustic_probe_transfer.d.ts.map +1 -1
  276. package/src/engine/sound/simulation/probe/acoustic_probe_transfer.js +6 -2
  277. package/src/engine/sound/simulation/probe/bakeProbeReflectors.d.ts +3 -1
  278. package/src/engine/sound/simulation/probe/bakeProbeReflectors.d.ts.map +1 -1
  279. package/src/engine/sound/simulation/probe/bakeProbeReflectors.js +3 -1
  280. package/src/engine/ui/GUIEngine.d.ts.map +1 -1
  281. package/src/engine/ui/GUIEngine.js +8 -1
  282. package/src/generation/theme/TerrainTheme.d.ts.map +1 -1
  283. package/src/generation/theme/TerrainTheme.js +2 -1
  284. package/src/generation/theme/ThemeEngine.d.ts.map +1 -1
  285. package/src/generation/theme/ThemeEngine.js +6 -5
  286. package/src/view/ViewGroup.d.ts.map +1 -1
  287. package/src/view/ViewGroup.js +9 -7
  288. package/src/view/graphics/WebGLContextFailureView.d.ts +19 -0
  289. package/src/view/graphics/WebGLContextFailureView.d.ts.map +1 -0
  290. package/src/view/graphics/WebGLContextFailureView.js +76 -0
  291. package/src/view/minimap/Minimap.d.ts +8 -0
  292. package/src/view/minimap/Minimap.d.ts.map +1 -1
  293. package/src/view/minimap/Minimap.js +16 -3
  294. package/src/view/minimap/dom/MinimapMarkerView.d.ts.map +1 -1
  295. package/src/view/minimap/dom/MinimapMarkerView.js +3 -1
@@ -11,6 +11,7 @@ import ObservedBoolean from "../core/model/ObservedBoolean.js";
11
11
  import ConcurrentExecutor from '../core/process/executor/ConcurrentExecutor.js';
12
12
  import EmptyView from "../view/elements/EmptyView.js";
13
13
  import { ViewStack } from "../view/elements/navigation/ViewStack.js";
14
+ import { WebGLContextFailureView } from "../view/graphics/WebGLContextFailureView.js";
14
15
 
15
16
  import { AssetManager } from './asset/AssetManager.js';
16
17
  import { AssetPreloader } from "./asset/preloader/AssetPreloader.js";
@@ -44,9 +45,48 @@ const METRIC_ID_FRAME = 'frame_delay';
44
45
  const METRIC_ID_RENDER = 'render_time';
45
46
  const METRIC_ID_SIMULATION = 'simulation_time';
46
47
 
48
+ /**
49
+ * How long a context loss is tolerated before the simulation is paused as well, in seconds. Most losses
50
+ * are resolved in well under a second, and stopping the world for those would be more disruptive than
51
+ * letting it run; a longer outage is worth pausing for, as the player cannot see what is happening.
52
+ * @type {number}
53
+ */
54
+ const CONTEXT_LOSS_SIMULATION_PAUSE_DELAY = 2;
55
+
47
56
  class Engine {
48
57
  #last_frame_timestamp = 0;
49
58
 
59
+ /**
60
+ * Handle of the pending render-loop frame, `-1` when the loop is not running
61
+ * @type {number}
62
+ */
63
+ #animation_frame_handle = -1;
64
+
65
+ /**
66
+ * Handle of the pending "pause the simulation, this outage is taking a while" timer, `-1` when none
67
+ * @type {number}
68
+ */
69
+ #context_loss_pause_timer = -1;
70
+
71
+ /**
72
+ * Whether the simulation was paused because of a context loss, and therefore should be resumed once
73
+ * the context comes back
74
+ * @type {boolean}
75
+ */
76
+ #paused_by_context_loss = false;
77
+
78
+ /**
79
+ * Absent when the engine is constructed with `enableGraphics: false`.
80
+ * @type {GraphicsEngine|null}
81
+ */
82
+ graphics = null;
83
+
84
+ /**
85
+ * Absent when the engine is constructed with `enableAudio: false`.
86
+ * @type {SoundEngine|null}
87
+ */
88
+ sound = null;
89
+
50
90
  viewStack = new ViewStack();
51
91
 
52
92
  /**
@@ -257,6 +297,10 @@ class Engine {
257
297
  logger.error(`Failed to start GraphicEngine: ${e}`);
258
298
  }
259
299
 
300
+ graphicsEngine.on.contextLost.add(this.#handle_context_lost, this);
301
+ graphicsEngine.on.contextRestored.add(this.#handle_context_restored, this);
302
+ graphicsEngine.on.contextFailed.add(this.#handle_context_failed, this);
303
+
260
304
  } else {
261
305
  logger.info('enableGraphics option is not set, no graphics engine will be created');
262
306
  }
@@ -316,9 +360,84 @@ class Engine {
316
360
  this.plugins.initialize(this);
317
361
  }
318
362
 
363
+ #clear_context_loss_pause_timer() {
364
+ if (this.#context_loss_pause_timer !== -1) {
365
+ clearTimeout(this.#context_loss_pause_timer);
366
+ this.#context_loss_pause_timer = -1;
367
+ }
368
+ }
369
+
370
+ /**
371
+ * Pauses the simulation, if it is running. {@link Ticker#pause} freezes the clock, so no simulation
372
+ * time accrues while we wait and the first step after resuming is a normal-sized one.
373
+ *
374
+ * A ticker that is already paused is left alone - somebody else owns that pause and it is not ours to
375
+ * undo when the context comes back.
376
+ */
377
+ #pause_simulation_for_context_loss() {
378
+ this.#context_loss_pause_timer = -1;
379
+
380
+ if (this.#paused_by_context_loss) {
381
+ return;
382
+ }
383
+
384
+ const ticker = this.ticker;
385
+
386
+ if (!ticker.is_active || ticker.is_paused) {
387
+ return;
388
+ }
389
+
390
+ this.#paused_by_context_loss = true;
391
+
392
+ logger.warn('Graphics context outage is taking a while, pausing simulation');
393
+
394
+ ticker.pause();
395
+ }
396
+
397
+ #handle_context_lost() {
398
+ logger.warn('Graphics context lost, waiting for recovery');
399
+
400
+ this.#clear_context_loss_pause_timer();
401
+
402
+ this.#context_loss_pause_timer = setTimeout(
403
+ () => this.#pause_simulation_for_context_loss(),
404
+ CONTEXT_LOSS_SIMULATION_PAUSE_DELAY * 1000
405
+ );
406
+ }
407
+
408
+ #handle_context_restored() {
409
+ this.#clear_context_loss_pause_timer();
410
+
411
+ if (this.#paused_by_context_loss) {
412
+ this.#paused_by_context_loss = false;
413
+
414
+ if (this.ticker.is_active) {
415
+ this.ticker.resume();
416
+ }
417
+ }
418
+
419
+ logger.info('Graphics context restored, rendering resumed');
420
+ }
421
+
422
+ /**
423
+ *
424
+ * @param {WebGLContextFailureReason} reason
425
+ */
426
+ #handle_context_failed(reason) {
427
+ logger.error(`Graphics context recovery abandoned (${reason}), no further rendering is possible`);
428
+
429
+ this.#clear_context_loss_pause_timer();
430
+
431
+ // nothing can be drawn any more, so let the simulation stop rather than burn cycles invisibly.
432
+ // Application state is left intact, which keeps a save-on-failure handler viable.
433
+ this.#pause_simulation_for_context_loss();
434
+
435
+ this.viewStack.addChild(new WebGLContextFailureView());
436
+ }
437
+
319
438
  #initialize_audio() {
320
439
  const sound = this.sound;
321
- if (sound === undefined || sound === null) {
440
+ if (sound === null) {
322
441
  // no sound engine
323
442
  return;
324
443
  }
@@ -348,7 +467,7 @@ class Engine {
348
467
 
349
468
  this.viewStack.push(gameView, 'game-view');
350
469
 
351
- if (this.graphics !== undefined) {
470
+ if (this.graphics !== null) {
352
471
 
353
472
  const viewport = this.graphics.viewport;
354
473
 
@@ -440,12 +559,17 @@ class Engine {
440
559
 
441
560
  const graphics = this.graphics;
442
561
 
562
+ if (graphics === null) {
563
+ // headless
564
+ return;
565
+ }
566
+
443
567
  if (graphics.autoDraw) {
444
568
  // request redraw
445
569
  graphics.needDraw = true;
446
570
  }
447
571
 
448
- if (graphics && this.renderingEnabled && graphics.needDraw) {
572
+ if (this.renderingEnabled && graphics.needDraw) {
449
573
 
450
574
  const metrics = this.performance;
451
575
 
@@ -465,7 +589,7 @@ class Engine {
465
589
  * Startup
466
590
  * @returns {Promise}
467
591
  */
468
- start() {
592
+ async start() {
469
593
  this.assetManager.startup();
470
594
 
471
595
  this.#initialize_audio();
@@ -479,9 +603,14 @@ class Engine {
479
603
 
480
604
  this.__performacne_monitor.start();
481
605
 
606
+ const sound = this.sound;
607
+
608
+ const soundStarted = sound === null
609
+ ? Promise.resolve()
610
+ : sound.start();
611
+
482
612
  return Promise.all([
483
- this.sound.start()
484
- .then(promiseEntityManager),
613
+ soundStarted.then(promiseEntityManager),
485
614
  this.staticKnowledge.load(this.assetManager, this.executor),
486
615
  this.gui.startup(this),
487
616
  this.plugins.startup()
@@ -492,7 +621,7 @@ class Engine {
492
621
  /**
493
622
  * Starting the engine
494
623
  */
495
- requestAnimationFrame(this.#animation_frame);
624
+ this.#animation_frame_handle = requestAnimationFrame(this.#animation_frame);
496
625
 
497
626
  //start simulation
498
627
  this.ticker.start({ maxTimeout: 200 });
@@ -504,6 +633,10 @@ class Engine {
504
633
  logger.info('engine started');
505
634
  }, function (e) {
506
635
  logger.error(`Engine Failed to start: ${e}`);
636
+
637
+ // the caller awaits start() to know whether the engine came up;
638
+ // swallowing this reported success after a failed startup
639
+ throw e;
507
640
  });
508
641
 
509
642
 
@@ -516,7 +649,7 @@ class Engine {
516
649
 
517
650
  const t0 = this.#last_frame_timestamp;
518
651
  const t1 = performance.now();
519
- requestAnimationFrame(this.#animation_frame);
652
+ this.#animation_frame_handle = requestAnimationFrame(this.#animation_frame);
520
653
  this.render();
521
654
 
522
655
  const frame_delay = (t1 - t0) / 1000;
@@ -534,8 +667,14 @@ class Engine {
534
667
  async stop() {
535
668
  this.__performacne_monitor.stop();
536
669
 
537
- // stop the ticker
538
- this.ticker.pause();
670
+ // stop the ticker. pause() throws when the loop is not currently
671
+ // running, which would abort the whole teardown below
672
+ this.ticker.stop();
673
+
674
+ // and the render loop, which re-requests itself every frame and would
675
+ // otherwise keep calling render() on a torn-down engine forever
676
+ cancelAnimationFrame(this.#animation_frame_handle);
677
+ this.#animation_frame_handle = -1;
539
678
 
540
679
  // shutdown entity manager
541
680
  if (!this.__using_external_entity_manager) {
@@ -1 +1 @@
1
- {"version":3,"file":"EngineHarness.d.ts","sourceRoot":"","sources":["../../../src/engine/EngineHarness.js"],"names":[],"mappings":"AA6DA;IAmBI;;;;OAIG;IACH,8CAHmB,mBAAmB,UAAQ,MAAM,WACxC,QAAQ,MAAM,CAAC,CAM1B;IAED;;;OAGG;IACH,6BAFW,MAAM,QAYhB;IAkED;;;;;;;;;;;;;OAaG;IACH;QAZyB,MAAM,EAApB,MAAM;QACyB,GAAG;QAClB,MAAM,GAAtB,OAAO;QACQ,QAAQ,GAAvB,MAAM;QACS,KAAK,GAApB,MAAM;QACS,GAAG,GAAlB,MAAM;QACU,QAAQ,GAAxB,OAAO;QACQ,WAAW,GAA1B,MAAM;QACS,WAAW,GAA1B,MAAM;QACS,WAAW,GAA1B,MAAM;QACJ,MAAM,CA+DlB;IAED;;;;;;;;;;;;;;;;;;;;;OAqBG;IACH;QApB0B,MAAM,EAArB,MAAM;QACgC,KAAK,GAA3C;YAAC,CAAC,EAAC,MAAM,CAAC;YAAA,CAAC,EAAC,MAAM,CAAC;YAAA,CAAC,EAAC,MAAM,CAAA;SAAC;QACrB,SAAS;QACT,WAAW;QACF,KAAK,GAArB,MAAM;QACU,GAAG,GAAnB,MAAM;QACU,QAAQ,GAAxB,MAAM;QACwB,WAAW,GAAzC;YAAC,CAAC,EAAC,MAAM,CAAC;YAAC,CAAC,EAAC,MAAM,CAAA;SAAC;QACJ,iBAAiB,GAAjC,MAAM;QACW,WAAW,GAA5B,OAAO;QACU,aAAa,GAA9B,OAAO;QACU,YAAY,GAA7B,OAAO;QACU,aAAa,GAA9B,OAAO;QACS,iBAAiB,GAAjC,MAAM;QACU,iBAAiB,GAAjC,MAAM;QACW,gBAAgB,GAAjC,OAAO;QACU,cAAc,GAA/B,OAAO;QACS,mBAAmB,GAAnC,MAAM;QACW,OAAO,GAAxB,OAAO;sBA0EjB;IAGD;;;;;;;;;;;;OAYG;IACH;QAXyB,MAAM,EAApB,MAAM;QACyB,GAAG;QACnB,mBAAmB,GAAlC,MAAM;QACU,UAAU,GAA1B,OAAO;QACO,GAAG,GAAjB,KAAK;QACU,YAAY,GAA3B,MAAM;QACU,YAAY,GAA5B,OAAO;QACO,OAAO,GAArB,KAAK;QACU,gBAAgB,GAA/B,MAAM;QACS,iBAAiB,GAAhC,MAAM;sBAuDhB;IAED;;;;;;;OAOG;IACH;QAN0B,YAAY,GAA3B,MAAM;QACQ,MAAM,EAApB,MAAM;QACS,WAAW,GAA1B,MAAM;QACyB,GAAG;QAChC,QAAQ,MAAM,CAAC,CA2C3B;IAGD;;;;;;;;;;OAUG;IACH,sFATW,MAAM,GAOJ,OAAO,CAsDnB;IAjdG;;;OAGG;IACH,QAFU,MAAM,CAEiC;IAMjD;;;OAGG;IACH,YAFU,eAAQ,IAAI,CAET;IA8BjB;;;;;OAKG;IACH;iCAJmB,mBAAmB,UAAQ,MAAM;8BACzC,OAAO;QACL,QAAQ,MAAM,CAAC,CA0D3B;CAwWJ;;IAID;;;OAGG;IACH,uCAMC;;mBAhhBkB,aAAa;oCACI,0BAA0B;oBAX1C,yBAAyB;mBAK1B,iBAAiB;sBATd,wBAAwB;oBAW1B,8BAA8B"}
1
+ {"version":3,"file":"EngineHarness.d.ts","sourceRoot":"","sources":["../../../src/engine/EngineHarness.js"],"names":[],"mappings":"AA8DA;IAmBI;;;;OAIG;IACH,8CAHmB,mBAAmB,UAAQ,MAAM,WACxC,QAAQ,MAAM,CAAC,CAM1B;IAED;;;OAGG;IACH,6BAFW,MAAM,QAYhB;IAkED;;;;;;;;;;;;;OAaG;IACH;QAZyB,MAAM,EAApB,MAAM;QACyB,GAAG;QAClB,MAAM,GAAtB,OAAO;QACQ,QAAQ,GAAvB,MAAM;QACS,KAAK,GAApB,MAAM;QACS,GAAG,GAAlB,MAAM;QACU,QAAQ,GAAxB,OAAO;QACQ,WAAW,GAA1B,MAAM;QACS,WAAW,GAA1B,MAAM;QACS,WAAW,GAA1B,MAAM;QACJ,MAAM,CA+DlB;IAED;;;;;;;;;;;;;;;;;;;;;OAqBG;IACH;QApB0B,MAAM,EAArB,MAAM;QACgC,KAAK,GAA3C;YAAC,CAAC,EAAC,MAAM,CAAC;YAAA,CAAC,EAAC,MAAM,CAAC;YAAA,CAAC,EAAC,MAAM,CAAA;SAAC;QACrB,SAAS;QACT,WAAW;QACF,KAAK,GAArB,MAAM;QACU,GAAG,GAAnB,MAAM;QACU,QAAQ,GAAxB,MAAM;QACwB,WAAW,GAAzC;YAAC,CAAC,EAAC,MAAM,CAAC;YAAC,CAAC,EAAC,MAAM,CAAA;SAAC;QACJ,iBAAiB,GAAjC,MAAM;QACW,WAAW,GAA5B,OAAO;QACU,aAAa,GAA9B,OAAO;QACU,YAAY,GAA7B,OAAO;QACU,aAAa,GAA9B,OAAO;QACS,iBAAiB,GAAjC,MAAM;QACU,iBAAiB,GAAjC,MAAM;QACW,gBAAgB,GAAjC,OAAO;QACU,cAAc,GAA/B,OAAO;QACS,mBAAmB,GAAnC,MAAM;QACW,OAAO,GAAxB,OAAO;sBA0EjB;IAGD;;;;;;;;;;;;OAYG;IACH;QAXyB,MAAM,EAApB,MAAM;QACyB,GAAG;QACnB,mBAAmB,GAAlC,MAAM;QACU,UAAU,GAA1B,OAAO;QACO,GAAG,GAAjB,KAAK;QACU,YAAY,GAA3B,MAAM;QACU,YAAY,GAA5B,OAAO;QACO,OAAO,GAArB,KAAK;QACU,gBAAgB,GAA/B,MAAM;QACS,iBAAiB,GAAhC,MAAM;sBAuDhB;IAED;;;;;;;OAOG;IACH;QAN0B,YAAY,GAA3B,MAAM;QACQ,MAAM,EAApB,MAAM;QACS,WAAW,GAA1B,MAAM;QACyB,GAAG;QAChC,QAAQ,MAAM,CAAC,CA6C3B;IAGD;;;;;;;;;;OAUG;IACH,sFATW,MAAM,GAOJ,OAAO,CAsDnB;IAndG;;;OAGG;IACH,QAFU,MAAM,CAEiC;IAMjD;;;OAGG;IACH,YAFU,eAAQ,IAAI,CAET;IA8BjB;;;;;OAKG;IACH;iCAJmB,mBAAmB,UAAQ,MAAM;8BACzC,OAAO;QACL,QAAQ,MAAM,CAAC,CA0D3B;CA0WJ;;IAID;;;OAGG;IACH,uCAMC;;mBAlhBkB,aAAa;oCACI,0BAA0B;oBAX1C,yBAAyB;mBAK1B,iBAAiB;sBATd,wBAAwB;oBAW1B,8BAA8B"}
@@ -1,4 +1,5 @@
1
1
  import Stats from "three/examples/jsm/libs/stats.module.js";
2
+ import { assert } from "../core/assert.js";
2
3
  import { Color } from "../core/color/Color.js";
3
4
 
4
5
  import { noop } from "../core/function/noop.js";
@@ -327,7 +328,7 @@ export class EngineHarness {
327
328
  }
328
329
 
329
330
  if (cameraController) {
330
- EngineHarness.buildOrbitalCameraController({
331
+ await EngineHarness.buildOrbitalCameraController({
331
332
  engine,
332
333
  cameraEntity: cameraEntity
333
334
  });
@@ -430,6 +431,8 @@ export class EngineHarness {
430
431
  cameraEntity = ecd.getAnyComponent(Camera).entity;
431
432
  }
432
433
 
434
+ assert.defined(cameraEntity, "cameraEntity");
435
+
433
436
  const em = engine.entityManager;
434
437
 
435
438
  if (em.getSystem(InputControllerSystem) === null) {
@@ -1 +1 @@
1
- {"version":3,"file":"ArrayBufferLoader.d.ts","sourceRoot":"","sources":["../../../../../src/engine/asset/loaders/ArrayBufferLoader.js"],"names":[],"mappings":"AAyFA;IACI;;;OAGG;IACH,iCAFW,MAAM,GAAC,KAAK,GAAC,MAAM,EAa7B;IANG;;;;OAIG;IACH,yBAAsC;IAG1C;;;oDA0DC;CACJ;4BAlK2B,kBAAkB;qBAJzB,gCAAgC;sBAC/B,aAAa"}
1
+ {"version":3,"file":"ArrayBufferLoader.d.ts","sourceRoot":"","sources":["../../../../../src/engine/asset/loaders/ArrayBufferLoader.js"],"names":[],"mappings":"AAgGA;IACI;;;OAGG;IACH,iCAFW,MAAM,GAAC,KAAK,GAAC,MAAM,EAa7B;IANG;;;;OAIG;IACH,yBAAsC;IAG1C;;;oDA0DC;CACJ;4BAzK2B,kBAAkB;qBAJzB,gCAAgC;sBAC/B,aAAa"}
@@ -58,6 +58,13 @@ function observeResponseProgress(input, progress) {
58
58
 
59
59
  pump();
60
60
 
61
+ }).catch(error => {
62
+ // A stream failure mid-download -- or a throw out of the
63
+ // caller's progress callback -- otherwise reaches nobody:
64
+ // the stream never closes and the load never settles.
65
+ // .catch rather than a second .then argument, so that
66
+ // throws from the fulfilment path above are covered too.
67
+ controller.error(error);
61
68
  });
62
69
 
63
70
  }
@@ -1 +1 @@
1
- {"version":3,"file":"LineSetDescription.d.ts","sourceRoot":"","sources":["../../../../../../../src/engine/ecs/speaker/lines/sets/LineSetDescription.js"],"names":[],"mappings":"AAEA;IACI;;;OAGG;IACH,IAFU,MAAM,CAER;IACR;;;OAGG;IACH,OAFU,iBAAiB,CAEhB;IACX;;;OAGG;IACH,MAFU,kBAAkB,EAAE,CAEpB;IAEV;;;;OAIG;IACH,qBAHW,iBAAiB,sBACjB,MAAM,UA8ChB;CACJ"}
1
+ {"version":3,"file":"LineSetDescription.d.ts","sourceRoot":"","sources":["../../../../../../../src/engine/ecs/speaker/lines/sets/LineSetDescription.js"],"names":[],"mappings":"AAEA;IACI;;;OAGG;IACH,IAFU,MAAM,CAER;IACR;;;OAGG;IACH,OAFU,iBAAiB,CAEhB;IACX;;;OAGG;IACH,MAFU,kBAAkB,EAAE,CAEpB;IAEV;;;;OAIG;IACH,qBAHW,iBAAiB,sBACjB,MAAM,UAgDhB;CACJ"}
@@ -53,7 +53,9 @@ export class LineSetDescription {
53
53
  added_line_count++;
54
54
  }
55
55
 
56
- const sets = this.sets;
56
+ // the popped set's children, not the root's -- reading `this` here
57
+ // re-pushes the root's children on every iteration and never terminates
58
+ const sets = set.sets;
57
59
  const set_count = sets.length;
58
60
 
59
61
 
@@ -1 +1 @@
1
- {"version":3,"file":"TerrainSystem.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/ecs/terrain/ecs/TerrainSystem.js"],"names":[],"mappings":";AAgCA;IA0NI;;;;;OAKG;IACH,kEAHW,OAAO,uBAwCjB;IA5OD;;;;;OAKG;IACH,kEAeC;IA7CD,iCAAyB;IAEzB,mBAAe;IACf,mBAAe;IAEf;;;;OAIG;IACH,qBAAiB;IAEjB;;;OAGG;IACH,aAFU,cAAY,IAAI,CAEP;IAEnB;;;OAGG;IACH,KAFU,GAAG,CAEG;IAoBZ,yBAAwB;IAExB,2BAAgC;IAGpC,kDAMC;IAED,2CA0EC;IAED,4CAEC;IAED;;;;OAIG;IACH,gBAHW,OAAO,qBAqBjB;IAED;;;;OAIG;IACH,kBAHW,OAAO,qBAKjB;IAED,6BAaC;IAED;;;;;OAKG;IACH,gCAwBC;CA+CJ;uBAzRsB,iBAAiB;oBAEpB,cAAc;oBAdd,mCAAmC"}
1
+ {"version":3,"file":"TerrainSystem.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/ecs/terrain/ecs/TerrainSystem.js"],"names":[],"mappings":";AAgCA;IA6NI;;;;;OAKG;IACH,kEAHW,OAAO,uBAwCjB;IA/OD;;;;;OAKG;IACH,kEAkBC;IAhDD,iCAAyB;IAEzB,mBAAe;IACf,mBAAe;IAEf;;;;OAIG;IACH,qBAAiB;IAEjB;;;OAGG;IACH,aAFU,cAAY,IAAI,CAEP;IAEnB;;;OAGG;IACH,KAFU,GAAG,CAEG;IAuBZ,yBAAwB;IAExB,2BAAgC;IAGpC,kDAMC;IAED,2CA0EC;IAED,4CAEC;IAED;;;;OAIG;IACH,gBAHW,OAAO,qBAqBjB;IAED;;;;OAIG;IACH,kBAHW,OAAO,qBAKjB;IAED,6BAaC;IAED;;;;;OAKG;IACH,gCAwBC;CA+CJ;uBA5RsB,iBAAiB;oBAEpB,cAAc;oBAdd,mCAAmC"}
@@ -64,7 +64,10 @@ class TerrainSystem extends System {
64
64
  constructor(graphics, assetManager) {
65
65
  super();
66
66
 
67
- if (graphics === undefined) {
67
+ // Engine.graphics is null, not undefined, when the engine runs headless,
68
+ // so an undefined-only check lets null straight through to fail later
69
+ // and further away
70
+ if (graphics === undefined || graphics === null) {
68
71
  throw new Error('No GraphicsEngine supplied');
69
72
  }
70
73
 
@@ -124,6 +124,19 @@ declare class TerrainTileManager {
124
124
  * @returns {number}
125
125
  */
126
126
  computeTileIndex(x: number, y: number): number;
127
+ /**
128
+ * Number of tiles along X. A terrain whose size is not a whole multiple of
129
+ * the tile size ends in a partial tile, and that tile is real, so this
130
+ * rounds up. Every consumer must agree on this or edge tiles fall outside
131
+ * whatever grid the consumer imagined.
132
+ * @returns {number}
133
+ */
134
+ get gridWidth(): number;
135
+ /**
136
+ * Number of tiles along Y.
137
+ * @returns {number}
138
+ */
139
+ get gridHeight(): number;
127
140
  /**
128
141
  *
129
142
  * @param {number} x
@@ -174,6 +187,22 @@ declare class TerrainTileManager {
174
187
  * @param {TerrainTile} tile
175
188
  */
176
189
  stitchTile(x: number, y: number, tile: TerrainTile): void;
190
+ /**
191
+ * The eight tiles surrounding a grid cell, each undefined where the cell sits
192
+ * on the edge of the grid.
193
+ *
194
+ * Partial edge tiles are real tiles, so the neighbour grid must round up
195
+ * exactly as tile creation and getRaw do. Flooring it -- as this did until
196
+ * recently -- leaves the last row and column believing they have no
197
+ * neighbour on the outward side, so their seams are never stitched.
198
+ *
199
+ * @param {number} x Tile X coordinate
200
+ * @param {number} y Tile Y coordinate
201
+ * @returns {Object<string,TerrainTile|undefined>}
202
+ */
203
+ collectTileNeighbours(x: number, y: number): {
204
+ [x: string]: TerrainTile | undefined;
205
+ };
177
206
  /**
178
207
  *
179
208
  * @param {SurfacePoint3} result
@@ -1 +1 @@
1
- {"version":3,"file":"TerrainTileManager.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/ecs/terrain/tiles/TerrainTileManager.js"],"names":[],"mappings":";AA6BA;IA6DI;;;;;;;;OAQG;IACH,uDAPW,OAAO,EA2CjB;IAzGD;;;OAGG;IACH,OAFU,WAAW,EAAE,CAEZ;IAEX;;;MAGE;IAEF;;;OAGG;IACH,UAFU,OAAO,CAEc;IAE/B;;;OAGG;IACH,WAFU,OAAO,CAEa;IAC9B;;;OAGG;IACH,YAFU,eAAe,CAEW;IAEpC;;;OAGG;IACH,OAFU,OAAO,CAES;IAG1B;;;;OAIG;IACH,oBAAmC;IAEnC;;;OAGG;IACH,cAFU,GAAG,CAEG;IAEhB;;;OAGG;IACH,aAFU,eAAe,CAEe;IAExC;;;OAGG;IACH,yBAFU,OAAO,CAEe;IAyB5B,wBAA2C;IAE3C;;;;;;OAMG;IACH,eAFU,WAAS,IAAI,CAEW;IAGlC;;;OAGG;IACH,yBAA8B;IAQlC,iCAWC;IAED,8BAEC;IAED;;;;OAIG;IACH,2BAHW,MAAM,cACN,MAAM,QAiChB;IAED,mBAIC;IAED;;;OAGG;IACH,yBAFW,WAAW,QAuBrB;IAED;;;;OAIG;IACH,6CASC;IAED,qBAqBC;IAED;;OAEG;IACH,gBAIC;IAED;;;;;;OAMG;IACH,qBALW,MAAM,MACN,MAAM,MACN,MAAM,MACN,MAAM,QAuBhB;IAGD;;;;;;;OAOG;IACH,oCANW,MAAM,MACN,MAAM,MACN,MAAM,MACN,MAAM,GACJ,WAAW,EAAE,CAgCzB;IAED,wBAgDC;IAED;;;;;OAKG;IACH,oBAJW,MAAM,KACN,MAAM,GACJ,MAAM,CAYlB;IAED;;;;;OAKG;IACH,UAJW,MAAM,KACN,MAAM,GACJ,WAAW,GAAC,SAAS,CAiBjC;IAED;;;;;OAKG;IACH,wBAJW,MAAM,KACN,MAAM,GACJ,WAAW,CAavB;IAED;;;;;OAKG;IACH,4BAJW,MAAM,KACN,MAAM,GACL,WAAW,GAAC,SAAS,CAahC;IAED;;;;;OAKG;IACH,+BAJW,MAAM,KACN,MAAM,GACJ,QAAQ,WAAW,CAAC,CAYhC;IAED;;;;;;OAMG;IACH,UALW,MAAM,KACN,MAAM,GACJ,QAAQ,WAAW,CAAC,CA4BhC;IAED;;;OAGG;IACH,cAFW,WAAW,QAcrB;IAED,gBASC;IAED;;;;;;OAMG;IACH,cAJW,MAAM,KACN,MAAM,QACN,WAAW,QAsCrB;IAED;;;;;;;;;;OAUG;IACH,yBATW,aAAa,WACb,MAAM,WACN,MAAM,WACN,MAAM,cACN,MAAM,cACN,MAAM,cACN,MAAM,GACJ,OAAO,CAuDnB;IAED;;;;;;OAMG;IACH,kCALW,aAAa,KACb,MAAM,KACN,MAAM,GACL,OAAO,CAOlB;IAED;;;;;;OAMG;IACH,SALW,MAAM,KACN,MAAM,mCAuFhB;CACJ;wBA9uBuB,kBAAkB;mBAVvB,0CAA0C;oBAGzC,kCAAkC;4BAG1B,2CAA2C;oBAVnD,mCAAmC;gCAQvB,mDAAmD;0BAGzD,yCAAyC;8BALrC,2CAA2C"}
1
+ {"version":3,"file":"TerrainTileManager.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/ecs/terrain/tiles/TerrainTileManager.js"],"names":[],"mappings":";AA6BA;IA6DI;;;;;;;;OAQG;IACH,uDAPW,OAAO,EA2CjB;IAzGD;;;OAGG;IACH,OAFU,WAAW,EAAE,CAEZ;IAEX;;;MAGE;IAEF;;;OAGG;IACH,UAFU,OAAO,CAEc;IAE/B;;;OAGG;IACH,WAFU,OAAO,CAEa;IAC9B;;;OAGG;IACH,YAFU,eAAe,CAEW;IAEpC;;;OAGG;IACH,OAFU,OAAO,CAES;IAG1B;;;;OAIG;IACH,oBAAmC;IAEnC;;;OAGG;IACH,cAFU,GAAG,CAEG;IAEhB;;;OAGG;IACH,aAFU,eAAe,CAEe;IAExC;;;OAGG;IACH,yBAFU,OAAO,CAEe;IAyB5B,wBAA2C;IAE3C;;;;;;OAMG;IACH,eAFU,WAAS,IAAI,CAEW;IAGlC;;;OAGG;IACH,yBAA8B;IAQlC,iCAWC;IAED,8BAEC;IAED;;;;OAIG;IACH,2BAHW,MAAM,cACN,MAAM,QAiChB;IAED,mBAIC;IAED;;;OAGG;IACH,yBAFW,WAAW,QAuBrB;IAED;;;;OAIG;IACH,6CASC;IAED,qBAqBC;IAED;;OAEG;IACH,gBAIC;IAED;;;;;;OAMG;IACH,qBALW,MAAM,MACN,MAAM,MACN,MAAM,MACN,MAAM,QAuBhB;IAGD;;;;;;;OAOG;IACH,oCANW,MAAM,MACN,MAAM,MACN,MAAM,MACN,MAAM,GACJ,WAAW,EAAE,CAgCzB;IAED,wBAgDC;IAED;;;;;OAKG;IACH,oBAJW,MAAM,KACN,MAAM,GACJ,MAAM,CAYlB;IAED;;;;;;OAMG;IACH,wBAEC;IAED;;;OAGG;IACH,yBAEC;IAED;;;;;OAKG;IACH,UAJW,MAAM,KACN,MAAM,GACJ,WAAW,GAAC,SAAS,CAiBjC;IAED;;;;;OAKG;IACH,wBAJW,MAAM,KACN,MAAM,GACJ,WAAW,CAavB;IAED;;;;;OAKG;IACH,4BAJW,MAAM,KACN,MAAM,GACL,WAAW,GAAC,SAAS,CAoBhC;IAED;;;;;OAKG;IACH,+BAJW,MAAM,KACN,MAAM,GACJ,QAAQ,WAAW,CAAC,CAYhC;IAED;;;;;;OAMG;IACH,UALW,MAAM,KACN,MAAM,GACJ,QAAQ,WAAW,CAAC,CA4BhC;IAED;;;OAGG;IACH,cAFW,WAAW,QAcrB;IAED,gBASC;IAED;;;;;;OAMG;IACH,cAJW,MAAM,KACN,MAAM,QACN,WAAW,QAUrB;IAED;;;;;;;;;;;;OAYG;IACH,yBAJW,MAAM,KACN,MAAM;YACG,MAAM,GAAC,WAAW,GAAC,SAAS;MAkD/C;IAED;;;;;;;;;;OAUG;IACH,yBATW,aAAa,WACb,MAAM,WACN,MAAM,WACN,MAAM,cACN,MAAM,cACN,MAAM,cACN,MAAM,GACJ,OAAO,CAuDnB;IAED;;;;;;OAMG;IACH,kCALW,aAAa,KACb,MAAM,KACN,MAAM,GACL,OAAO,CAOlB;IAED;;;;;;OAMG;IACH,SALW,MAAM,KACN,MAAM,mCAuFhB;CACJ;wBA3yBuB,kBAAkB;mBAVvB,0CAA0C;oBAGzC,kCAAkC;4BAG1B,2CAA2C;oBAVnD,mCAAmC;gCAQvB,mDAAmD;0BAGzD,yCAAyC;8BALrC,2CAA2C"}
@@ -402,14 +402,33 @@ class TerrainTileManager {
402
402
  assert.isNonNegativeInteger(x, 'x');
403
403
  assert.isNonNegativeInteger(y, 'y');
404
404
 
405
- const w = Math.ceil(this.totalSize.x / this.tileSize.x);
405
+ const w = this.gridWidth;
406
406
 
407
407
  assert.ok(x < w, `x(=${x}) must be less than than width(=${w})`);
408
- assert.ok(y < Math.ceil(this.totalSize.y / this.tileSize.y), `y(=${y}) must be less than than height(=${Math.ceil(this.totalSize.y / this.tileSize.y)})`);
408
+ assert.ok(y < this.gridHeight, `y(=${y}) must be less than than height(=${this.gridHeight})`);
409
409
 
410
410
  return y * w + x;
411
411
  }
412
412
 
413
+ /**
414
+ * Number of tiles along X. A terrain whose size is not a whole multiple of
415
+ * the tile size ends in a partial tile, and that tile is real, so this
416
+ * rounds up. Every consumer must agree on this or edge tiles fall outside
417
+ * whatever grid the consumer imagined.
418
+ * @returns {number}
419
+ */
420
+ get gridWidth() {
421
+ return Math.ceil(this.totalSize.x / this.tileSize.x);
422
+ }
423
+
424
+ /**
425
+ * Number of tiles along Y.
426
+ * @returns {number}
427
+ */
428
+ get gridHeight() {
429
+ return Math.ceil(this.totalSize.y / this.tileSize.y);
430
+ }
431
+
413
432
  /**
414
433
  *
415
434
  * @param {number} x
@@ -419,7 +438,7 @@ class TerrainTileManager {
419
438
  getRaw(x, y) {
420
439
  if (
421
440
  x < 0
422
- || x >= Math.ceil(this.totalSize.x / this.tileSize.x)
441
+ || x >= this.gridWidth
423
442
  || y < 0
424
443
  ) {
425
444
  return undefined;
@@ -468,7 +487,14 @@ class TerrainTileManager {
468
487
 
469
488
  v3_matrix4_multiply(v3, 0, v3, 0, world_inverse);
470
489
 
471
- return this.getRawTileByPosition(v3[0], v3[1]);
490
+ // v3 was built as (x, 0, z): index 1 is the vertical axis, which is not
491
+ // a grid row. The top-down plane is X/Z.
492
+ //
493
+ // getRawTileByPosition takes *grid* coordinates, and `transform` does
494
+ // not carry the grid scale -- tiles apply it themselves (see
495
+ // assignTileScale). Divide it out here, matching Terrain's own
496
+ // mapPointWorld2Grid.
497
+ return this.getRawTileByPosition(v3[0] / this.scale.x, v3[2] / this.scale.y);
472
498
  }
473
499
 
474
500
  /**
@@ -561,40 +587,75 @@ class TerrainTileManager {
561
587
  */
562
588
  stitchTile(x, y, tile) {
563
589
 
564
- const gridSize = this.totalSize.clone();
565
- gridSize.divide(this.tileSize);
566
- gridSize.floor();
590
+ const n = this.collectTileNeighbours(x, y);
567
591
 
568
- const self = this;
569
- //normal stitching
570
- let top, bottom, left, right, topLeft, topRight, bottomLeft, bottomRight;
592
+ tile.stitchNormals(
593
+ n.top, n.bottom, n.left, n.right,
594
+ n.topLeft, n.topRight, n.bottomLeft, n.bottomRight
595
+ );
596
+ }
597
+
598
+ /**
599
+ * The eight tiles surrounding a grid cell, each undefined where the cell sits
600
+ * on the edge of the grid.
601
+ *
602
+ * Partial edge tiles are real tiles, so the neighbour grid must round up
603
+ * exactly as tile creation and getRaw do. Flooring it -- as this did until
604
+ * recently -- leaves the last row and column believing they have no
605
+ * neighbour on the outward side, so their seams are never stitched.
606
+ *
607
+ * @param {number} x Tile X coordinate
608
+ * @param {number} y Tile Y coordinate
609
+ * @returns {Object<string,TerrainTile|undefined>}
610
+ */
611
+ collectTileNeighbours(x, y) {
612
+ const gridWidth = this.gridWidth;
613
+ const gridHeight = this.gridHeight;
614
+
615
+ const result = {
616
+ top: undefined,
617
+ bottom: undefined,
618
+ left: undefined,
619
+ right: undefined,
620
+ topLeft: undefined,
621
+ topRight: undefined,
622
+ bottomLeft: undefined,
623
+ bottomRight: undefined
624
+ };
571
625
 
572
626
  if (y > 0) {
573
- top = self.getRaw(x, y - 1);
627
+ result.top = this.getRaw(x, y - 1);
628
+
574
629
  if (x > 0) {
575
- topLeft = self.getRaw(x - 1, y - 1);
630
+ result.topLeft = this.getRaw(x - 1, y - 1);
576
631
  }
577
- if (x < gridSize.x - 1) {
578
- topRight = self.getRaw(x + 1, y - 1);
632
+
633
+ if (x < gridWidth - 1) {
634
+ result.topRight = this.getRaw(x + 1, y - 1);
579
635
  }
580
636
  }
581
- if (y < gridSize.y - 1) {
582
- bottom = self.getRaw(x, y + 1);
637
+
638
+ if (y < gridHeight - 1) {
639
+ result.bottom = this.getRaw(x, y + 1);
640
+
583
641
  if (x > 0) {
584
- bottomLeft = self.getRaw(x - 1, y + 1);
642
+ result.bottomLeft = this.getRaw(x - 1, y + 1);
585
643
  }
586
- if (x < gridSize.x - 1) {
587
- bottomRight = self.getRaw(x + 1, y + 1);
644
+
645
+ if (x < gridWidth - 1) {
646
+ result.bottomRight = this.getRaw(x + 1, y + 1);
588
647
  }
589
648
  }
649
+
590
650
  if (x > 0) {
591
- left = self.getRaw(x - 1, y);
651
+ result.left = this.getRaw(x - 1, y);
592
652
  }
593
- if (x < gridSize.x - 1) {
594
- right = self.getRaw(x + 1, y);
653
+
654
+ if (x < gridWidth - 1) {
655
+ result.right = this.getRaw(x + 1, y);
595
656
  }
596
657
 
597
- tile.stitchNormals(top, bottom, left, right, topLeft, topRight, bottomLeft, bottomRight);
658
+ return result;
598
659
  }
599
660
 
600
661
  /**