@thunderclap-engine/engine 0.0.0-stage → 1.1.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.
- package/CHANGELOG.md +390 -0
- package/LICENSE +21 -0
- package/README.md +333 -2
- package/dist/analytics/analytics.d.ts +80 -0
- package/dist/analytics/analytics.js +129 -0
- package/dist/analytics/index.d.ts +1 -0
- package/dist/analytics/index.js +1 -0
- package/dist/anim/aim.d.ts +43 -0
- package/dist/anim/aim.js +157 -0
- package/dist/anim/clip.d.ts +98 -0
- package/dist/anim/clip.js +282 -0
- package/dist/anim/compress.d.ts +65 -0
- package/dist/anim/compress.js +339 -0
- package/dist/anim/foot-ik.d.ts +74 -0
- package/dist/anim/foot-ik.js +241 -0
- package/dist/anim/graph.d.ts +153 -0
- package/dist/anim/graph.js +532 -0
- package/dist/anim/ik.d.ts +105 -0
- package/dist/anim/ik.js +435 -0
- package/dist/anim/index.d.ts +36 -0
- package/dist/anim/index.js +21 -0
- package/dist/anim/match.d.ts +66 -0
- package/dist/anim/match.js +153 -0
- package/dist/anim/mixer.d.ts +113 -0
- package/dist/anim/mixer.js +314 -0
- package/dist/anim/morph.d.ts +41 -0
- package/dist/anim/morph.js +94 -0
- package/dist/anim/pose.d.ts +74 -0
- package/dist/anim/pose.js +254 -0
- package/dist/anim/quat.d.ts +44 -0
- package/dist/anim/quat.js +187 -0
- package/dist/anim/retarget.d.ts +97 -0
- package/dist/anim/retarget.js +366 -0
- package/dist/anim/root-motion.d.ts +44 -0
- package/dist/anim/root-motion.js +224 -0
- package/dist/anim/skin-pose.d.ts +39 -0
- package/dist/anim/skin-pose.js +53 -0
- package/dist/anim/socket.d.ts +47 -0
- package/dist/anim/socket.js +84 -0
- package/dist/anim/spring-chain.d.ts +73 -0
- package/dist/anim/spring-chain.js +294 -0
- package/dist/assets/atlas.d.ts +90 -0
- package/dist/assets/atlas.js +212 -0
- package/dist/assets/baked.d.ts +33 -0
- package/dist/assets/baked.js +38 -0
- package/dist/assets/bundle.d.ts +88 -0
- package/dist/assets/bundle.js +464 -0
- package/dist/assets/cache.d.ts +56 -0
- package/dist/assets/cache.js +123 -0
- package/dist/assets/gltf-load.d.ts +252 -0
- package/dist/assets/gltf-load.js +661 -0
- package/dist/assets/gltf-skin.d.ts +36 -0
- package/dist/assets/gltf-skin.js +109 -0
- package/dist/assets/gltf.d.ts +706 -0
- package/dist/assets/gltf.js +1376 -0
- package/dist/assets/index.d.ts +20 -0
- package/dist/assets/index.js +10 -0
- package/dist/assets/ktx2.d.ts +71 -0
- package/dist/assets/ktx2.js +213 -0
- package/dist/assets/manifest.d.ts +79 -0
- package/dist/assets/manifest.js +7 -0
- package/dist/assets/meshopt.d.ts +23 -0
- package/dist/assets/meshopt.js +403 -0
- package/dist/audio/audio.d.ts +733 -0
- package/dist/audio/audio.js +2013 -0
- package/dist/audio/dsp.d.ts +61 -0
- package/dist/audio/dsp.js +159 -0
- package/dist/audio/duck.d.ts +44 -0
- package/dist/audio/duck.js +101 -0
- package/dist/audio/envelope.d.ts +53 -0
- package/dist/audio/envelope.js +106 -0
- package/dist/audio/index.d.ts +13 -0
- package/dist/audio/index.js +14 -0
- package/dist/audio/music.d.ts +113 -0
- package/dist/audio/music.js +548 -0
- package/dist/audio/occlusion.d.ts +55 -0
- package/dist/audio/occlusion.js +61 -0
- package/dist/audio/persist.d.ts +23 -0
- package/dist/audio/persist.js +27 -0
- package/dist/audio/recipes.d.ts +55 -0
- package/dist/audio/recipes.js +227 -0
- package/dist/audio/send.d.ts +41 -0
- package/dist/audio/send.js +118 -0
- package/dist/audio/sprites.d.ts +59 -0
- package/dist/audio/sprites.js +43 -0
- package/dist/audio/synth.d.ts +103 -0
- package/dist/audio/synth.js +197 -0
- package/dist/audio/variations.d.ts +25 -0
- package/dist/audio/variations.js +55 -0
- package/dist/audio/zones.d.ts +100 -0
- package/dist/audio/zones.js +167 -0
- package/dist/core/detached-surface.d.ts +44 -0
- package/dist/core/detached-surface.js +104 -0
- package/dist/core/events.d.ts +24 -0
- package/dist/core/events.js +43 -0
- package/dist/core/game.d.ts +409 -0
- package/dist/core/game.js +530 -0
- package/dist/core/hash.d.ts +24 -0
- package/dist/core/hash.js +49 -0
- package/dist/core/index.d.ts +17 -0
- package/dist/core/index.js +9 -0
- package/dist/core/loop.d.ts +113 -0
- package/dist/core/loop.js +185 -0
- package/dist/core/math.d.ts +58 -0
- package/dist/core/math.js +210 -0
- package/dist/core/noise.d.ts +40 -0
- package/dist/core/noise.js +247 -0
- package/dist/core/pool.d.ts +42 -0
- package/dist/core/pool.js +85 -0
- package/dist/core/random.d.ts +61 -0
- package/dist/core/random.js +199 -0
- package/dist/core/scene.d.ts +79 -0
- package/dist/core/scene.js +195 -0
- package/dist/core/timer.d.ts +66 -0
- package/dist/core/timer.js +286 -0
- package/dist/fx/billboard-wgsl.d.ts +29 -0
- package/dist/fx/billboard-wgsl.js +158 -0
- package/dist/fx/billboard.d.ts +249 -0
- package/dist/fx/billboard.js +702 -0
- package/dist/fx/debug-draw.d.ts +127 -0
- package/dist/fx/debug-draw.js +523 -0
- package/dist/fx/debug-wgsl.d.ts +7 -0
- package/dist/fx/debug-wgsl.js +32 -0
- package/dist/fx/decals-wgsl.d.ts +15 -0
- package/dist/fx/decals-wgsl.js +173 -0
- package/dist/fx/decals.d.ts +216 -0
- package/dist/fx/decals.js +607 -0
- package/dist/fx/effect.d.ts +129 -0
- package/dist/fx/effect.js +349 -0
- package/dist/fx/effects/hit-spark.json +48 -0
- package/dist/fx/effects/index.d.ts +8 -0
- package/dist/fx/effects/index.js +9 -0
- package/dist/fx/effects/magic-aura.json +47 -0
- package/dist/fx/effects/smoke-puff.json +34 -0
- package/dist/fx/emit-surface.d.ts +40 -0
- package/dist/fx/emit-surface.js +124 -0
- package/dist/fx/flicker.d.ts +30 -0
- package/dist/fx/flicker.js +42 -0
- package/dist/fx/index.d.ts +31 -0
- package/dist/fx/index.js +20 -0
- package/dist/fx/particles-wgsl.d.ts +57 -0
- package/dist/fx/particles-wgsl.js +828 -0
- package/dist/fx/particles.d.ts +566 -0
- package/dist/fx/particles.js +1533 -0
- package/dist/fx/random.d.ts +15 -0
- package/dist/fx/random.js +20 -0
- package/dist/fx/sky-wgsl.d.ts +23 -0
- package/dist/fx/sky-wgsl.js +127 -0
- package/dist/fx/sky.d.ts +96 -0
- package/dist/fx/sky.js +175 -0
- package/dist/fx/text-atlas.d.ts +143 -0
- package/dist/fx/text-atlas.js +327 -0
- package/dist/fx/trail-wgsl.d.ts +11 -0
- package/dist/fx/trail-wgsl.js +42 -0
- package/dist/fx/trail.d.ts +194 -0
- package/dist/fx/trail.js +555 -0
- package/dist/fx/water-wgsl.d.ts +34 -0
- package/dist/fx/water-wgsl.js +197 -0
- package/dist/fx/water.d.ts +176 -0
- package/dist/fx/water.js +371 -0
- package/dist/geom/collide/bvh.d.ts +151 -0
- package/dist/geom/collide/bvh.js +493 -0
- package/dist/geom/collide/debug.d.ts +14 -0
- package/dist/geom/collide/debug.js +74 -0
- package/dist/geom/collide/grid.d.ts +26 -0
- package/dist/geom/collide/grid.js +91 -0
- package/dist/geom/collide/index.d.ts +8 -0
- package/dist/geom/collide/index.js +8 -0
- package/dist/geom/collide/queries.d.ts +70 -0
- package/dist/geom/collide/queries.js +583 -0
- package/dist/geom/collide/serialize.d.ts +14 -0
- package/dist/geom/collide/serialize.js +145 -0
- package/dist/geom/collide/shapes.d.ts +161 -0
- package/dist/geom/collide/shapes.js +686 -0
- package/dist/geom/collide/slide.d.ts +66 -0
- package/dist/geom/collide/slide.js +375 -0
- package/dist/geom/collide/tile-slide.d.ts +88 -0
- package/dist/geom/collide/tile-slide.js +255 -0
- package/dist/geom/geometry.d.ts +95 -0
- package/dist/geom/geometry.js +322 -0
- package/dist/geom/heightfield.d.ts +72 -0
- package/dist/geom/heightfield.js +295 -0
- package/dist/geom/hull.d.ts +27 -0
- package/dist/geom/hull.js +279 -0
- package/dist/geom/index.d.ts +35 -0
- package/dist/geom/index.js +23 -0
- package/dist/geom/iso.d.ts +74 -0
- package/dist/geom/iso.js +89 -0
- package/dist/geom/lod.d.ts +29 -0
- package/dist/geom/lod.js +27 -0
- package/dist/geom/ops.d.ts +47 -0
- package/dist/geom/ops.js +285 -0
- package/dist/geom/primitives.d.ts +97 -0
- package/dist/geom/primitives.js +359 -0
- package/dist/geom/shapes.d.ts +43 -0
- package/dist/geom/shapes.js +88 -0
- package/dist/geom/simplify.d.ts +38 -0
- package/dist/geom/simplify.js +519 -0
- package/dist/geom/split.d.ts +37 -0
- package/dist/geom/split.js +413 -0
- package/dist/geom/sweep.d.ts +83 -0
- package/dist/geom/sweep.js +534 -0
- package/dist/geom/tangents.d.ts +16 -0
- package/dist/geom/tangents.js +124 -0
- package/dist/geom/triangulate.d.ts +19 -0
- package/dist/geom/triangulate.js +147 -0
- package/dist/host/default.d.ts +10 -0
- package/dist/host/default.js +10 -0
- package/dist/host/index.d.ts +4 -0
- package/dist/host/index.js +3 -0
- package/dist/host/types.d.ts +144 -0
- package/dist/host/types.js +1 -0
- package/dist/host/web-links.d.ts +38 -0
- package/dist/host/web-links.js +110 -0
- package/dist/host/web.d.ts +30 -0
- package/dist/host/web.js +216 -0
- package/dist/host/xr.d.ts +24 -0
- package/dist/host/xr.js +59 -0
- package/dist/i18n/i18n.d.ts +59 -0
- package/dist/i18n/i18n.js +241 -0
- package/dist/i18n/index.d.ts +3 -0
- package/dist/i18n/index.js +3 -0
- package/dist/i18n/message.d.ts +72 -0
- package/dist/i18n/message.js +369 -0
- package/dist/i18n/negotiate.d.ts +17 -0
- package/dist/i18n/negotiate.js +58 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.js +1 -0
- package/dist/input/bindings.d.ts +31 -0
- package/dist/input/bindings.js +141 -0
- package/dist/input/clock.d.ts +44 -0
- package/dist/input/clock.js +49 -0
- package/dist/input/follow.d.ts +133 -0
- package/dist/input/follow.js +218 -0
- package/dist/input/gestures.d.ts +281 -0
- package/dist/input/gestures.js +662 -0
- package/dist/input/glyphs.d.ts +35 -0
- package/dist/input/glyphs.js +216 -0
- package/dist/input/gyro.d.ts +85 -0
- package/dist/input/gyro.js +140 -0
- package/dist/input/index.d.ts +19 -0
- package/dist/input/index.js +16 -0
- package/dist/input/input.d.ts +543 -0
- package/dist/input/input.js +1492 -0
- package/dist/input/look.d.ts +327 -0
- package/dist/input/look.js +681 -0
- package/dist/input/magnify.d.ts +177 -0
- package/dist/input/magnify.js +131 -0
- package/dist/input/pointer-dispatch.d.ts +138 -0
- package/dist/input/pointer-dispatch.js +180 -0
- package/dist/input/pointer-router.d.ts +204 -0
- package/dist/input/pointer-router.js +533 -0
- package/dist/input/pointer-sources.d.ts +164 -0
- package/dist/input/pointer-sources.js +306 -0
- package/dist/input/rays.d.ts +138 -0
- package/dist/input/rays.js +615 -0
- package/dist/input/record.d.ts +209 -0
- package/dist/input/record.js +601 -0
- package/dist/input/touch-zones.d.ts +147 -0
- package/dist/input/touch-zones.js +300 -0
- package/dist/input/types.d.ts +158 -0
- package/dist/input/types.js +1 -0
- package/dist/input/xr-source.d.ts +53 -0
- package/dist/input/xr-source.js +164 -0
- package/dist/nav/astar.d.ts +45 -0
- package/dist/nav/astar.js +182 -0
- package/dist/nav/corridor.d.ts +40 -0
- package/dist/nav/corridor.js +95 -0
- package/dist/nav/crowd.d.ts +94 -0
- package/dist/nav/crowd.js +624 -0
- package/dist/nav/flow.d.ts +61 -0
- package/dist/nav/flow.js +193 -0
- package/dist/nav/grid.d.ts +108 -0
- package/dist/nav/grid.js +210 -0
- package/dist/nav/heap.d.ts +22 -0
- package/dist/nav/heap.js +92 -0
- package/dist/nav/index.d.ts +37 -0
- package/dist/nav/index.js +19 -0
- package/dist/nav/mesh/areas.d.ts +44 -0
- package/dist/nav/mesh/areas.js +98 -0
- package/dist/nav/mesh/bake-options.d.ts +33 -0
- package/dist/nav/mesh/bake-options.js +76 -0
- package/dist/nav/mesh/contour.d.ts +22 -0
- package/dist/nav/mesh/contour.js +323 -0
- package/dist/nav/mesh/flow3.d.ts +35 -0
- package/dist/nav/mesh/flow3.js +229 -0
- package/dist/nav/mesh/links.d.ts +38 -0
- package/dist/nav/mesh/links.js +72 -0
- package/dist/nav/mesh/mesh-path.d.ts +152 -0
- package/dist/nav/mesh/mesh-path.js +643 -0
- package/dist/nav/mesh/mesh-reach.d.ts +78 -0
- package/dist/nav/mesh/mesh-reach.js +450 -0
- package/dist/nav/mesh/navmesh.d.ts +117 -0
- package/dist/nav/mesh/navmesh.js +647 -0
- package/dist/nav/mesh/polymesh.d.ts +24 -0
- package/dist/nav/mesh/polymesh.js +384 -0
- package/dist/nav/mesh/regions.d.ts +12 -0
- package/dist/nav/mesh/regions.js +367 -0
- package/dist/nav/mesh/serialize.d.ts +13 -0
- package/dist/nav/mesh/serialize.js +197 -0
- package/dist/nav/mesh/voxelize.d.ts +111 -0
- package/dist/nav/mesh/voxelize.js +552 -0
- package/dist/nav/obstacles.d.ts +75 -0
- package/dist/nav/obstacles.js +294 -0
- package/dist/nav/path.d.ts +59 -0
- package/dist/nav/path.js +177 -0
- package/dist/nav/query-queue.d.ts +46 -0
- package/dist/nav/query-queue.js +308 -0
- package/dist/nav/reach.d.ts +53 -0
- package/dist/nav/reach.js +148 -0
- package/dist/nav/steer.d.ts +36 -0
- package/dist/nav/steer.js +78 -0
- package/dist/platform/boot.d.ts +28 -0
- package/dist/platform/boot.js +43 -0
- package/dist/platform/device-mode.d.ts +40 -0
- package/dist/platform/device-mode.js +104 -0
- package/dist/platform/device.d.ts +31 -0
- package/dist/platform/device.js +91 -0
- package/dist/platform/environment.d.ts +42 -0
- package/dist/platform/environment.js +82 -0
- package/dist/platform/gpu.d.ts +40 -0
- package/dist/platform/gpu.js +57 -0
- package/dist/platform/index.d.ts +18 -0
- package/dist/platform/index.js +10 -0
- package/dist/platform/letterbox.d.ts +43 -0
- package/dist/platform/letterbox.js +57 -0
- package/dist/platform/links.d.ts +20 -0
- package/dist/platform/links.js +43 -0
- package/dist/platform/screens.d.ts +36 -0
- package/dist/platform/screens.js +138 -0
- package/dist/platform/surface.d.ts +72 -0
- package/dist/platform/surface.js +157 -0
- package/dist/platform/xr-fake.d.ts +168 -0
- package/dist/platform/xr-fake.js +434 -0
- package/dist/platform/xr-surface.d.ts +120 -0
- package/dist/platform/xr-surface.js +214 -0
- package/dist/platform/xr-types.d.ts +262 -0
- package/dist/post/ao.d.ts +12 -0
- package/dist/post/ao.js +136 -0
- package/dist/post/blend.d.ts +27 -0
- package/dist/post/blend.js +129 -0
- package/dist/post/depth-pass.d.ts +43 -0
- package/dist/post/depth-pass.js +118 -0
- package/dist/post/dof.d.ts +1 -0
- package/dist/post/dof.js +66 -0
- package/dist/post/exposure.d.ts +80 -0
- package/dist/post/exposure.js +322 -0
- package/dist/post/index.d.ts +12 -0
- package/dist/post/index.js +11 -0
- package/dist/post/lens-dirt.d.ts +13 -0
- package/dist/post/lens-dirt.js +91 -0
- package/dist/post/lut.d.ts +19 -0
- package/dist/post/lut.js +50 -0
- package/dist/post/motion-blur.d.ts +9 -0
- package/dist/post/motion-blur.js +78 -0
- package/dist/post/post-stack.d.ts +302 -0
- package/dist/post/post-stack.js +1137 -0
- package/dist/post/settings.d.ts +485 -0
- package/dist/post/settings.js +416 -0
- package/dist/post/shaders.d.ts +25 -0
- package/dist/post/shaders.js +410 -0
- package/dist/post/ssr.d.ts +16 -0
- package/dist/post/ssr.js +155 -0
- package/dist/post/taa.d.ts +74 -0
- package/dist/post/taa.js +235 -0
- package/dist/post/white-balance.d.ts +25 -0
- package/dist/post/white-balance.js +98 -0
- package/dist/render/bindings.d.ts +98 -0
- package/dist/render/bindings.js +281 -0
- package/dist/render/blend.d.ts +13 -0
- package/dist/render/blend.js +26 -0
- package/dist/render/camera-2d.d.ts +72 -0
- package/dist/render/camera-2d.js +92 -0
- package/dist/render/camera.d.ts +302 -0
- package/dist/render/camera.js +671 -0
- package/dist/render/color.d.ts +16 -0
- package/dist/render/color.js +41 -0
- package/dist/render/compressed.d.ts +104 -0
- package/dist/render/compressed.js +248 -0
- package/dist/render/diagnostics.d.ts +15 -0
- package/dist/render/diagnostics.js +43 -0
- package/dist/render/dynamic-resolution.d.ts +70 -0
- package/dist/render/dynamic-resolution.js +126 -0
- package/dist/render/fake-gpu.d.ts +204 -0
- package/dist/render/fake-gpu.js +426 -0
- package/dist/render/flipbook.d.ts +56 -0
- package/dist/render/flipbook.js +87 -0
- package/dist/render/frame.d.ts +278 -0
- package/dist/render/frame.js +174 -0
- package/dist/render/fullscreen.d.ts +54 -0
- package/dist/render/fullscreen.js +91 -0
- package/dist/render/gpu-timer.d.ts +73 -0
- package/dist/render/gpu-timer.js +186 -0
- package/dist/render/index.d.ts +53 -0
- package/dist/render/index.js +29 -0
- package/dist/render/instance-list.d.ts +185 -0
- package/dist/render/instance-list.js +547 -0
- package/dist/render/lights.d.ts +181 -0
- package/dist/render/lights.js +233 -0
- package/dist/render/lod.d.ts +54 -0
- package/dist/render/lod.js +52 -0
- package/dist/render/material.d.ts +165 -0
- package/dist/render/material.js +292 -0
- package/dist/render/mesh.d.ts +284 -0
- package/dist/render/mesh.js +472 -0
- package/dist/render/mipmap.d.ts +16 -0
- package/dist/render/mipmap.js +121 -0
- package/dist/render/parallax.d.ts +50 -0
- package/dist/render/parallax.js +47 -0
- package/dist/render/pbr-wgsl.d.ts +31 -0
- package/dist/render/pbr-wgsl.js +119 -0
- package/dist/render/ping-pong.d.ts +42 -0
- package/dist/render/ping-pong.js +74 -0
- package/dist/render/renderer.d.ts +741 -0
- package/dist/render/renderer.js +2486 -0
- package/dist/render/scene-pipelines.d.ts +44 -0
- package/dist/render/scene-pipelines.js +92 -0
- package/dist/render/scene-target.d.ts +170 -0
- package/dist/render/scene-target.js +450 -0
- package/dist/render/shadow.d.ts +74 -0
- package/dist/render/shadow.js +208 -0
- package/dist/render/skin.d.ts +112 -0
- package/dist/render/skin.js +240 -0
- package/dist/render/snapshot.d.ts +36 -0
- package/dist/render/snapshot.js +34 -0
- package/dist/render/standard.d.ts +162 -0
- package/dist/render/standard.js +263 -0
- package/dist/render/texture.d.ts +142 -0
- package/dist/render/texture.js +228 -0
- package/dist/render/tile-layer.d.ts +110 -0
- package/dist/render/tile-layer.js +304 -0
- package/dist/render/transform.d.ts +115 -0
- package/dist/render/transform.js +318 -0
- package/dist/render/wgsl.d.ts +131 -0
- package/dist/render/wgsl.js +528 -0
- package/dist/save/codec.d.ts +49 -0
- package/dist/save/codec.js +169 -0
- package/dist/save/index.d.ts +8 -0
- package/dist/save/index.js +8 -0
- package/dist/save/journal.d.ts +24 -0
- package/dist/save/journal.js +102 -0
- package/dist/save/migrate.d.ts +15 -0
- package/dist/save/migrate.js +37 -0
- package/dist/save/schema.d.ts +72 -0
- package/dist/save/schema.js +154 -0
- package/dist/save/settings.d.ts +28 -0
- package/dist/save/settings.js +59 -0
- package/dist/save/slots.d.ts +56 -0
- package/dist/save/slots.js +200 -0
- package/dist/save/storage.d.ts +35 -0
- package/dist/save/storage.js +62 -0
- package/dist/save/store.d.ts +114 -0
- package/dist/save/store.js +269 -0
- package/dist/testing/fake-host.d.ts +103 -0
- package/dist/testing/fake-host.js +163 -0
- package/dist/testing/fixed-clock.d.ts +25 -0
- package/dist/testing/fixed-clock.js +30 -0
- package/dist/testing/index.d.ts +4 -0
- package/dist/testing/index.js +5 -0
- package/dist/testing/test-game.d.ts +76 -0
- package/dist/testing/test-game.js +92 -0
- package/dist/tween/ease.d.ts +77 -0
- package/dist/tween/ease.js +192 -0
- package/dist/tween/index.d.ts +8 -0
- package/dist/tween/index.js +7 -0
- package/dist/tween/timeline.d.ts +78 -0
- package/dist/tween/timeline.js +269 -0
- package/dist/tween/tween.d.ts +168 -0
- package/dist/tween/tween.js +320 -0
- package/dist/ui/anchor.d.ts +206 -0
- package/dist/ui/anchor.js +307 -0
- package/dist/ui/caption.d.ts +122 -0
- package/dist/ui/caption.js +286 -0
- package/dist/ui/cursor.d.ts +105 -0
- package/dist/ui/cursor.js +261 -0
- package/dist/ui/dom.d.ts +30 -0
- package/dist/ui/dom.js +92 -0
- package/dist/ui/floats.d.ts +86 -0
- package/dist/ui/floats.js +260 -0
- package/dist/ui/hud.d.ts +198 -0
- package/dist/ui/hud.js +431 -0
- package/dist/ui/index.d.ts +37 -0
- package/dist/ui/index.js +34 -0
- package/dist/ui/inventory-card.d.ts +52 -0
- package/dist/ui/inventory-card.js +173 -0
- package/dist/ui/inventory-context.d.ts +29 -0
- package/dist/ui/inventory-context.js +125 -0
- package/dist/ui/inventory-drag.d.ts +63 -0
- package/dist/ui/inventory-drag.js +394 -0
- package/dist/ui/inventory-grid.d.ts +66 -0
- package/dist/ui/inventory-grid.js +625 -0
- package/dist/ui/inventory-radial.d.ts +39 -0
- package/dist/ui/inventory-radial.js +168 -0
- package/dist/ui/inventory.d.ts +128 -0
- package/dist/ui/inventory.js +154 -0
- package/dist/ui/layout.d.ts +356 -0
- package/dist/ui/layout.js +856 -0
- package/dist/ui/link.d.ts +64 -0
- package/dist/ui/link.js +155 -0
- package/dist/ui/loading.d.ts +40 -0
- package/dist/ui/loading.js +157 -0
- package/dist/ui/loupe.d.ts +74 -0
- package/dist/ui/loupe.js +164 -0
- package/dist/ui/menu-nav.d.ts +33 -0
- package/dist/ui/menu-nav.js +28 -0
- package/dist/ui/minimap-canvas.d.ts +145 -0
- package/dist/ui/minimap-canvas.js +460 -0
- package/dist/ui/notify.d.ts +40 -0
- package/dist/ui/notify.js +141 -0
- package/dist/ui/orb.d.ts +53 -0
- package/dist/ui/orb.js +304 -0
- package/dist/ui/overlay.d.ts +213 -0
- package/dist/ui/overlay.js +394 -0
- package/dist/ui/padnav.d.ts +53 -0
- package/dist/ui/padnav.js +146 -0
- package/dist/ui/perf.d.ts +130 -0
- package/dist/ui/perf.js +329 -0
- package/dist/ui/rotate-card.d.ts +54 -0
- package/dist/ui/rotate-card.js +97 -0
- package/dist/ui/stack.d.ts +128 -0
- package/dist/ui/stack.js +312 -0
- package/dist/ui/styles.d.ts +13 -0
- package/dist/ui/styles.js +200 -0
- package/dist/ui/text-scale.d.ts +67 -0
- package/dist/ui/text-scale.js +102 -0
- package/dist/ui/theme.d.ts +70 -0
- package/dist/ui/theme.js +98 -0
- package/dist/ui/toast.d.ts +23 -0
- package/dist/ui/toast.js +46 -0
- package/dist/ui/tooltip.d.ts +89 -0
- package/dist/ui/tooltip.js +333 -0
- package/dist/ui/widgets-2.d.ts +134 -0
- package/dist/ui/widgets-2.js +399 -0
- package/dist/ui/widgets-3.d.ts +91 -0
- package/dist/ui/widgets-3.js +212 -0
- package/dist/ui/widgets.d.ts +34 -0
- package/dist/ui/widgets.js +50 -0
- package/dist/ui/world-panel/index.d.ts +5 -0
- package/dist/ui/world-panel/index.js +5 -0
- package/dist/ui/world-panel/layout.d.ts +38 -0
- package/dist/ui/world-panel/layout.js +68 -0
- package/dist/ui/world-panel/paint.d.ts +96 -0
- package/dist/ui/world-panel/paint.js +136 -0
- package/dist/ui/world-panel/panel.d.ts +235 -0
- package/dist/ui/world-panel/panel.js +762 -0
- package/dist/ui/world-panel/wgsl.d.ts +10 -0
- package/dist/ui/world-panel/wgsl.js +52 -0
- package/dist/ui/world-panel/widgets.d.ts +207 -0
- package/dist/ui/world-panel/widgets.js +569 -0
- package/dist/voxel/chunks.d.ts +77 -0
- package/dist/voxel/chunks.js +149 -0
- package/dist/voxel/grid.d.ts +84 -0
- package/dist/voxel/grid.js +223 -0
- package/dist/voxel/index.d.ts +22 -0
- package/dist/voxel/index.js +7 -0
- package/dist/voxel/mesher-worker.d.ts +14 -0
- package/dist/voxel/mesher-worker.js +47 -0
- package/dist/voxel/mesher.d.ts +73 -0
- package/dist/voxel/mesher.js +306 -0
- package/dist/voxel/ray.d.ts +32 -0
- package/dist/voxel/ray.js +73 -0
- package/dist/voxel/wgsl.d.ts +16 -0
- package/dist/voxel/wgsl.js +28 -0
- package/dist/voxel/worker-client.d.ts +79 -0
- package/dist/voxel/worker-client.js +122 -0
- package/package.json +177 -3
|
@@ -0,0 +1,369 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ICU-style message syntax: a parser that runs once per string when a table loads, and a
|
|
3
|
+
* formatter that walks the resulting AST and builds only the output string.
|
|
4
|
+
*
|
|
5
|
+
* Supported forms:
|
|
6
|
+
* - `{name}`: an argument. Numbers go through `Intl.NumberFormat`, dates through
|
|
7
|
+
* `Intl.DateTimeFormat`, everything else through `String`.
|
|
8
|
+
* - `{n, number}`, `{n, number, integer | percent}`; `{d, date}`, `{d, date, short | medium |
|
|
9
|
+
* long | full}`; `{d, time}`, `{d, time, short | medium | long | full}`.
|
|
10
|
+
* - `{count, plural, offset:1 =0 {none} one {# item} other {# items}}`: `Intl.PluralRules`
|
|
11
|
+
* cardinal categories (`zero one two few many other`), exact `=N` forms checked first, `#` the
|
|
12
|
+
* number minus the offset, formatted for the locale. `selectordinal` uses ordinal rules.
|
|
13
|
+
* - `{g, select, male {he} female {she} other {they}}`.
|
|
14
|
+
* - `'{'` quotes a special character (`{ } #`), `''` is one apostrophe; any other apostrophe is
|
|
15
|
+
* literal.
|
|
16
|
+
*
|
|
17
|
+
* Every error names the key and the 1-based column where parsing stopped.
|
|
18
|
+
*/
|
|
19
|
+
export class MessageSyntaxError extends Error {
|
|
20
|
+
key;
|
|
21
|
+
/** 1-based column in the message where parsing stopped. */
|
|
22
|
+
column;
|
|
23
|
+
constructor(key, column, detail) {
|
|
24
|
+
super(`i18n: "${key}" column ${column}: ${detail}`);
|
|
25
|
+
this.name = 'MessageSyntaxError';
|
|
26
|
+
this.key = key;
|
|
27
|
+
this.column = column;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
const SPECIAL = new Set(['{', '}', '#']);
|
|
31
|
+
const IDENT = /[A-Za-z0-9_]/;
|
|
32
|
+
const WS = /\s/;
|
|
33
|
+
class Parser {
|
|
34
|
+
src;
|
|
35
|
+
key;
|
|
36
|
+
pos = 0;
|
|
37
|
+
constructor(src, key) {
|
|
38
|
+
this.src = src;
|
|
39
|
+
this.key = key;
|
|
40
|
+
}
|
|
41
|
+
fail(detail, at = this.pos) {
|
|
42
|
+
throw new MessageSyntaxError(this.key, Math.min(at, this.src.length) + 1, detail);
|
|
43
|
+
}
|
|
44
|
+
skipWs() {
|
|
45
|
+
while (this.pos < this.src.length && WS.test(this.src[this.pos]))
|
|
46
|
+
this.pos++;
|
|
47
|
+
}
|
|
48
|
+
ident(what) {
|
|
49
|
+
const start = this.pos;
|
|
50
|
+
while (this.pos < this.src.length && IDENT.test(this.src[this.pos]))
|
|
51
|
+
this.pos++;
|
|
52
|
+
if (this.pos === start)
|
|
53
|
+
this.fail(`expected ${what}`);
|
|
54
|
+
return this.src.slice(start, this.pos);
|
|
55
|
+
}
|
|
56
|
+
expect(ch) {
|
|
57
|
+
if (this.src[this.pos] !== ch) {
|
|
58
|
+
this.fail(this.pos >= this.src.length ? `unexpected end, expected '${ch}'` : `expected '${ch}'`);
|
|
59
|
+
}
|
|
60
|
+
this.pos++;
|
|
61
|
+
}
|
|
62
|
+
/** Parses up to `}` (nested) or the end (top level). */
|
|
63
|
+
sequence(nested, inPlural) {
|
|
64
|
+
const out = [];
|
|
65
|
+
let text = '';
|
|
66
|
+
const flush = () => {
|
|
67
|
+
if (text)
|
|
68
|
+
out.push(text);
|
|
69
|
+
text = '';
|
|
70
|
+
};
|
|
71
|
+
const s = this.src;
|
|
72
|
+
while (this.pos < s.length) {
|
|
73
|
+
const c = s[this.pos];
|
|
74
|
+
if (c === "'") {
|
|
75
|
+
const next = s[this.pos + 1];
|
|
76
|
+
if (next === "'") {
|
|
77
|
+
text += "'";
|
|
78
|
+
this.pos += 2;
|
|
79
|
+
}
|
|
80
|
+
else if (next !== undefined && SPECIAL.has(next)) {
|
|
81
|
+
// Quoted literal to the next lone apostrophe (or the end, as ICU does).
|
|
82
|
+
this.pos++;
|
|
83
|
+
while (this.pos < s.length) {
|
|
84
|
+
if (s[this.pos] === "'") {
|
|
85
|
+
if (s[this.pos + 1] === "'") {
|
|
86
|
+
text += "'";
|
|
87
|
+
this.pos += 2;
|
|
88
|
+
continue;
|
|
89
|
+
}
|
|
90
|
+
this.pos++;
|
|
91
|
+
break;
|
|
92
|
+
}
|
|
93
|
+
text += s[this.pos++];
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
else {
|
|
97
|
+
text += c;
|
|
98
|
+
this.pos++;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
else if (c === '{') {
|
|
102
|
+
flush();
|
|
103
|
+
out.push(this.argument(inPlural));
|
|
104
|
+
}
|
|
105
|
+
else if (c === '}') {
|
|
106
|
+
if (!nested)
|
|
107
|
+
this.fail("unmatched '}'");
|
|
108
|
+
flush();
|
|
109
|
+
return out;
|
|
110
|
+
}
|
|
111
|
+
else if (c === '#' && inPlural) {
|
|
112
|
+
flush();
|
|
113
|
+
out.push({ kind: 'hash' });
|
|
114
|
+
this.pos++;
|
|
115
|
+
}
|
|
116
|
+
else {
|
|
117
|
+
text += c;
|
|
118
|
+
this.pos++;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
if (nested)
|
|
122
|
+
this.fail("unexpected end, expected '}'");
|
|
123
|
+
flush();
|
|
124
|
+
return out;
|
|
125
|
+
}
|
|
126
|
+
argument(inPlural) {
|
|
127
|
+
this.expect('{');
|
|
128
|
+
this.skipWs();
|
|
129
|
+
const name = this.ident('an argument name');
|
|
130
|
+
this.skipWs();
|
|
131
|
+
if (this.src[this.pos] === '}') {
|
|
132
|
+
this.pos++;
|
|
133
|
+
return { kind: 'arg', name };
|
|
134
|
+
}
|
|
135
|
+
if (this.src[this.pos] !== ',') {
|
|
136
|
+
this.fail(this.pos >= this.src.length ? "unexpected end, expected '}' or ','" : "expected '}' or ','");
|
|
137
|
+
}
|
|
138
|
+
this.pos++;
|
|
139
|
+
this.skipWs();
|
|
140
|
+
const typeAt = this.pos;
|
|
141
|
+
const type = this.ident('an argument type');
|
|
142
|
+
this.skipWs();
|
|
143
|
+
switch (type) {
|
|
144
|
+
case 'number':
|
|
145
|
+
case 'date':
|
|
146
|
+
case 'time': {
|
|
147
|
+
let style = null;
|
|
148
|
+
if (this.src[this.pos] === ',') {
|
|
149
|
+
this.pos++;
|
|
150
|
+
this.skipWs();
|
|
151
|
+
style = this.ident('a style');
|
|
152
|
+
this.skipWs();
|
|
153
|
+
}
|
|
154
|
+
this.expect('}');
|
|
155
|
+
return { kind: type, name, style };
|
|
156
|
+
}
|
|
157
|
+
case 'plural':
|
|
158
|
+
case 'selectordinal':
|
|
159
|
+
this.expect(',');
|
|
160
|
+
return this.plural(name, type === 'selectordinal');
|
|
161
|
+
case 'select':
|
|
162
|
+
this.expect(',');
|
|
163
|
+
return this.select(name, inPlural);
|
|
164
|
+
default:
|
|
165
|
+
this.fail(`unknown argument type '${type}'`, typeAt);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
plural(name, ordinal) {
|
|
169
|
+
const exact = new Map();
|
|
170
|
+
const categories = new Map();
|
|
171
|
+
let other = null;
|
|
172
|
+
let offset = 0;
|
|
173
|
+
this.skipWs();
|
|
174
|
+
if (this.src.startsWith('offset:', this.pos)) {
|
|
175
|
+
this.pos += 'offset:'.length;
|
|
176
|
+
this.skipWs();
|
|
177
|
+
const at = this.pos;
|
|
178
|
+
const digits = this.ident('an offset');
|
|
179
|
+
offset = Number(digits);
|
|
180
|
+
if (!Number.isInteger(offset))
|
|
181
|
+
this.fail(`bad offset '${digits}'`, at);
|
|
182
|
+
this.skipWs();
|
|
183
|
+
}
|
|
184
|
+
for (;;) {
|
|
185
|
+
this.skipWs();
|
|
186
|
+
if (this.src[this.pos] === '}')
|
|
187
|
+
break;
|
|
188
|
+
if (this.pos >= this.src.length)
|
|
189
|
+
this.fail("unexpected end, expected '}'");
|
|
190
|
+
const at = this.pos;
|
|
191
|
+
if (this.src[this.pos] === '=') {
|
|
192
|
+
this.pos++;
|
|
193
|
+
const digits = this.ident('a number after =');
|
|
194
|
+
const n = Number(digits);
|
|
195
|
+
if (!Number.isFinite(n))
|
|
196
|
+
this.fail(`bad exact form '=${digits}'`, at);
|
|
197
|
+
exact.set(n, this.caseBody(true));
|
|
198
|
+
continue;
|
|
199
|
+
}
|
|
200
|
+
const selector = this.ident('a plural category');
|
|
201
|
+
if (selector === 'other')
|
|
202
|
+
other = this.caseBody(true);
|
|
203
|
+
else if (CATEGORIES.has(selector))
|
|
204
|
+
categories.set(selector, this.caseBody(true));
|
|
205
|
+
else
|
|
206
|
+
this.fail(`unknown plural category '${selector}'`, at);
|
|
207
|
+
}
|
|
208
|
+
if (!other)
|
|
209
|
+
this.fail("plural needs an 'other' case");
|
|
210
|
+
this.pos++;
|
|
211
|
+
return { kind: 'plural', name, ordinal, offset, exact, categories, other };
|
|
212
|
+
}
|
|
213
|
+
select(name, inPlural) {
|
|
214
|
+
const cases = new Map();
|
|
215
|
+
let other = null;
|
|
216
|
+
for (;;) {
|
|
217
|
+
this.skipWs();
|
|
218
|
+
if (this.src[this.pos] === '}')
|
|
219
|
+
break;
|
|
220
|
+
if (this.pos >= this.src.length)
|
|
221
|
+
this.fail("unexpected end, expected '}'");
|
|
222
|
+
const selector = this.ident('a select case');
|
|
223
|
+
const body = this.caseBody(inPlural);
|
|
224
|
+
if (selector === 'other')
|
|
225
|
+
other = body;
|
|
226
|
+
else
|
|
227
|
+
cases.set(selector, body);
|
|
228
|
+
}
|
|
229
|
+
if (!other)
|
|
230
|
+
this.fail("select needs an 'other' case");
|
|
231
|
+
this.pos++;
|
|
232
|
+
return { kind: 'select', name, cases, other };
|
|
233
|
+
}
|
|
234
|
+
caseBody(inPlural) {
|
|
235
|
+
this.skipWs();
|
|
236
|
+
this.expect('{');
|
|
237
|
+
const body = this.sequence(true, inPlural);
|
|
238
|
+
this.expect('}');
|
|
239
|
+
return body;
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
const CATEGORIES = new Set(['zero', 'one', 'two', 'few', 'many']);
|
|
243
|
+
/** Parses one message. Throws `MessageSyntaxError` naming `key` and the column. */
|
|
244
|
+
export function parseMessage(source, key = 'message') {
|
|
245
|
+
return new Parser(source, key).sequence(false, false);
|
|
246
|
+
}
|
|
247
|
+
const DATE_STYLES = new Set(['short', 'medium', 'long', 'full']);
|
|
248
|
+
export function createIntlCache() {
|
|
249
|
+
const plurals = new Map();
|
|
250
|
+
const numbers = new Map();
|
|
251
|
+
const dates = new Map();
|
|
252
|
+
return {
|
|
253
|
+
plural(locale, ordinal) {
|
|
254
|
+
const k = `${locale}|${ordinal ? 'o' : 'c'}`;
|
|
255
|
+
let r = plurals.get(k);
|
|
256
|
+
if (!r) {
|
|
257
|
+
r = new Intl.PluralRules(locale, { type: ordinal ? 'ordinal' : 'cardinal' });
|
|
258
|
+
plurals.set(k, r);
|
|
259
|
+
}
|
|
260
|
+
return r;
|
|
261
|
+
},
|
|
262
|
+
number(locale, style) {
|
|
263
|
+
const k = `${locale}|${style ?? ''}`;
|
|
264
|
+
let f = numbers.get(k);
|
|
265
|
+
if (!f) {
|
|
266
|
+
const opts = style === 'integer'
|
|
267
|
+
? { maximumFractionDigits: 0 }
|
|
268
|
+
: style === 'percent'
|
|
269
|
+
? { style: 'percent' }
|
|
270
|
+
: {};
|
|
271
|
+
f = new Intl.NumberFormat(locale, opts);
|
|
272
|
+
numbers.set(k, f);
|
|
273
|
+
}
|
|
274
|
+
return f;
|
|
275
|
+
},
|
|
276
|
+
date(locale, kind, style) {
|
|
277
|
+
const k = `${locale}|${kind}|${style ?? ''}`;
|
|
278
|
+
let f = dates.get(k);
|
|
279
|
+
if (!f) {
|
|
280
|
+
const s = style && DATE_STYLES.has(style)
|
|
281
|
+
? style
|
|
282
|
+
: undefined;
|
|
283
|
+
const opts = kind === 'date' ? { dateStyle: s ?? 'medium' } : { timeStyle: s ?? 'short' };
|
|
284
|
+
f = new Intl.DateTimeFormat(locale, opts);
|
|
285
|
+
dates.set(k, f);
|
|
286
|
+
}
|
|
287
|
+
return f;
|
|
288
|
+
},
|
|
289
|
+
};
|
|
290
|
+
}
|
|
291
|
+
/**
|
|
292
|
+
* Formats a parsed message for `locale`. A missing argument renders as `{name}` so the UI never
|
|
293
|
+
* shows an empty string. Allocates only the output string.
|
|
294
|
+
*/
|
|
295
|
+
export function formatMessage(ast, args, locale, intl) {
|
|
296
|
+
return walk(ast, args, locale, intl, null);
|
|
297
|
+
}
|
|
298
|
+
function walk(ast, args, locale, intl, hash) {
|
|
299
|
+
let out = '';
|
|
300
|
+
for (let i = 0; i < ast.length; i++) {
|
|
301
|
+
const node = ast[i];
|
|
302
|
+
if (typeof node === 'string') {
|
|
303
|
+
out += node;
|
|
304
|
+
continue;
|
|
305
|
+
}
|
|
306
|
+
switch (node.kind) {
|
|
307
|
+
case 'hash':
|
|
308
|
+
if (hash === null)
|
|
309
|
+
out += '#';
|
|
310
|
+
else if (typeof hash === 'number')
|
|
311
|
+
out += intl.number(locale, null).format(hash);
|
|
312
|
+
else
|
|
313
|
+
out += hash;
|
|
314
|
+
break;
|
|
315
|
+
case 'arg': {
|
|
316
|
+
const v = args?.[node.name];
|
|
317
|
+
if (v === undefined)
|
|
318
|
+
out += `{${node.name}}`;
|
|
319
|
+
else if (typeof v === 'number')
|
|
320
|
+
out += intl.number(locale, null).format(v);
|
|
321
|
+
else if (v instanceof Date)
|
|
322
|
+
out += intl.date(locale, 'date', null).format(v);
|
|
323
|
+
else
|
|
324
|
+
out += String(v);
|
|
325
|
+
break;
|
|
326
|
+
}
|
|
327
|
+
case 'number': {
|
|
328
|
+
const v = args?.[node.name];
|
|
329
|
+
if (typeof v === 'number')
|
|
330
|
+
out += intl.number(locale, node.style).format(v);
|
|
331
|
+
else
|
|
332
|
+
out += v === undefined ? `{${node.name}}` : String(v);
|
|
333
|
+
break;
|
|
334
|
+
}
|
|
335
|
+
case 'date':
|
|
336
|
+
case 'time': {
|
|
337
|
+
const v = args?.[node.name];
|
|
338
|
+
if (v instanceof Date || typeof v === 'number')
|
|
339
|
+
out += intl.date(locale, node.kind, node.style).format(v);
|
|
340
|
+
else
|
|
341
|
+
out += v === undefined ? `{${node.name}}` : String(v);
|
|
342
|
+
break;
|
|
343
|
+
}
|
|
344
|
+
case 'plural': {
|
|
345
|
+
const v = args?.[node.name];
|
|
346
|
+
if (typeof v !== 'number') {
|
|
347
|
+
// Not a number: `other`, with `#` printing the argument (or its placeholder) as text.
|
|
348
|
+
const text = v === undefined ? `{${node.name}}` : String(v);
|
|
349
|
+
out += walk(node.other, args, locale, intl, text);
|
|
350
|
+
break;
|
|
351
|
+
}
|
|
352
|
+
const inner = v - node.offset;
|
|
353
|
+
const exact = node.exact.get(v);
|
|
354
|
+
const branch = exact ??
|
|
355
|
+
node.categories.get(intl.plural(locale, node.ordinal).select(inner)) ??
|
|
356
|
+
node.other;
|
|
357
|
+
out += walk(branch, args, locale, intl, inner);
|
|
358
|
+
break;
|
|
359
|
+
}
|
|
360
|
+
case 'select': {
|
|
361
|
+
const v = args?.[node.name];
|
|
362
|
+
const branch = (v === undefined ? undefined : node.cases.get(String(v))) ?? node.other;
|
|
363
|
+
out += walk(branch, args, locale, intl, hash);
|
|
364
|
+
break;
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
return out;
|
|
369
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/** Locale matching and text direction. No `Intl.Locale` needed: BCP 47 tags split on `-`. */
|
|
2
|
+
export type TextDirection = 'ltr' | 'rtl';
|
|
3
|
+
/** Language subtags written right to left. Scripts are not consulted: `ar-Latn` is rare in games. */
|
|
4
|
+
export declare const RTL_LANGUAGES: ReadonlySet<string>;
|
|
5
|
+
/** The language subtag of a BCP 47 tag, lower case: `pt-BR` → `pt`. */
|
|
6
|
+
export declare function languageOf(locale: string): string;
|
|
7
|
+
/** `'rtl'` when the language subtag is in `RTL_LANGUAGES`, else `'ltr'`. */
|
|
8
|
+
export declare function directionOf(locale: string): TextDirection;
|
|
9
|
+
/** What the browser asks for, most preferred first; empty outside a browser. */
|
|
10
|
+
export declare function requestedLocales(): readonly string[];
|
|
11
|
+
/**
|
|
12
|
+
* Picks the locale from `available` that best matches `requested` (most preferred first,
|
|
13
|
+
* `navigator.languages` by default). For each requested tag in order: an exact match
|
|
14
|
+
* (case-insensitive), else the first available tag sharing its language subtag (`en-US` → `en`
|
|
15
|
+
* or `en-GB`). When nothing matches, `fallback` (the first entry of `available`).
|
|
16
|
+
*/
|
|
17
|
+
export declare function negotiateLocale(available: readonly string[], requested?: readonly string[], fallback?: string): string;
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/** Locale matching and text direction. No `Intl.Locale` needed: BCP 47 tags split on `-`. */
|
|
2
|
+
/** Language subtags written right to left. Scripts are not consulted: `ar-Latn` is rare in games. */
|
|
3
|
+
export const RTL_LANGUAGES = new Set([
|
|
4
|
+
'ar',
|
|
5
|
+
'arc',
|
|
6
|
+
'ckb',
|
|
7
|
+
'dv',
|
|
8
|
+
'fa',
|
|
9
|
+
'ha',
|
|
10
|
+
'he',
|
|
11
|
+
'iw',
|
|
12
|
+
'khw',
|
|
13
|
+
'ks',
|
|
14
|
+
'ku',
|
|
15
|
+
'ps',
|
|
16
|
+
'sd',
|
|
17
|
+
'syr',
|
|
18
|
+
'ug',
|
|
19
|
+
'ur',
|
|
20
|
+
'yi',
|
|
21
|
+
]);
|
|
22
|
+
/** The language subtag of a BCP 47 tag, lower case: `pt-BR` → `pt`. */
|
|
23
|
+
export function languageOf(locale) {
|
|
24
|
+
return locale.split(/[-_]/, 1)[0].toLowerCase();
|
|
25
|
+
}
|
|
26
|
+
/** `'rtl'` when the language subtag is in `RTL_LANGUAGES`, else `'ltr'`. */
|
|
27
|
+
export function directionOf(locale) {
|
|
28
|
+
return RTL_LANGUAGES.has(languageOf(locale)) ? 'rtl' : 'ltr';
|
|
29
|
+
}
|
|
30
|
+
/** What the browser asks for, most preferred first; empty outside a browser. */
|
|
31
|
+
export function requestedLocales() {
|
|
32
|
+
if (typeof navigator === 'undefined')
|
|
33
|
+
return [];
|
|
34
|
+
if (navigator.languages?.length)
|
|
35
|
+
return navigator.languages;
|
|
36
|
+
return navigator.language ? [navigator.language] : [];
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Picks the locale from `available` that best matches `requested` (most preferred first,
|
|
40
|
+
* `navigator.languages` by default). For each requested tag in order: an exact match
|
|
41
|
+
* (case-insensitive), else the first available tag sharing its language subtag (`en-US` → `en`
|
|
42
|
+
* or `en-GB`). When nothing matches, `fallback` (the first entry of `available`).
|
|
43
|
+
*/
|
|
44
|
+
export function negotiateLocale(available, requested = requestedLocales(), fallback = available[0]) {
|
|
45
|
+
if (available.length === 0)
|
|
46
|
+
return fallback;
|
|
47
|
+
for (const want of requested) {
|
|
48
|
+
const w = want.toLowerCase();
|
|
49
|
+
const exact = available.find((a) => a.toLowerCase() === w);
|
|
50
|
+
if (exact !== undefined)
|
|
51
|
+
return exact;
|
|
52
|
+
const lang = languageOf(want);
|
|
53
|
+
const partial = available.find((a) => languageOf(a) === lang);
|
|
54
|
+
if (partial !== undefined)
|
|
55
|
+
return partial;
|
|
56
|
+
}
|
|
57
|
+
return fallback;
|
|
58
|
+
}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@thunderclap-engine/engine`: the top layer a game touches (D-041). `createGame()` boots the platform
|
|
3
|
+
* and wires every noun-free system into one ctx. The modules under it stay reachable through
|
|
4
|
+
* their own subpaths (`@thunderclap-engine/engine/<module>`).
|
|
5
|
+
*/
|
|
6
|
+
export type { CreateGameOptions, EngineCtx, FlushableSave, GameHooks, GameReplay, HideReason, ReplayOptions, ShowReason, SimOption, XrControl, XrOptions, } from './core/game.js';
|
|
7
|
+
export { createGame } from './core/game.js';
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { createGame } from './core/game.js';
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Saving, loading and checking bindings maps (ws/input-3). `serializeBindings` writes the map a
|
|
3
|
+
* game got from `Input.bindings()` as JSON; `parseBindings` reads it back against the game's
|
|
4
|
+
* defaults (unknown actions dropped with a warning, missing ones filled in, malformed bindings
|
|
5
|
+
* dropped); `findConflicts` lists inputs bound to more than one action.
|
|
6
|
+
*/
|
|
7
|
+
import type { Binding, Bindings } from './types.js';
|
|
8
|
+
/** Plain JSON of a bindings map, for saving. */
|
|
9
|
+
export declare function serializeBindings<A extends string>(map: Bindings<A>): string;
|
|
10
|
+
/**
|
|
11
|
+
* Read a bindings map saved by `serializeBindings` (text or an already-parsed object). Every
|
|
12
|
+
* action in `defaults` is present in the result: from `text` when it has a well-formed list
|
|
13
|
+
* there, else from `defaults`. Actions not in `defaults` are dropped with one `console.warn`
|
|
14
|
+
* naming them; malformed bindings are dropped the same way. Unparseable text yields `defaults`.
|
|
15
|
+
*/
|
|
16
|
+
export declare function parseBindings<A extends string>(text: string | unknown, defaults: Bindings<A>): Bindings<A>;
|
|
17
|
+
/** One input bound to several actions. */
|
|
18
|
+
export interface BindingConflict {
|
|
19
|
+
/** The binding (its first occurrence). */
|
|
20
|
+
binding: Binding;
|
|
21
|
+
/** The actions sharing it, in map order. */
|
|
22
|
+
actions: string[];
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Inputs bound to more than one action. Two bindings conflict when their input and trigger
|
|
26
|
+
* fields are equal (a `hold` and a `press` on the same key do not); chords conflict only with
|
|
27
|
+
* identical chords.
|
|
28
|
+
*/
|
|
29
|
+
export declare function findConflicts<A extends string>(map: Bindings<A>): BindingConflict[];
|
|
30
|
+
/** Structural check of one binding (its input shape and optional trigger fields). */
|
|
31
|
+
export declare function isBinding(v: unknown): v is Binding;
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
const GESTURES = new Set(['tap', 'doubleTap', 'longPress', 'pan', 'drag', 'pinch']);
|
|
2
|
+
const POINTER_BUTTONS = new Set(['select', 'secondary']);
|
|
3
|
+
const XR_BUTTONS = new Set(['trigger', 'squeeze', 'pinch']);
|
|
4
|
+
const TRIGGERS = new Set(['press', 'hold', 'doubleTap']);
|
|
5
|
+
/** Plain JSON of a bindings map, for saving. */
|
|
6
|
+
export function serializeBindings(map) {
|
|
7
|
+
return JSON.stringify(map);
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Read a bindings map saved by `serializeBindings` (text or an already-parsed object). Every
|
|
11
|
+
* action in `defaults` is present in the result: from `text` when it has a well-formed list
|
|
12
|
+
* there, else from `defaults`. Actions not in `defaults` are dropped with one `console.warn`
|
|
13
|
+
* naming them; malformed bindings are dropped the same way. Unparseable text yields `defaults`.
|
|
14
|
+
*/
|
|
15
|
+
export function parseBindings(text, defaults) {
|
|
16
|
+
let raw;
|
|
17
|
+
if (typeof text === 'string') {
|
|
18
|
+
try {
|
|
19
|
+
raw = JSON.parse(text);
|
|
20
|
+
}
|
|
21
|
+
catch {
|
|
22
|
+
console.warn('[input] bindings: not JSON; using defaults');
|
|
23
|
+
return defaults;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
else
|
|
27
|
+
raw = text;
|
|
28
|
+
if (!isObject(raw)) {
|
|
29
|
+
console.warn('[input] bindings: not an object; using defaults');
|
|
30
|
+
return defaults;
|
|
31
|
+
}
|
|
32
|
+
const out = {};
|
|
33
|
+
const unknown = [];
|
|
34
|
+
const malformed = [];
|
|
35
|
+
for (const action of Object.keys(raw)) {
|
|
36
|
+
if (!(action in defaults))
|
|
37
|
+
unknown.push(action);
|
|
38
|
+
}
|
|
39
|
+
for (const action of Object.keys(defaults)) {
|
|
40
|
+
const list = raw[action];
|
|
41
|
+
if (list === undefined) {
|
|
42
|
+
out[action] = defaults[action];
|
|
43
|
+
continue;
|
|
44
|
+
}
|
|
45
|
+
if (!Array.isArray(list)) {
|
|
46
|
+
malformed.push(action);
|
|
47
|
+
out[action] = defaults[action];
|
|
48
|
+
continue;
|
|
49
|
+
}
|
|
50
|
+
const good = [];
|
|
51
|
+
for (const b of list) {
|
|
52
|
+
if (isBinding(b))
|
|
53
|
+
good.push(b);
|
|
54
|
+
else
|
|
55
|
+
malformed.push(action);
|
|
56
|
+
}
|
|
57
|
+
out[action] = good;
|
|
58
|
+
}
|
|
59
|
+
if (unknown.length)
|
|
60
|
+
console.warn(`[input] bindings: unknown actions dropped: ${unknown.join(', ')}`);
|
|
61
|
+
if (malformed.length) {
|
|
62
|
+
console.warn(`[input] bindings: malformed bindings dropped in: ${[...new Set(malformed)].join(', ')}`);
|
|
63
|
+
}
|
|
64
|
+
return out;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Inputs bound to more than one action. Two bindings conflict when their input and trigger
|
|
68
|
+
* fields are equal (a `hold` and a `press` on the same key do not); chords conflict only with
|
|
69
|
+
* identical chords.
|
|
70
|
+
*/
|
|
71
|
+
export function findConflicts(map) {
|
|
72
|
+
const seen = new Map();
|
|
73
|
+
for (const action of Object.keys(map)) {
|
|
74
|
+
for (const b of map[action]) {
|
|
75
|
+
const key = canonical(b);
|
|
76
|
+
const c = seen.get(key);
|
|
77
|
+
if (c) {
|
|
78
|
+
if (!c.actions.includes(action))
|
|
79
|
+
c.actions.push(action);
|
|
80
|
+
}
|
|
81
|
+
else
|
|
82
|
+
seen.set(key, { binding: b, actions: [action] });
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
const out = [];
|
|
86
|
+
for (const c of seen.values())
|
|
87
|
+
if (c.actions.length > 1)
|
|
88
|
+
out.push(c);
|
|
89
|
+
return out;
|
|
90
|
+
}
|
|
91
|
+
/** A stable key for a binding: its fields sorted, defaults made explicit. */
|
|
92
|
+
function canonical(b) {
|
|
93
|
+
const o = { ...b };
|
|
94
|
+
if (o.trigger === 'press')
|
|
95
|
+
delete o.trigger;
|
|
96
|
+
if ('chord' in b)
|
|
97
|
+
o.chord = b.chord.map(canonical);
|
|
98
|
+
return JSON.stringify(o, Object.keys(o).sort());
|
|
99
|
+
}
|
|
100
|
+
function isObject(v) {
|
|
101
|
+
return typeof v === 'object' && v !== null && !Array.isArray(v);
|
|
102
|
+
}
|
|
103
|
+
function isNum(v) {
|
|
104
|
+
return typeof v === 'number' && Number.isFinite(v);
|
|
105
|
+
}
|
|
106
|
+
/** Structural check of one binding (its input shape and optional trigger fields). */
|
|
107
|
+
export function isBinding(v) {
|
|
108
|
+
if (!isObject(v))
|
|
109
|
+
return false;
|
|
110
|
+
if (v.trigger !== undefined && !TRIGGERS.has(v.trigger))
|
|
111
|
+
return false;
|
|
112
|
+
if (v.holdMs !== undefined && !isNum(v.holdMs))
|
|
113
|
+
return false;
|
|
114
|
+
if (v.doubleTapMs !== undefined && !isNum(v.doubleTapMs))
|
|
115
|
+
return false;
|
|
116
|
+
if ('key' in v)
|
|
117
|
+
return typeof v.key === 'string';
|
|
118
|
+
if ('mouse' in v)
|
|
119
|
+
return isNum(v.mouse);
|
|
120
|
+
if ('wheel' in v)
|
|
121
|
+
return v.wheel === 1 || v.wheel === -1;
|
|
122
|
+
if ('padButton' in v)
|
|
123
|
+
return isNum(v.padButton) && optNum(v.pad) && optNum(v.threshold);
|
|
124
|
+
if ('padAxis' in v) {
|
|
125
|
+
return (isNum(v.padAxis) && (v.dir === 1 || v.dir === -1) && optNum(v.pad) && optNum(v.threshold));
|
|
126
|
+
}
|
|
127
|
+
if ('gesture' in v)
|
|
128
|
+
return GESTURES.has(v.gesture);
|
|
129
|
+
if ('pointer' in v)
|
|
130
|
+
return POINTER_BUTTONS.has(v.pointer);
|
|
131
|
+
if ('xr' in v) {
|
|
132
|
+
return (XR_BUTTONS.has(v.xr) &&
|
|
133
|
+
(v.hand === undefined || v.hand === 'left' || v.hand === 'right'));
|
|
134
|
+
}
|
|
135
|
+
if ('chord' in v)
|
|
136
|
+
return Array.isArray(v.chord) && v.chord.every(isBinding);
|
|
137
|
+
return false;
|
|
138
|
+
}
|
|
139
|
+
function optNum(v) {
|
|
140
|
+
return v === undefined || isNum(v);
|
|
141
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The clock gestures and look are timed on (ws/input-8). By default that is `performance.now()`
|
|
3
|
+
* (wall time). A game with a fixed step passes one `createTickClock()` to both and advances it
|
|
4
|
+
* from the step, so long-presses, double taps, look acceleration and `Look.onTap` run on game
|
|
5
|
+
* time, and a recording replays the same gestures on the same tick indices however far apart
|
|
6
|
+
* the replay's ticks are in wall time.
|
|
7
|
+
*/
|
|
8
|
+
/** A clock in ms. Only differences between readings matter; it should never go backwards. */
|
|
9
|
+
export interface InputClock {
|
|
10
|
+
now(): number;
|
|
11
|
+
}
|
|
12
|
+
/** A clock that moves only when told: `advance(ms)` once per fixed step. */
|
|
13
|
+
export interface TickClock extends InputClock {
|
|
14
|
+
/** Move the clock forward by `ms`. Negative and non-finite values are ignored. */
|
|
15
|
+
advance(ms: number): void;
|
|
16
|
+
}
|
|
17
|
+
/** `performance.now()` (or `Date.now()` where there is no `performance`): the default clock. */
|
|
18
|
+
export declare const wallClock: InputClock;
|
|
19
|
+
/**
|
|
20
|
+
* A game-time clock for gestures and look. Call `advance(stepMs)` from the fixed step, before
|
|
21
|
+
* `input.update()`, and pass the same clock to `createGestures({ clock })` and
|
|
22
|
+
* `createLook({ clock })` so the two share one time base. `start` is the first reading
|
|
23
|
+
* (default 0).
|
|
24
|
+
*
|
|
25
|
+
* ```ts
|
|
26
|
+
* const clock = createTickClock();
|
|
27
|
+
* const input = new Input(bindings, {
|
|
28
|
+
* gestures: createGestures({ clock }),
|
|
29
|
+
* look: createLook({ clock }),
|
|
30
|
+
* });
|
|
31
|
+
* // GameLoop `update(dt)`, in fixed steps of `dt` seconds:
|
|
32
|
+
* clock.advance(dt * 1000);
|
|
33
|
+
* input.update();
|
|
34
|
+
* ```
|
|
35
|
+
*/
|
|
36
|
+
export declare function createTickClock(start?: number): TickClock;
|
|
37
|
+
/**
|
|
38
|
+
* The clock options gestures and look accept resolved to one clock and its bound `now`:
|
|
39
|
+
* `clock` wins over the older `now` function, and with neither it is `wallClock`.
|
|
40
|
+
*/
|
|
41
|
+
export declare function resolveClock(clock: InputClock | undefined, now: (() => number) | undefined): {
|
|
42
|
+
clock: InputClock;
|
|
43
|
+
now: () => number;
|
|
44
|
+
};
|