@datamoc/mw_games 0.44.2 → 0.45.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/3d/models.d.ts +1 -0
- package/3d/models.js +1 -0
- package/3d.d.ts +1 -0
- package/3d.js +1 -0
- package/README.md +5 -732
- package/actors.d.ts +1 -0
- package/actors.js +1 -0
- package/ai/lua.d.ts +1 -0
- package/ai/lua.js +1 -0
- package/ai.d.ts +1 -0
- package/ai.js +1 -0
- package/assets/binary.d.ts +1 -0
- package/assets/binary.js +1 -0
- package/assets/paths.d.ts +1 -0
- package/assets/paths.js +1 -0
- package/assets.d.ts +1 -0
- package/assets.js +1 -0
- package/audio.d.ts +1 -0
- package/audio.js +1 -0
- package/battle.d.ts +1 -0
- package/battle.js +1 -0
- package/board.d.ts +1 -0
- package/board.js +1 -0
- package/core.d.ts +1 -0
- package/core.js +1 -0
- package/headless.d.ts +1 -0
- package/headless.js +1 -0
- package/i18n.d.ts +1 -0
- package/i18n.js +1 -0
- package/index.d.ts +1 -0
- package/index.js +1 -0
- package/mwl/presentation.d.ts +1 -0
- package/mwl/presentation.js +1 -0
- package/mwl/pyroeis.d.ts +1 -0
- package/mwl/pyroeis.js +1 -0
- package/mwl.d.ts +1 -0
- package/mwl.js +1 -0
- package/package.json +212 -394
- package/physics/xpbd.d.ts +1 -0
- package/physics/xpbd.js +1 -0
- package/physics.d.ts +1 -0
- package/physics.js +1 -0
- package/roguelike.d.ts +1 -0
- package/roguelike.js +1 -0
- package/rpg.d.ts +1 -0
- package/rpg.js +1 -0
- package/simulation.d.ts +1 -0
- package/simulation.js +1 -0
- package/skeleton.d.ts +1 -0
- package/skeleton.js +1 -0
- package/testing.d.ts +1 -0
- package/testing.js +1 -0
- package/threads.d.ts +1 -0
- package/threads.js +1 -0
- package/tools/asset-report.d.mts +1 -37
- package/tools/asset-report.mjs +1 -157
- package/tools/audio.d.mts +1 -75
- package/tools/audio.mjs +1 -437
- package/tools/audit-adoptions.d.mts +1 -65
- package/tools/audit-adoptions.mjs +1 -252
- package/tools/benchmark-browser.d.mts +1 -33
- package/tools/benchmark-browser.mjs +1 -169
- package/tools/benchmark-history.d.mts +1 -8
- package/tools/benchmark-history.mjs +1 -31
- package/tools/browser-driver.d.mts +1 -122
- package/tools/browser-driver.mjs +1 -861
- package/tools/browser-smoke.d.mts +1 -30
- package/tools/browser-smoke.mjs +1 -184
- package/tools/build-tablebases.d.mts +1 -22
- package/tools/build-tablebases.mjs +1 -557
- package/tools/bundle-size.d.mts +1 -11
- package/tools/bundle-size.mjs +1 -142
- package/tools/classic-html.d.mts +1 -6
- package/tools/classic-html.mjs +1 -69
- package/tools/compile-openings.d.mts +1 -20
- package/tools/compile-openings.mjs +1 -138
- package/tools/compile-resources.d.mts +1 -66
- package/tools/compile-resources.mjs +1 -406
- package/tools/compress-dist.d.mts +1 -42
- package/tools/compress-dist.mjs +1 -193
- package/tools/csp.d.mts +1 -7
- package/tools/csp.mjs +1 -65
- package/tools/emit-page.d.mts +1 -61
- package/tools/emit-page.mjs +1 -273
- package/tools/extract-html.d.mts +1 -18
- package/tools/extract-html.mjs +1 -235
- package/tools/extract-rgssad.d.mts +1 -5
- package/tools/extract-rgssad.mjs +1 -64
- package/tools/find-chrome.d.mts +1 -7
- package/tools/find-chrome.mjs +1 -106
- package/tools/i18n-edit.d.mts +1 -29
- package/tools/i18n-edit.mjs +1 -748
- package/tools/init.d.mts +1 -5
- package/tools/init.mjs +1 -155
- package/tools/make-example-assets.d.mts +1 -2
- package/tools/make-example-assets.mjs +1 -731
- package/tools/multiplayer-server.d.mts +1 -27
- package/tools/multiplayer-server.mjs +1 -199
- package/tools/play-uci.d.mts +1 -26
- package/tools/play-uci.mjs +1 -205
- package/tools/sbom.d.mts +1 -83
- package/tools/sbom.mjs +1 -340
- package/tools/single-file.d.mts +1 -33
- package/tools/single-file.mjs +1 -239
- package/tools/soundfonts.d.mts +1 -79
- package/tools/soundfonts.mjs +1 -301
- package/tools/svg-optimise.d.mts +1 -8
- package/tools/svg-optimise.mjs +1 -45
- package/tools/verify-scenarios.d.mts +1 -15
- package/tools/verify-scenarios.mjs +1 -133
- package/tools/vite.d.mts +1 -17
- package/tools/vite.mjs +1 -102
- package/tools/webp-convert.d.mts +1 -8
- package/tools/webp-convert.mjs +1 -98
- package/two-d/pixi-interop.d.ts +1 -0
- package/two-d/pixi-interop.js +1 -0
- package/two-d/presentation.d.ts +1 -0
- package/two-d/presentation.js +1 -0
- package/two-d/render.d.ts +1 -0
- package/two-d/render.js +1 -0
- package/two-d/stage.d.ts +1 -0
- package/two-d/stage.js +1 -0
- package/two-d/ui.d.ts +1 -0
- package/two-d/ui.js +1 -0
- package/two-d.d.ts +1 -0
- package/two-d.js +1 -0
- package/world.d.ts +1 -0
- package/world.js +1 -0
- package/CHANGELOG.md +0 -3196
- package/LICENSE +0 -373
- package/MWG - Best Practices.md +0 -97
- package/MWG - Deep Code and Architecture Review.md +0 -238
- package/REFERENCE.md +0 -2256
- package/api-surface.json +0 -18128
- package/data/microgm-essential.PROVENANCE.md +0 -13
- package/data/microgm-essential.sf2 +0 -0
- package/data/microgm-opt.PROVENANCE.md +0 -23
- package/data/microgm-opt.sf2 +0 -0
- package/data/soundfont-catalog.json +0 -191
- package/dist/actors/Advancement.d.ts +0 -90
- package/dist/actors/Advancement.d.ts.map +0 -1
- package/dist/actors/Advancement.js +0 -115
- package/dist/actors/Advancement.js.map +0 -1
- package/dist/actors/Affix.d.ts +0 -96
- package/dist/actors/Affix.d.ts.map +0 -1
- package/dist/actors/Affix.js +0 -68
- package/dist/actors/Affix.js.map +0 -1
- package/dist/actors/Appearances.d.ts +0 -48
- package/dist/actors/Appearances.d.ts.map +0 -1
- package/dist/actors/Appearances.js +0 -62
- package/dist/actors/Appearances.js.map +0 -1
- package/dist/actors/Aura.d.ts +0 -45
- package/dist/actors/Aura.d.ts.map +0 -1
- package/dist/actors/Aura.js +0 -85
- package/dist/actors/Aura.js.map +0 -1
- package/dist/actors/Barrier.d.ts +0 -60
- package/dist/actors/Barrier.d.ts.map +0 -1
- package/dist/actors/Barrier.js +0 -70
- package/dist/actors/Barrier.js.map +0 -1
- package/dist/actors/Charges.d.ts +0 -66
- package/dist/actors/Charges.d.ts.map +0 -1
- package/dist/actors/Charges.js +0 -61
- package/dist/actors/Charges.js.map +0 -1
- package/dist/actors/EntityTemplate.d.ts +0 -127
- package/dist/actors/EntityTemplate.d.ts.map +0 -1
- package/dist/actors/EntityTemplate.js +0 -117
- package/dist/actors/EntityTemplate.js.map +0 -1
- package/dist/actors/Equipment.d.ts +0 -88
- package/dist/actors/Equipment.d.ts.map +0 -1
- package/dist/actors/Equipment.js +0 -107
- package/dist/actors/Equipment.js.map +0 -1
- package/dist/actors/Inventory.d.ts +0 -123
- package/dist/actors/Inventory.d.ts.map +0 -1
- package/dist/actors/Inventory.js +0 -165
- package/dist/actors/Inventory.js.map +0 -1
- package/dist/actors/ItemState.d.ts +0 -43
- package/dist/actors/ItemState.d.ts.map +0 -1
- package/dist/actors/ItemState.js +0 -63
- package/dist/actors/ItemState.js.map +0 -1
- package/dist/actors/ItemStatusEffect.d.ts +0 -40
- package/dist/actors/ItemStatusEffect.d.ts.map +0 -1
- package/dist/actors/ItemStatusEffect.js +0 -39
- package/dist/actors/ItemStatusEffect.js.map +0 -1
- package/dist/actors/Loot.d.ts +0 -38
- package/dist/actors/Loot.d.ts.map +0 -1
- package/dist/actors/Loot.js +0 -28
- package/dist/actors/Loot.js.map +0 -1
- package/dist/actors/Progression.d.ts +0 -52
- package/dist/actors/Progression.d.ts.map +0 -1
- package/dist/actors/Progression.js +0 -59
- package/dist/actors/Progression.js.map +0 -1
- package/dist/actors/Resource.d.ts +0 -53
- package/dist/actors/Resource.d.ts.map +0 -1
- package/dist/actors/Resource.js +0 -57
- package/dist/actors/Resource.js.map +0 -1
- package/dist/actors/Scaling.d.ts +0 -30
- package/dist/actors/Scaling.d.ts.map +0 -1
- package/dist/actors/Scaling.js +0 -9
- package/dist/actors/Scaling.js.map +0 -1
- package/dist/actors/Shop.d.ts +0 -40
- package/dist/actors/Shop.d.ts.map +0 -1
- package/dist/actors/Shop.js +0 -36
- package/dist/actors/Shop.js.map +0 -1
- package/dist/actors/SkillPoints.d.ts +0 -72
- package/dist/actors/SkillPoints.d.ts.map +0 -1
- package/dist/actors/SkillPoints.js +0 -87
- package/dist/actors/SkillPoints.js.map +0 -1
- package/dist/actors/StatBlock.d.ts +0 -86
- package/dist/actors/StatBlock.d.ts.map +0 -1
- package/dist/actors/StatBlock.js +0 -110
- package/dist/actors/StatBlock.js.map +0 -1
- package/dist/actors/StatusEffect.d.ts +0 -67
- package/dist/actors/StatusEffect.d.ts.map +0 -1
- package/dist/actors/StatusEffect.js +0 -59
- package/dist/actors/StatusEffect.js.map +0 -1
- package/dist/actors/Support.d.ts +0 -43
- package/dist/actors/Support.d.ts.map +0 -1
- package/dist/actors/Support.js +0 -71
- package/dist/actors/Support.js.map +0 -1
- package/dist/actors/Traits.d.ts +0 -43
- package/dist/actors/Traits.d.ts.map +0 -1
- package/dist/actors/Traits.js +0 -35
- package/dist/actors/Traits.js.map +0 -1
- package/dist/actors/craft.d.ts +0 -63
- package/dist/actors/craft.d.ts.map +0 -1
- package/dist/actors/craft.js +0 -86
- package/dist/actors/craft.js.map +0 -1
- package/dist/actors/index.d.ts +0 -46
- package/dist/actors/index.d.ts.map +0 -1
- package/dist/actors/index.js +0 -24
- package/dist/actors/index.js.map +0 -1
- package/dist/actors/skillCheck.d.ts +0 -21
- package/dist/actors/skillCheck.d.ts.map +0 -1
- package/dist/actors/skillCheck.js +0 -24
- package/dist/actors/skillCheck.js.map +0 -1
- package/dist/ai/Heuristics.d.ts +0 -240
- package/dist/ai/Heuristics.d.ts.map +0 -1
- package/dist/ai/Heuristics.js +0 -298
- package/dist/ai/Heuristics.js.map +0 -1
- package/dist/ai/Neural.d.ts +0 -65
- package/dist/ai/Neural.d.ts.map +0 -1
- package/dist/ai/Neural.js +0 -169
- package/dist/ai/Neural.js.map +0 -1
- package/dist/ai/Suggest.d.ts +0 -54
- package/dist/ai/Suggest.d.ts.map +0 -1
- package/dist/ai/Suggest.js +0 -48
- package/dist/ai/Suggest.js.map +0 -1
- package/dist/ai/index.d.ts +0 -136
- package/dist/ai/index.d.ts.map +0 -1
- package/dist/ai/index.js +0 -207
- package/dist/ai/index.js.map +0 -1
- package/dist/ai/lua.d.ts +0 -74
- package/dist/ai/lua.d.ts.map +0 -1
- package/dist/ai/lua.js +0 -217
- package/dist/ai/lua.js.map +0 -1
- package/dist/ai/score.d.ts +0 -162
- package/dist/ai/score.d.ts.map +0 -1
- package/dist/ai/score.js +0 -147
- package/dist/ai/score.js.map +0 -1
- package/dist/ai/search.d.ts +0 -108
- package/dist/ai/search.d.ts.map +0 -1
- package/dist/ai/search.js +0 -148
- package/dist/ai/search.js.map +0 -1
- package/dist/assets/ByteProgress.d.ts +0 -37
- package/dist/assets/ByteProgress.d.ts.map +0 -1
- package/dist/assets/ByteProgress.js +0 -54
- package/dist/assets/ByteProgress.js.map +0 -1
- package/dist/assets/Streaming.d.ts +0 -56
- package/dist/assets/Streaming.d.ts.map +0 -1
- package/dist/assets/Streaming.js +0 -100
- package/dist/assets/Streaming.js.map +0 -1
- package/dist/assets/SvgParts.d.ts +0 -31
- package/dist/assets/SvgParts.d.ts.map +0 -1
- package/dist/assets/SvgParts.js +0 -54
- package/dist/assets/SvgParts.js.map +0 -1
- package/dist/assets/SvgSource.d.ts +0 -3
- package/dist/assets/SvgSource.d.ts.map +0 -1
- package/dist/assets/SvgSource.js +0 -22
- package/dist/assets/SvgSource.js.map +0 -1
- package/dist/assets/binary.d.ts +0 -52
- package/dist/assets/binary.d.ts.map +0 -1
- package/dist/assets/binary.js +0 -57
- package/dist/assets/binary.js.map +0 -1
- package/dist/assets/index.d.ts +0 -27
- package/dist/assets/index.d.ts.map +0 -1
- package/dist/assets/index.js +0 -20
- package/dist/assets/index.js.map +0 -1
- package/dist/assets/loader.d.ts +0 -70
- package/dist/assets/loader.d.ts.map +0 -1
- package/dist/assets/loader.js +0 -115
- package/dist/assets/loader.js.map +0 -1
- package/dist/assets/paths.d.ts +0 -73
- package/dist/assets/paths.d.ts.map +0 -1
- package/dist/assets/paths.js +0 -91
- package/dist/assets/paths.js.map +0 -1
- package/dist/assets/svg.d.ts +0 -87
- package/dist/assets/svg.d.ts.map +0 -1
- package/dist/assets/svg.js +0 -166
- package/dist/assets/svg.js.map +0 -1
- package/dist/audio/AdaptiveMusic.d.ts +0 -85
- package/dist/audio/AdaptiveMusic.d.ts.map +0 -1
- package/dist/audio/AdaptiveMusic.js +0 -230
- package/dist/audio/AdaptiveMusic.js.map +0 -1
- package/dist/audio/AudioLoader.d.ts +0 -33
- package/dist/audio/AudioLoader.d.ts.map +0 -1
- package/dist/audio/AudioLoader.js +0 -58
- package/dist/audio/AudioLoader.js.map +0 -1
- package/dist/audio/AudioViews.d.ts +0 -70
- package/dist/audio/AudioViews.d.ts.map +0 -1
- package/dist/audio/AudioViews.js +0 -119
- package/dist/audio/AudioViews.js.map +0 -1
- package/dist/audio/BusBudget.d.ts +0 -89
- package/dist/audio/BusBudget.d.ts.map +0 -1
- package/dist/audio/BusBudget.js +0 -120
- package/dist/audio/BusBudget.js.map +0 -1
- package/dist/audio/Captions.d.ts +0 -27
- package/dist/audio/Captions.d.ts.map +0 -1
- package/dist/audio/Captions.js +0 -16
- package/dist/audio/Captions.js.map +0 -1
- package/dist/audio/Channels.d.ts +0 -282
- package/dist/audio/Channels.d.ts.map +0 -1
- package/dist/audio/Channels.js +0 -573
- package/dist/audio/Channels.js.map +0 -1
- package/dist/audio/CoreHost.d.ts +0 -114
- package/dist/audio/CoreHost.d.ts.map +0 -1
- package/dist/audio/CoreHost.js +0 -335
- package/dist/audio/CoreHost.js.map +0 -1
- package/dist/audio/DecoderGuard.d.ts +0 -139
- package/dist/audio/DecoderGuard.d.ts.map +0 -1
- package/dist/audio/DecoderGuard.js +0 -208
- package/dist/audio/DecoderGuard.js.map +0 -1
- package/dist/audio/Fft.d.ts +0 -3
- package/dist/audio/Fft.d.ts.map +0 -1
- package/dist/audio/Fft.js +0 -45
- package/dist/audio/Fft.js.map +0 -1
- package/dist/audio/LoopTags.d.ts +0 -55
- package/dist/audio/LoopTags.d.ts.map +0 -1
- package/dist/audio/LoopTags.js +0 -136
- package/dist/audio/LoopTags.js.map +0 -1
- package/dist/audio/Midi.d.ts +0 -219
- package/dist/audio/Midi.d.ts.map +0 -1
- package/dist/audio/Midi.js +0 -409
- package/dist/audio/Midi.js.map +0 -1
- package/dist/audio/MidiRender.d.ts +0 -144
- package/dist/audio/MidiRender.d.ts.map +0 -1
- package/dist/audio/MidiRender.js +0 -448
- package/dist/audio/MidiRender.js.map +0 -1
- package/dist/audio/MidiSynth.d.ts +0 -147
- package/dist/audio/MidiSynth.d.ts.map +0 -1
- package/dist/audio/MidiSynth.js +0 -205
- package/dist/audio/MidiSynth.js.map +0 -1
- package/dist/audio/Music.d.ts +0 -70
- package/dist/audio/Music.d.ts.map +0 -1
- package/dist/audio/Music.js +0 -191
- package/dist/audio/Music.js.map +0 -1
- package/dist/audio/MusicPlayer.d.ts +0 -80
- package/dist/audio/MusicPlayer.d.ts.map +0 -1
- package/dist/audio/MusicPlayer.js +0 -147
- package/dist/audio/MusicPlayer.js.map +0 -1
- package/dist/audio/Orchestrator.d.ts +0 -58
- package/dist/audio/Orchestrator.d.ts.map +0 -1
- package/dist/audio/Orchestrator.js +0 -74
- package/dist/audio/Orchestrator.js.map +0 -1
- package/dist/audio/Playable.d.ts +0 -38
- package/dist/audio/Playable.d.ts.map +0 -1
- package/dist/audio/Playable.js +0 -29
- package/dist/audio/Playable.js.map +0 -1
- package/dist/audio/Positional.d.ts +0 -133
- package/dist/audio/Positional.d.ts.map +0 -1
- package/dist/audio/Positional.js +0 -138
- package/dist/audio/Positional.js.map +0 -1
- package/dist/audio/Resample.d.ts +0 -61
- package/dist/audio/Resample.d.ts.map +0 -1
- package/dist/audio/Resample.js +0 -97
- package/dist/audio/Resample.js.map +0 -1
- package/dist/audio/SampleDecoder.d.ts +0 -55
- package/dist/audio/SampleDecoder.d.ts.map +0 -1
- package/dist/audio/SampleDecoder.js +0 -74
- package/dist/audio/SampleDecoder.js.map +0 -1
- package/dist/audio/Settings.d.ts +0 -99
- package/dist/audio/Settings.d.ts.map +0 -1
- package/dist/audio/Settings.js +0 -134
- package/dist/audio/Settings.js.map +0 -1
- package/dist/audio/Sfx.d.ts +0 -148
- package/dist/audio/Sfx.d.ts.map +0 -1
- package/dist/audio/Sfx.js +0 -213
- package/dist/audio/Sfx.js.map +0 -1
- package/dist/audio/Sound.d.ts +0 -57
- package/dist/audio/Sound.d.ts.map +0 -1
- package/dist/audio/Sound.js +0 -79
- package/dist/audio/Sound.js.map +0 -1
- package/dist/audio/SoundFont.d.ts +0 -192
- package/dist/audio/SoundFont.d.ts.map +0 -1
- package/dist/audio/SoundFont.js +0 -862
- package/dist/audio/SoundFont.js.map +0 -1
- package/dist/audio/SpectralDistance.d.ts +0 -34
- package/dist/audio/SpectralDistance.d.ts.map +0 -1
- package/dist/audio/SpectralDistance.js +0 -64
- package/dist/audio/SpectralDistance.js.map +0 -1
- package/dist/audio/StreamChannel.d.ts +0 -150
- package/dist/audio/StreamChannel.d.ts.map +0 -1
- package/dist/audio/StreamChannel.js +0 -390
- package/dist/audio/StreamChannel.js.map +0 -1
- package/dist/audio/StreamPlayable.d.ts +0 -73
- package/dist/audio/StreamPlayable.d.ts.map +0 -1
- package/dist/audio/StreamPlayable.js +0 -130
- package/dist/audio/StreamPlayable.js.map +0 -1
- package/dist/audio/Synth.d.ts +0 -64
- package/dist/audio/Synth.d.ts.map +0 -1
- package/dist/audio/Synth.js +0 -133
- package/dist/audio/Synth.js.map +0 -1
- package/dist/audio/SyxBank.d.ts +0 -73
- package/dist/audio/SyxBank.d.ts.map +0 -1
- package/dist/audio/SyxBank.js +0 -130
- package/dist/audio/SyxBank.js.map +0 -1
- package/dist/audio/Underrun.d.ts +0 -25
- package/dist/audio/Underrun.d.ts.map +0 -1
- package/dist/audio/Underrun.js +0 -18
- package/dist/audio/Underrun.js.map +0 -1
- package/dist/audio/Wav.d.ts +0 -56
- package/dist/audio/Wav.d.ts.map +0 -1
- package/dist/audio/Wav.js +0 -164
- package/dist/audio/Wav.js.map +0 -1
- package/dist/audio/WebMidi.d.ts +0 -58
- package/dist/audio/WebMidi.d.ts.map +0 -1
- package/dist/audio/WebMidi.js +0 -79
- package/dist/audio/WebMidi.js.map +0 -1
- package/dist/audio/humanize/Groove.d.ts +0 -80
- package/dist/audio/humanize/Groove.d.ts.map +0 -1
- package/dist/audio/humanize/Groove.js +0 -102
- package/dist/audio/humanize/Groove.js.map +0 -1
- package/dist/audio/humanize/GrooveConverter.d.ts +0 -49
- package/dist/audio/humanize/GrooveConverter.d.ts.map +0 -1
- package/dist/audio/humanize/GrooveConverter.js +0 -344
- package/dist/audio/humanize/GrooveConverter.js.map +0 -1
- package/dist/audio/humanize/GrooveExtractor.d.ts +0 -49
- package/dist/audio/humanize/GrooveExtractor.d.ts.map +0 -1
- package/dist/audio/humanize/GrooveExtractor.js +0 -179
- package/dist/audio/humanize/GrooveExtractor.js.map +0 -1
- package/dist/audio/humanize/GrooveHumanizer.d.ts +0 -34
- package/dist/audio/humanize/GrooveHumanizer.d.ts.map +0 -1
- package/dist/audio/humanize/GrooveHumanizer.js +0 -37
- package/dist/audio/humanize/GrooveHumanizer.js.map +0 -1
- package/dist/audio/humanize/Humanize.d.ts +0 -54
- package/dist/audio/humanize/Humanize.d.ts.map +0 -1
- package/dist/audio/humanize/Humanize.js +0 -239
- package/dist/audio/humanize/Humanize.js.map +0 -1
- package/dist/audio/humanize/HumanizerFactory.d.ts +0 -68
- package/dist/audio/humanize/HumanizerFactory.d.ts.map +0 -1
- package/dist/audio/humanize/HumanizerFactory.js +0 -84
- package/dist/audio/humanize/HumanizerFactory.js.map +0 -1
- package/dist/audio/humanize/LiteHumanizer.d.ts +0 -30
- package/dist/audio/humanize/LiteHumanizer.d.ts.map +0 -1
- package/dist/audio/humanize/LiteHumanizer.js +0 -35
- package/dist/audio/humanize/LiteHumanizer.js.map +0 -1
- package/dist/audio/humanize/Onsets.d.ts +0 -26
- package/dist/audio/humanize/Onsets.d.ts.map +0 -1
- package/dist/audio/humanize/Onsets.js +0 -121
- package/dist/audio/humanize/Onsets.js.map +0 -1
- package/dist/audio/index.d.ts +0 -75
- package/dist/audio/index.d.ts.map +0 -1
- package/dist/audio/index.js +0 -38
- package/dist/audio/index.js.map +0 -1
- package/dist/battle/AttackDialog.d.ts +0 -75
- package/dist/battle/AttackDialog.d.ts.map +0 -1
- package/dist/battle/AttackDialog.js +0 -115
- package/dist/battle/AttackDialog.js.map +0 -1
- package/dist/battle/AttackPreview.d.ts +0 -70
- package/dist/battle/AttackPreview.d.ts.map +0 -1
- package/dist/battle/AttackPreview.js +0 -78
- package/dist/battle/AttackPreview.js.map +0 -1
- package/dist/battle/BattleAI.d.ts +0 -40
- package/dist/battle/BattleAI.d.ts.map +0 -1
- package/dist/battle/BattleAI.js +0 -63
- package/dist/battle/BattleAI.js.map +0 -1
- package/dist/battle/BattleStats.d.ts +0 -45
- package/dist/battle/BattleStats.d.ts.map +0 -1
- package/dist/battle/BattleStats.js +0 -63
- package/dist/battle/BattleStats.js.map +0 -1
- package/dist/battle/Evolution.d.ts +0 -34
- package/dist/battle/Evolution.d.ts.map +0 -1
- package/dist/battle/Evolution.js +0 -37
- package/dist/battle/Evolution.js.map +0 -1
- package/dist/battle/Field.d.ts +0 -36
- package/dist/battle/Field.d.ts.map +0 -1
- package/dist/battle/Field.js +0 -31
- package/dist/battle/Field.js.map +0 -1
- package/dist/battle/Hooks.d.ts +0 -39
- package/dist/battle/Hooks.d.ts.map +0 -1
- package/dist/battle/Hooks.js +0 -38
- package/dist/battle/Hooks.js.map +0 -1
- package/dist/battle/Move.d.ts +0 -45
- package/dist/battle/Move.d.ts.map +0 -1
- package/dist/battle/Move.js +0 -23
- package/dist/battle/Move.js.map +0 -1
- package/dist/battle/Party.d.ts +0 -32
- package/dist/battle/Party.d.ts.map +0 -1
- package/dist/battle/Party.js +0 -62
- package/dist/battle/Party.js.map +0 -1
- package/dist/battle/Species.d.ts +0 -50
- package/dist/battle/Species.d.ts.map +0 -1
- package/dist/battle/Species.js +0 -41
- package/dist/battle/Species.js.map +0 -1
- package/dist/battle/StatStages.d.ts +0 -52
- package/dist/battle/StatStages.d.ts.map +0 -1
- package/dist/battle/StatStages.js +0 -51
- package/dist/battle/StatStages.js.map +0 -1
- package/dist/battle/TypeMatrix.d.ts +0 -25
- package/dist/battle/TypeMatrix.d.ts.map +0 -1
- package/dist/battle/TypeMatrix.js +0 -35
- package/dist/battle/TypeMatrix.js.map +0 -1
- package/dist/battle/UnitSelector.d.ts +0 -72
- package/dist/battle/UnitSelector.d.ts.map +0 -1
- package/dist/battle/UnitSelector.js +0 -117
- package/dist/battle/UnitSelector.js.map +0 -1
- package/dist/battle/Whiteboard.d.ts +0 -50
- package/dist/battle/Whiteboard.d.ts.map +0 -1
- package/dist/battle/Whiteboard.js +0 -94
- package/dist/battle/Whiteboard.js.map +0 -1
- package/dist/battle/index.d.ts +0 -26
- package/dist/battle/index.d.ts.map +0 -1
- package/dist/battle/index.js +0 -15
- package/dist/battle/index.js.map +0 -1
- package/dist/board/Army.d.ts +0 -92
- package/dist/board/Army.d.ts.map +0 -1
- package/dist/board/Army.js +0 -123
- package/dist/board/Army.js.map +0 -1
- package/dist/board/Classics.d.ts +0 -419
- package/dist/board/Classics.d.ts.map +0 -1
- package/dist/board/Classics.js +0 -754
- package/dist/board/Classics.js.map +0 -1
- package/dist/board/Engine.d.ts +0 -95
- package/dist/board/Engine.d.ts.map +0 -1
- package/dist/board/Engine.js +0 -545
- package/dist/board/Engine.js.map +0 -1
- package/dist/board/FogOfWar.d.ts +0 -79
- package/dist/board/FogOfWar.d.ts.map +0 -1
- package/dist/board/FogOfWar.js +0 -150
- package/dist/board/FogOfWar.js.map +0 -1
- package/dist/board/HexSkirmish.d.ts +0 -213
- package/dist/board/HexSkirmish.d.ts.map +0 -1
- package/dist/board/HexSkirmish.js +0 -268
- package/dist/board/HexSkirmish.js.map +0 -1
- package/dist/board/Tactics.d.ts +0 -212
- package/dist/board/Tactics.d.ts.map +0 -1
- package/dist/board/Tactics.js +0 -303
- package/dist/board/Tactics.js.map +0 -1
- package/dist/board/bitboard.d.ts +0 -132
- package/dist/board/bitboard.d.ts.map +0 -1
- package/dist/board/bitboard.js +0 -495
- package/dist/board/bitboard.js.map +0 -1
- package/dist/board/chess.d.ts +0 -167
- package/dist/board/chess.d.ts.map +0 -1
- package/dist/board/chess.js +0 -578
- package/dist/board/chess.js.map +0 -1
- package/dist/board/index.d.ts +0 -23
- package/dist/board/index.d.ts.map +0 -1
- package/dist/board/index.js +0 -12
- package/dist/board/index.js.map +0 -1
- package/dist/board/openings.d.ts +0 -58
- package/dist/board/openings.d.ts.map +0 -1
- package/dist/board/openings.js +0 -45
- package/dist/board/openings.js.map +0 -1
- package/dist/board/tablebase.d.ts +0 -118
- package/dist/board/tablebase.d.ts.map +0 -1
- package/dist/board/tablebase.js +0 -414
- package/dist/board/tablebase.js.map +0 -1
- package/dist/board/tourney.d.ts +0 -97
- package/dist/board/tourney.d.ts.map +0 -1
- package/dist/board/tourney.js +0 -1002
- package/dist/board/tourney.js.map +0 -1
- package/dist/core/Achievements.d.ts +0 -101
- package/dist/core/Achievements.d.ts.map +0 -1
- package/dist/core/Achievements.js +0 -141
- package/dist/core/Achievements.js.map +0 -1
- package/dist/core/ActionJournal.d.ts +0 -43
- package/dist/core/ActionJournal.d.ts.map +0 -1
- package/dist/core/ActionJournal.js +0 -77
- package/dist/core/ActionJournal.js.map +0 -1
- package/dist/core/Blob.d.ts +0 -79
- package/dist/core/Blob.d.ts.map +0 -1
- package/dist/core/Blob.js +0 -140
- package/dist/core/Blob.js.map +0 -1
- package/dist/core/Clone.d.ts +0 -31
- package/dist/core/Clone.d.ts.map +0 -1
- package/dist/core/Clone.js +0 -84
- package/dist/core/Clone.js.map +0 -1
- package/dist/core/Collection.d.ts +0 -59
- package/dist/core/Collection.d.ts.map +0 -1
- package/dist/core/Collection.js +0 -77
- package/dist/core/Collection.js.map +0 -1
- package/dist/core/Csv.d.ts +0 -74
- package/dist/core/Csv.d.ts.map +0 -1
- package/dist/core/Csv.js +0 -201
- package/dist/core/Csv.js.map +0 -1
- package/dist/core/DialogueText.d.ts +0 -72
- package/dist/core/DialogueText.d.ts.map +0 -1
- package/dist/core/DialogueText.js +0 -68
- package/dist/core/DialogueText.js.map +0 -1
- package/dist/core/Entity.d.ts +0 -42
- package/dist/core/Entity.d.ts.map +0 -1
- package/dist/core/Entity.js +0 -61
- package/dist/core/Entity.js.map +0 -1
- package/dist/core/Feedback.d.ts +0 -27
- package/dist/core/Feedback.d.ts.map +0 -1
- package/dist/core/Feedback.js +0 -33
- package/dist/core/Feedback.js.map +0 -1
- package/dist/core/FixedStepper.d.ts +0 -38
- package/dist/core/FixedStepper.d.ts.map +0 -1
- package/dist/core/FixedStepper.js +0 -56
- package/dist/core/FixedStepper.js.map +0 -1
- package/dist/core/Grid.d.ts +0 -179
- package/dist/core/Grid.d.ts.map +0 -1
- package/dist/core/Grid.js +0 -201
- package/dist/core/Grid.js.map +0 -1
- package/dist/core/Handles.d.ts +0 -42
- package/dist/core/Handles.d.ts.map +0 -1
- package/dist/core/Handles.js +0 -38
- package/dist/core/Handles.js.map +0 -1
- package/dist/core/Hex.d.ts +0 -79
- package/dist/core/Hex.d.ts.map +0 -1
- package/dist/core/Hex.js +0 -161
- package/dist/core/Hex.js.map +0 -1
- package/dist/core/Hooks.d.ts +0 -48
- package/dist/core/Hooks.d.ts.map +0 -1
- package/dist/core/Hooks.js +0 -33
- package/dist/core/Hooks.js.map +0 -1
- package/dist/core/HttpTransport.d.ts +0 -53
- package/dist/core/HttpTransport.d.ts.map +0 -1
- package/dist/core/HttpTransport.js +0 -108
- package/dist/core/HttpTransport.js.map +0 -1
- package/dist/core/Input.d.ts +0 -256
- package/dist/core/Input.d.ts.map +0 -1
- package/dist/core/Input.js +0 -557
- package/dist/core/Input.js.map +0 -1
- package/dist/core/JavaRandom.d.ts +0 -55
- package/dist/core/JavaRandom.d.ts.map +0 -1
- package/dist/core/JavaRandom.js +0 -81
- package/dist/core/JavaRandom.js.map +0 -1
- package/dist/core/Loading.d.ts +0 -65
- package/dist/core/Loading.d.ts.map +0 -1
- package/dist/core/Loading.js +0 -119
- package/dist/core/Loading.js.map +0 -1
- package/dist/core/Log.d.ts +0 -48
- package/dist/core/Log.d.ts.map +0 -1
- package/dist/core/Log.js +0 -59
- package/dist/core/Log.js.map +0 -1
- package/dist/core/Math.d.ts +0 -14
- package/dist/core/Math.d.ts.map +0 -1
- package/dist/core/Math.js +0 -16
- package/dist/core/Math.js.map +0 -1
- package/dist/core/Motion.d.ts +0 -47
- package/dist/core/Motion.d.ts.map +0 -1
- package/dist/core/Motion.js +0 -122
- package/dist/core/Motion.js.map +0 -1
- package/dist/core/Multiplayer.d.ts +0 -101
- package/dist/core/Multiplayer.d.ts.map +0 -1
- package/dist/core/Multiplayer.js +0 -156
- package/dist/core/Multiplayer.js.map +0 -1
- package/dist/core/News.d.ts +0 -51
- package/dist/core/News.d.ts.map +0 -1
- package/dist/core/News.js +0 -65
- package/dist/core/News.js.map +0 -1
- package/dist/core/Pathfinding.d.ts +0 -41
- package/dist/core/Pathfinding.d.ts.map +0 -1
- package/dist/core/Pathfinding.js +0 -86
- package/dist/core/Pathfinding.js.map +0 -1
- package/dist/core/PlayerInput.d.ts +0 -57
- package/dist/core/PlayerInput.d.ts.map +0 -1
- package/dist/core/PlayerInput.js +0 -82
- package/dist/core/PlayerInput.js.map +0 -1
- package/dist/core/Presentation.d.ts +0 -56
- package/dist/core/Presentation.d.ts.map +0 -1
- package/dist/core/Presentation.js +0 -78
- package/dist/core/Presentation.js.map +0 -1
- package/dist/core/Random.d.ts +0 -259
- package/dist/core/Random.d.ts.map +0 -1
- package/dist/core/Random.js +0 -408
- package/dist/core/Random.js.map +0 -1
- package/dist/core/Reactions.d.ts +0 -67
- package/dist/core/Reactions.d.ts.map +0 -1
- package/dist/core/Reactions.js +0 -92
- package/dist/core/Reactions.js.map +0 -1
- package/dist/core/Registry.d.ts +0 -31
- package/dist/core/Registry.d.ts.map +0 -1
- package/dist/core/Registry.js +0 -46
- package/dist/core/Registry.js.map +0 -1
- package/dist/core/Replay.d.ts +0 -126
- package/dist/core/Replay.d.ts.map +0 -1
- package/dist/core/Replay.js +0 -162
- package/dist/core/Replay.js.map +0 -1
- package/dist/core/ReplayFile.d.ts +0 -197
- package/dist/core/ReplayFile.d.ts.map +0 -1
- package/dist/core/ReplayFile.js +0 -257
- package/dist/core/ReplayFile.js.map +0 -1
- package/dist/core/RunHistory.d.ts +0 -54
- package/dist/core/RunHistory.d.ts.map +0 -1
- package/dist/core/RunHistory.js +0 -40
- package/dist/core/RunHistory.js.map +0 -1
- package/dist/core/Sanitize.d.ts +0 -101
- package/dist/core/Sanitize.d.ts.map +0 -1
- package/dist/core/Sanitize.js +0 -162
- package/dist/core/Sanitize.js.map +0 -1
- package/dist/core/Save.d.ts +0 -123
- package/dist/core/Save.d.ts.map +0 -1
- package/dist/core/Save.js +0 -216
- package/dist/core/Save.js.map +0 -1
- package/dist/core/SaveSync.d.ts +0 -43
- package/dist/core/SaveSync.d.ts.map +0 -1
- package/dist/core/SaveSync.js +0 -56
- package/dist/core/SaveSync.js.map +0 -1
- package/dist/core/Scene.d.ts +0 -63
- package/dist/core/Scene.d.ts.map +0 -1
- package/dist/core/Scene.js +0 -81
- package/dist/core/Scene.js.map +0 -1
- package/dist/core/SceneComponents.d.ts +0 -67
- package/dist/core/SceneComponents.d.ts.map +0 -1
- package/dist/core/SceneComponents.js +0 -76
- package/dist/core/SceneComponents.js.map +0 -1
- package/dist/core/SceneStack.d.ts +0 -61
- package/dist/core/SceneStack.d.ts.map +0 -1
- package/dist/core/SceneStack.js +0 -91
- package/dist/core/SceneStack.js.map +0 -1
- package/dist/core/Scramble.d.ts +0 -21
- package/dist/core/Scramble.d.ts.map +0 -1
- package/dist/core/Scramble.js +0 -52
- package/dist/core/Scramble.js.map +0 -1
- package/dist/core/Session.d.ts +0 -31
- package/dist/core/Session.d.ts.map +0 -1
- package/dist/core/Session.js +0 -11
- package/dist/core/Session.js.map +0 -1
- package/dist/core/Settings.d.ts +0 -96
- package/dist/core/Settings.d.ts.map +0 -1
- package/dist/core/Settings.js +0 -190
- package/dist/core/Settings.js.map +0 -1
- package/dist/core/Signal.d.ts +0 -35
- package/dist/core/Signal.d.ts.map +0 -1
- package/dist/core/Signal.js +0 -41
- package/dist/core/Signal.js.map +0 -1
- package/dist/core/Spawner.d.ts +0 -65
- package/dist/core/Spawner.d.ts.map +0 -1
- package/dist/core/Spawner.js +0 -82
- package/dist/core/Spawner.js.map +0 -1
- package/dist/core/State.d.ts +0 -97
- package/dist/core/State.d.ts.map +0 -1
- package/dist/core/State.js +0 -177
- package/dist/core/State.js.map +0 -1
- package/dist/core/Stats.d.ts +0 -46
- package/dist/core/Stats.d.ts.map +0 -1
- package/dist/core/Stats.js +0 -47
- package/dist/core/Stats.js.map +0 -1
- package/dist/core/StoredValue.d.ts +0 -30
- package/dist/core/StoredValue.d.ts.map +0 -1
- package/dist/core/StoredValue.js +0 -38
- package/dist/core/StoredValue.js.map +0 -1
- package/dist/core/SyncGuard.d.ts +0 -57
- package/dist/core/SyncGuard.d.ts.map +0 -1
- package/dist/core/SyncGuard.js +0 -116
- package/dist/core/SyncGuard.js.map +0 -1
- package/dist/core/Telemetry.d.ts +0 -63
- package/dist/core/Telemetry.d.ts.map +0 -1
- package/dist/core/Telemetry.js +0 -83
- package/dist/core/Telemetry.js.map +0 -1
- package/dist/core/Twee.d.ts +0 -101
- package/dist/core/Twee.d.ts.map +0 -1
- package/dist/core/Twee.js +0 -174
- package/dist/core/Twee.js.map +0 -1
- package/dist/core/Tween.d.ts +0 -60
- package/dist/core/Tween.d.ts.map +0 -1
- package/dist/core/Tween.js +0 -98
- package/dist/core/Tween.js.map +0 -1
- package/dist/core/UndoHistory.d.ts +0 -52
- package/dist/core/UndoHistory.d.ts.map +0 -1
- package/dist/core/UndoHistory.js +0 -49
- package/dist/core/UndoHistory.js.map +0 -1
- package/dist/core/index.d.ts +0 -94
- package/dist/core/index.d.ts.map +0 -1
- package/dist/core/index.js +0 -53
- package/dist/core/index.js.map +0 -1
- package/dist/headless/index.d.ts +0 -87
- package/dist/headless/index.d.ts.map +0 -1
- package/dist/headless/index.js +0 -87
- package/dist/headless/index.js.map +0 -1
- package/dist/i18n/Content.d.ts +0 -151
- package/dist/i18n/Content.d.ts.map +0 -1
- package/dist/i18n/Content.js +0 -218
- package/dist/i18n/Content.js.map +0 -1
- package/dist/i18n/EditSession.d.ts +0 -101
- package/dist/i18n/EditSession.d.ts.map +0 -1
- package/dist/i18n/EditSession.js +0 -150
- package/dist/i18n/EditSession.js.map +0 -1
- package/dist/i18n/Fluent.d.ts +0 -7
- package/dist/i18n/Fluent.d.ts.map +0 -1
- package/dist/i18n/Fluent.js +0 -98
- package/dist/i18n/Fluent.js.map +0 -1
- package/dist/i18n/Format.d.ts +0 -25
- package/dist/i18n/Format.d.ts.map +0 -1
- package/dist/i18n/Format.js +0 -32
- package/dist/i18n/Format.js.map +0 -1
- package/dist/i18n/FormatSpec.d.ts +0 -76
- package/dist/i18n/FormatSpec.d.ts.map +0 -1
- package/dist/i18n/FormatSpec.js +0 -306
- package/dist/i18n/FormatSpec.js.map +0 -1
- package/dist/i18n/Po.d.ts +0 -54
- package/dist/i18n/Po.d.ts.map +0 -1
- package/dist/i18n/Po.js +0 -192
- package/dist/i18n/Po.js.map +0 -1
- package/dist/i18n/SemanticMessage.d.ts +0 -84
- package/dist/i18n/SemanticMessage.d.ts.map +0 -1
- package/dist/i18n/SemanticMessage.js +0 -54
- package/dist/i18n/SemanticMessage.js.map +0 -1
- package/dist/i18n/SoundMarkers.d.ts +0 -38
- package/dist/i18n/SoundMarkers.d.ts.map +0 -1
- package/dist/i18n/SoundMarkers.js +0 -48
- package/dist/i18n/SoundMarkers.js.map +0 -1
- package/dist/i18n/Validate.d.ts +0 -82
- package/dist/i18n/Validate.d.ts.map +0 -1
- package/dist/i18n/Validate.js +0 -106
- package/dist/i18n/Validate.js.map +0 -1
- package/dist/i18n/index.d.ts +0 -177
- package/dist/i18n/index.d.ts.map +0 -1
- package/dist/i18n/index.js +0 -331
- package/dist/i18n/index.js.map +0 -1
- package/dist/index.d.ts +0 -26
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js +0 -26
- package/dist/index.js.map +0 -1
- package/dist/mw_games.global.js +0 -1410
- package/dist/mwl/MapFile.d.ts +0 -41
- package/dist/mwl/MapFile.d.ts.map +0 -1
- package/dist/mwl/MapFile.js +0 -53
- package/dist/mwl/MapFile.js.map +0 -1
- package/dist/mwl/actors.d.ts +0 -62
- package/dist/mwl/actors.d.ts.map +0 -1
- package/dist/mwl/actors.js +0 -82
- package/dist/mwl/actors.js.map +0 -1
- package/dist/mwl/campaign.d.ts +0 -51
- package/dist/mwl/campaign.d.ts.map +0 -1
- package/dist/mwl/campaign.js +0 -58
- package/dist/mwl/campaign.js.map +0 -1
- package/dist/mwl/carryover.d.ts +0 -86
- package/dist/mwl/carryover.d.ts.map +0 -1
- package/dist/mwl/carryover.js +0 -70
- package/dist/mwl/carryover.js.map +0 -1
- package/dist/mwl/catalog.d.ts +0 -98
- package/dist/mwl/catalog.d.ts.map +0 -1
- package/dist/mwl/catalog.js +0 -259
- package/dist/mwl/catalog.js.map +0 -1
- package/dist/mwl/compiler.d.ts +0 -135
- package/dist/mwl/compiler.d.ts.map +0 -1
- package/dist/mwl/compiler.js +0 -216
- package/dist/mwl/compiler.js.map +0 -1
- package/dist/mwl/conditions.d.ts +0 -30
- package/dist/mwl/conditions.d.ts.map +0 -1
- package/dist/mwl/conditions.js +0 -212
- package/dist/mwl/conditions.js.map +0 -1
- package/dist/mwl/content.d.ts +0 -140
- package/dist/mwl/content.d.ts.map +0 -1
- package/dist/mwl/content.js +0 -179
- package/dist/mwl/content.js.map +0 -1
- package/dist/mwl/expression.d.ts +0 -42
- package/dist/mwl/expression.d.ts.map +0 -1
- package/dist/mwl/expression.js +0 -164
- package/dist/mwl/expression.js.map +0 -1
- package/dist/mwl/grammar.d.ts +0 -100
- package/dist/mwl/grammar.d.ts.map +0 -1
- package/dist/mwl/grammar.js +0 -588
- package/dist/mwl/grammar.js.map +0 -1
- package/dist/mwl/hooks.d.ts +0 -201
- package/dist/mwl/hooks.d.ts.map +0 -1
- package/dist/mwl/hooks.js +0 -165
- package/dist/mwl/hooks.js.map +0 -1
- package/dist/mwl/index.d.ts +0 -51
- package/dist/mwl/index.d.ts.map +0 -1
- package/dist/mwl/index.js +0 -26
- package/dist/mwl/index.js.map +0 -1
- package/dist/mwl/objects.d.ts +0 -31
- package/dist/mwl/objects.d.ts.map +0 -1
- package/dist/mwl/objects.js +0 -83
- package/dist/mwl/objects.js.map +0 -1
- package/dist/mwl/package-container.d.ts +0 -185
- package/dist/mwl/package-container.d.ts.map +0 -1
- package/dist/mwl/package-container.js +0 -446
- package/dist/mwl/package-container.js.map +0 -1
- package/dist/mwl/package-document.d.ts +0 -217
- package/dist/mwl/package-document.d.ts.map +0 -1
- package/dist/mwl/package-document.js +0 -639
- package/dist/mwl/package-document.js.map +0 -1
- package/dist/mwl/package-rom.d.ts +0 -37
- package/dist/mwl/package-rom.d.ts.map +0 -1
- package/dist/mwl/package-rom.js +0 -96
- package/dist/mwl/package-rom.js.map +0 -1
- package/dist/mwl/package-verify.d.ts +0 -34
- package/dist/mwl/package-verify.d.ts.map +0 -1
- package/dist/mwl/package-verify.js +0 -111
- package/dist/mwl/package-verify.js.map +0 -1
- package/dist/mwl/package.d.ts +0 -184
- package/dist/mwl/package.d.ts.map +0 -1
- package/dist/mwl/package.js +0 -382
- package/dist/mwl/package.js.map +0 -1
- package/dist/mwl/persistence.d.ts +0 -67
- package/dist/mwl/persistence.d.ts.map +0 -1
- package/dist/mwl/persistence.js +0 -135
- package/dist/mwl/persistence.js.map +0 -1
- package/dist/mwl/presentation.d.ts +0 -86
- package/dist/mwl/presentation.d.ts.map +0 -1
- package/dist/mwl/presentation.js +0 -419
- package/dist/mwl/presentation.js.map +0 -1
- package/dist/mwl/pyroeis-runtime.d.ts +0 -82
- package/dist/mwl/pyroeis-runtime.d.ts.map +0 -1
- package/dist/mwl/pyroeis-runtime.js +0 -535
- package/dist/mwl/pyroeis-runtime.js.map +0 -1
- package/dist/mwl/pyroeis.d.ts +0 -54
- package/dist/mwl/pyroeis.d.ts.map +0 -1
- package/dist/mwl/pyroeis.js +0 -189
- package/dist/mwl/pyroeis.js.map +0 -1
- package/dist/mwl/readers.d.ts +0 -77
- package/dist/mwl/readers.d.ts.map +0 -1
- package/dist/mwl/readers.js +0 -150
- package/dist/mwl/readers.js.map +0 -1
- package/dist/mwl/report.d.ts +0 -44
- package/dist/mwl/report.d.ts.map +0 -1
- package/dist/mwl/report.js +0 -88
- package/dist/mwl/report.js.map +0 -1
- package/dist/mwl/runtime.d.ts +0 -577
- package/dist/mwl/runtime.d.ts.map +0 -1
- package/dist/mwl/runtime.js +0 -1741
- package/dist/mwl/runtime.js.map +0 -1
- package/dist/mwl/schema.d.ts +0 -151
- package/dist/mwl/schema.d.ts.map +0 -1
- package/dist/mwl/schema.js +0 -979
- package/dist/mwl/schema.js.map +0 -1
- package/dist/mwl/scripts.d.ts +0 -26
- package/dist/mwl/scripts.d.ts.map +0 -1
- package/dist/mwl/scripts.js +0 -34
- package/dist/mwl/scripts.js.map +0 -1
- package/dist/mwl/tables.d.ts +0 -95
- package/dist/mwl/tables.d.ts.map +0 -1
- package/dist/mwl/tables.js +0 -100
- package/dist/mwl/tables.js.map +0 -1
- package/dist/mwl/utils.d.ts +0 -10
- package/dist/mwl/utils.d.ts.map +0 -1
- package/dist/mwl/utils.js +0 -40
- package/dist/mwl/utils.js.map +0 -1
- package/dist/physics/PhysicsWorld.d.ts +0 -158
- package/dist/physics/PhysicsWorld.d.ts.map +0 -1
- package/dist/physics/PhysicsWorld.js +0 -376
- package/dist/physics/PhysicsWorld.js.map +0 -1
- package/dist/physics/XpbdWorld.d.ts +0 -213
- package/dist/physics/XpbdWorld.d.ts.map +0 -1
- package/dist/physics/XpbdWorld.js +0 -337
- package/dist/physics/XpbdWorld.js.map +0 -1
- package/dist/physics/cloth/index.d.ts +0 -99
- package/dist/physics/cloth/index.d.ts.map +0 -1
- package/dist/physics/cloth/index.js +0 -226
- package/dist/physics/cloth/index.js.map +0 -1
- package/dist/physics/index.d.ts +0 -7
- package/dist/physics/index.d.ts.map +0 -1
- package/dist/physics/index.js +0 -4
- package/dist/physics/index.js.map +0 -1
- package/dist/physics/spring/index.d.ts +0 -91
- package/dist/physics/spring/index.d.ts.map +0 -1
- package/dist/physics/spring/index.js +0 -120
- package/dist/physics/spring/index.js.map +0 -1
- package/dist/physics/xpbd.d.ts +0 -3
- package/dist/physics/xpbd.d.ts.map +0 -1
- package/dist/physics/xpbd.js +0 -2
- package/dist/physics/xpbd.js.map +0 -1
- package/dist/roguelike/Boss.d.ts +0 -79
- package/dist/roguelike/Boss.d.ts.map +0 -1
- package/dist/roguelike/Boss.js +0 -126
- package/dist/roguelike/Boss.js.map +0 -1
- package/dist/roguelike/Cave.d.ts +0 -124
- package/dist/roguelike/Cave.d.ts.map +0 -1
- package/dist/roguelike/Cave.js +0 -216
- package/dist/roguelike/Cave.js.map +0 -1
- package/dist/roguelike/Combat.d.ts +0 -35
- package/dist/roguelike/Combat.d.ts.map +0 -1
- package/dist/roguelike/Combat.js +0 -33
- package/dist/roguelike/Combat.js.map +0 -1
- package/dist/roguelike/ContentRoll.d.ts +0 -53
- package/dist/roguelike/ContentRoll.d.ts.map +0 -1
- package/dist/roguelike/ContentRoll.js +0 -48
- package/dist/roguelike/ContentRoll.js.map +0 -1
- package/dist/roguelike/Doors.d.ts +0 -73
- package/dist/roguelike/Doors.d.ts.map +0 -1
- package/dist/roguelike/Doors.js +0 -115
- package/dist/roguelike/Doors.js.map +0 -1
- package/dist/roguelike/DungeonParity.d.ts +0 -57
- package/dist/roguelike/DungeonParity.d.ts.map +0 -1
- package/dist/roguelike/DungeonParity.js +0 -87
- package/dist/roguelike/DungeonParity.js.map +0 -1
- package/dist/roguelike/Elevation.d.ts +0 -41
- package/dist/roguelike/Elevation.d.ts.map +0 -1
- package/dist/roguelike/Elevation.js +0 -52
- package/dist/roguelike/Elevation.js.map +0 -1
- package/dist/roguelike/Features.d.ts +0 -59
- package/dist/roguelike/Features.d.ts.map +0 -1
- package/dist/roguelike/Features.js +0 -76
- package/dist/roguelike/Features.js.map +0 -1
- package/dist/roguelike/FieldOfView.d.ts +0 -86
- package/dist/roguelike/FieldOfView.d.ts.map +0 -1
- package/dist/roguelike/FieldOfView.js +0 -148
- package/dist/roguelike/FieldOfView.js.map +0 -1
- package/dist/roguelike/Level.d.ts +0 -139
- package/dist/roguelike/Level.d.ts.map +0 -1
- package/dist/roguelike/Level.js +0 -189
- package/dist/roguelike/Level.js.map +0 -1
- package/dist/roguelike/MonsterAI.d.ts +0 -54
- package/dist/roguelike/MonsterAI.d.ts.map +0 -1
- package/dist/roguelike/MonsterAI.js +0 -83
- package/dist/roguelike/MonsterAI.js.map +0 -1
- package/dist/roguelike/MultiStageAbility.d.ts +0 -59
- package/dist/roguelike/MultiStageAbility.d.ts.map +0 -1
- package/dist/roguelike/MultiStageAbility.js +0 -76
- package/dist/roguelike/MultiStageAbility.js.map +0 -1
- package/dist/roguelike/MultiTurnBeam.d.ts +0 -108
- package/dist/roguelike/MultiTurnBeam.d.ts.map +0 -1
- package/dist/roguelike/MultiTurnBeam.js +0 -164
- package/dist/roguelike/MultiTurnBeam.js.map +0 -1
- package/dist/roguelike/Overworld.d.ts +0 -89
- package/dist/roguelike/Overworld.d.ts.map +0 -1
- package/dist/roguelike/Overworld.js +0 -325
- package/dist/roguelike/Overworld.js.map +0 -1
- package/dist/roguelike/Pathfinder.d.ts +0 -103
- package/dist/roguelike/Pathfinder.d.ts.map +0 -1
- package/dist/roguelike/Pathfinder.js +0 -213
- package/dist/roguelike/Pathfinder.js.map +0 -1
- package/dist/roguelike/Placement.d.ts +0 -62
- package/dist/roguelike/Placement.d.ts.map +0 -1
- package/dist/roguelike/Placement.js +0 -79
- package/dist/roguelike/Placement.js.map +0 -1
- package/dist/roguelike/RoomBuilders.d.ts +0 -60
- package/dist/roguelike/RoomBuilders.d.ts.map +0 -1
- package/dist/roguelike/RoomBuilders.js +0 -57
- package/dist/roguelike/RoomBuilders.js.map +0 -1
- package/dist/roguelike/Scheduler.d.ts +0 -96
- package/dist/roguelike/Scheduler.d.ts.map +0 -1
- package/dist/roguelike/Scheduler.js +0 -154
- package/dist/roguelike/Scheduler.js.map +0 -1
- package/dist/roguelike/Secrets.d.ts +0 -57
- package/dist/roguelike/Secrets.d.ts.map +0 -1
- package/dist/roguelike/Secrets.js +0 -77
- package/dist/roguelike/Secrets.js.map +0 -1
- package/dist/roguelike/Stealth.d.ts +0 -47
- package/dist/roguelike/Stealth.d.ts.map +0 -1
- package/dist/roguelike/Stealth.js +0 -48
- package/dist/roguelike/Stealth.js.map +0 -1
- package/dist/roguelike/Targeting.d.ts +0 -312
- package/dist/roguelike/Targeting.d.ts.map +0 -1
- package/dist/roguelike/Targeting.js +0 -483
- package/dist/roguelike/Targeting.js.map +0 -1
- package/dist/roguelike/TriggerTracker.d.ts +0 -46
- package/dist/roguelike/TriggerTracker.d.ts.map +0 -1
- package/dist/roguelike/TriggerTracker.js +0 -59
- package/dist/roguelike/TriggerTracker.js.map +0 -1
- package/dist/roguelike/generate.d.ts +0 -139
- package/dist/roguelike/generate.d.ts.map +0 -1
- package/dist/roguelike/generate.js +0 -166
- package/dist/roguelike/generate.js.map +0 -1
- package/dist/roguelike/index.d.ts +0 -48
- package/dist/roguelike/index.d.ts.map +0 -1
- package/dist/roguelike/index.js +0 -27
- package/dist/roguelike/index.js.map +0 -1
- package/dist/rpg/Collision.d.ts +0 -61
- package/dist/rpg/Collision.d.ts.map +0 -1
- package/dist/rpg/Collision.js +0 -94
- package/dist/rpg/Collision.js.map +0 -1
- package/dist/rpg/Event.d.ts +0 -50
- package/dist/rpg/Event.d.ts.map +0 -1
- package/dist/rpg/Event.js +0 -36
- package/dist/rpg/Event.js.map +0 -1
- package/dist/rpg/EventRunner.d.ts +0 -139
- package/dist/rpg/EventRunner.d.ts.map +0 -1
- package/dist/rpg/EventRunner.js +0 -125
- package/dist/rpg/EventRunner.js.map +0 -1
- package/dist/rpg/FreeMover.d.ts +0 -59
- package/dist/rpg/FreeMover.d.ts.map +0 -1
- package/dist/rpg/FreeMover.js +0 -79
- package/dist/rpg/FreeMover.js.map +0 -1
- package/dist/rpg/GameState.d.ts +0 -36
- package/dist/rpg/GameState.d.ts.map +0 -1
- package/dist/rpg/GameState.js +0 -49
- package/dist/rpg/GameState.js.map +0 -1
- package/dist/rpg/GridMover.d.ts +0 -71
- package/dist/rpg/GridMover.d.ts.map +0 -1
- package/dist/rpg/GridMover.js +0 -119
- package/dist/rpg/GridMover.js.map +0 -1
- package/dist/rpg/Marshal.d.ts +0 -81
- package/dist/rpg/Marshal.d.ts.map +0 -1
- package/dist/rpg/Marshal.js +0 -422
- package/dist/rpg/Marshal.js.map +0 -1
- package/dist/rpg/MovableSprite.d.ts +0 -31
- package/dist/rpg/MovableSprite.d.ts.map +0 -1
- package/dist/rpg/MovableSprite.js +0 -10
- package/dist/rpg/MovableSprite.js.map +0 -1
- package/dist/rpg/MoveRoute.d.ts +0 -118
- package/dist/rpg/MoveRoute.d.ts.map +0 -1
- package/dist/rpg/MoveRoute.js +0 -139
- package/dist/rpg/MoveRoute.js.map +0 -1
- package/dist/rpg/Quest.d.ts +0 -173
- package/dist/rpg/Quest.d.ts.map +0 -1
- package/dist/rpg/Quest.js +0 -221
- package/dist/rpg/Quest.js.map +0 -1
- package/dist/rpg/automap.d.ts +0 -81
- package/dist/rpg/automap.d.ts.map +0 -1
- package/dist/rpg/automap.js +0 -107
- package/dist/rpg/automap.js.map +0 -1
- package/dist/rpg/dialogue-text.d.ts +0 -81
- package/dist/rpg/dialogue-text.d.ts.map +0 -1
- package/dist/rpg/dialogue-text.js +0 -88
- package/dist/rpg/dialogue-text.js.map +0 -1
- package/dist/rpg/index.d.ts +0 -25
- package/dist/rpg/index.d.ts.map +0 -1
- package/dist/rpg/index.js +0 -14
- package/dist/rpg/index.js.map +0 -1
- package/dist/rpg/twee-events.d.ts +0 -48
- package/dist/rpg/twee-events.d.ts.map +0 -1
- package/dist/rpg/twee-events.js +0 -35
- package/dist/rpg/twee-events.js.map +0 -1
- package/dist/simulation/Campaign.d.ts +0 -60
- package/dist/simulation/Campaign.d.ts.map +0 -1
- package/dist/simulation/Campaign.js +0 -89
- package/dist/simulation/Campaign.js.map +0 -1
- package/dist/simulation/CampaignSave.d.ts +0 -68
- package/dist/simulation/CampaignSave.d.ts.map +0 -1
- package/dist/simulation/CampaignSave.js +0 -54
- package/dist/simulation/CampaignSave.js.map +0 -1
- package/dist/simulation/EventPresentation.d.ts +0 -111
- package/dist/simulation/EventPresentation.d.ts.map +0 -1
- package/dist/simulation/EventPresentation.js +0 -120
- package/dist/simulation/EventPresentation.js.map +0 -1
- package/dist/simulation/Harness.d.ts +0 -26
- package/dist/simulation/Harness.d.ts.map +0 -1
- package/dist/simulation/Harness.js +0 -26
- package/dist/simulation/Harness.js.map +0 -1
- package/dist/simulation/Runtime.d.ts +0 -189
- package/dist/simulation/Runtime.d.ts.map +0 -1
- package/dist/simulation/Runtime.js +0 -244
- package/dist/simulation/Runtime.js.map +0 -1
- package/dist/simulation/Scenario.d.ts +0 -44
- package/dist/simulation/Scenario.d.ts.map +0 -1
- package/dist/simulation/Scenario.js +0 -40
- package/dist/simulation/Scenario.js.map +0 -1
- package/dist/simulation/Training.d.ts +0 -220
- package/dist/simulation/Training.d.ts.map +0 -1
- package/dist/simulation/Training.js +0 -366
- package/dist/simulation/Training.js.map +0 -1
- package/dist/simulation/Turns.d.ts +0 -40
- package/dist/simulation/Turns.d.ts.map +0 -1
- package/dist/simulation/Turns.js +0 -41
- package/dist/simulation/Turns.js.map +0 -1
- package/dist/simulation/index.d.ts +0 -25
- package/dist/simulation/index.d.ts.map +0 -1
- package/dist/simulation/index.js +0 -16
- package/dist/simulation/index.js.map +0 -1
- package/dist/skeleton/index.d.ts +0 -212
- package/dist/skeleton/index.d.ts.map +0 -1
- package/dist/skeleton/index.js +0 -325
- package/dist/skeleton/index.js.map +0 -1
- package/dist/testing/FakeAudio.d.ts +0 -149
- package/dist/testing/FakeAudio.d.ts.map +0 -1
- package/dist/testing/FakeAudio.js +0 -219
- package/dist/testing/FakeAudio.js.map +0 -1
- package/dist/testing/SceneControls.d.ts +0 -35
- package/dist/testing/SceneControls.d.ts.map +0 -1
- package/dist/testing/SceneControls.js +0 -49
- package/dist/testing/SceneControls.js.map +0 -1
- package/dist/testing/index.d.ts +0 -125
- package/dist/testing/index.d.ts.map +0 -1
- package/dist/testing/index.js +0 -157
- package/dist/testing/index.js.map +0 -1
- package/dist/threads/index.d.ts +0 -3
- package/dist/threads/index.d.ts.map +0 -1
- package/dist/threads/index.js +0 -2
- package/dist/threads/index.js.map +0 -1
- package/dist/threads/spawn.d.ts +0 -73
- package/dist/threads/spawn.d.ts.map +0 -1
- package/dist/threads/spawn.js +0 -167
- package/dist/threads/spawn.js.map +0 -1
- package/dist/threads/worker.d.ts +0 -51
- package/dist/threads/worker.d.ts.map +0 -1
- package/dist/threads/worker.js +0 -84
- package/dist/threads/worker.js.map +0 -1
- package/dist/three-d/Character3D.d.ts +0 -74
- package/dist/three-d/Character3D.d.ts.map +0 -1
- package/dist/three-d/Character3D.js +0 -122
- package/dist/three-d/Character3D.js.map +0 -1
- package/dist/three-d/Collision3D.d.ts +0 -111
- package/dist/three-d/Collision3D.d.ts.map +0 -1
- package/dist/three-d/Collision3D.js +0 -119
- package/dist/three-d/Collision3D.js.map +0 -1
- package/dist/three-d/Engine3D.d.ts +0 -25
- package/dist/three-d/Engine3D.d.ts.map +0 -1
- package/dist/three-d/Engine3D.js +0 -45
- package/dist/three-d/Engine3D.js.map +0 -1
- package/dist/three-d/Grid.d.ts +0 -30
- package/dist/three-d/Grid.d.ts.map +0 -1
- package/dist/three-d/Grid.js +0 -24
- package/dist/three-d/Grid.js.map +0 -1
- package/dist/three-d/Heightmap.d.ts +0 -38
- package/dist/three-d/Heightmap.d.ts.map +0 -1
- package/dist/three-d/Heightmap.js +0 -29
- package/dist/three-d/Heightmap.js.map +0 -1
- package/dist/three-d/Models.d.ts +0 -49
- package/dist/three-d/Models.d.ts.map +0 -1
- package/dist/three-d/Models.js +0 -77
- package/dist/three-d/Models.js.map +0 -1
- package/dist/three-d/TileGrid3D.d.ts +0 -27
- package/dist/three-d/TileGrid3D.d.ts.map +0 -1
- package/dist/three-d/TileGrid3D.js +0 -66
- package/dist/three-d/TileGrid3D.js.map +0 -1
- package/dist/three-d/Vox.d.ts +0 -43
- package/dist/three-d/Vox.d.ts.map +0 -1
- package/dist/three-d/Vox.js +0 -108
- package/dist/three-d/Vox.js.map +0 -1
- package/dist/three-d/index.d.ts +0 -15
- package/dist/three-d/index.d.ts.map +0 -1
- package/dist/three-d/index.js +0 -8
- package/dist/three-d/index.js.map +0 -1
- package/dist/two-d/Game.d.ts +0 -240
- package/dist/two-d/Game.d.ts.map +0 -1
- package/dist/two-d/Game.js +0 -487
- package/dist/two-d/Game.js.map +0 -1
- package/dist/two-d/QualityScaler.d.ts +0 -63
- package/dist/two-d/QualityScaler.d.ts.map +0 -1
- package/dist/two-d/QualityScaler.js +0 -92
- package/dist/two-d/QualityScaler.js.map +0 -1
- package/dist/two-d/ResolutionFit.d.ts +0 -28
- package/dist/two-d/ResolutionFit.d.ts.map +0 -1
- package/dist/two-d/ResolutionFit.js +0 -39
- package/dist/two-d/ResolutionFit.js.map +0 -1
- package/dist/two-d/Scene2D.d.ts +0 -43
- package/dist/two-d/Scene2D.d.ts.map +0 -1
- package/dist/two-d/Scene2D.js +0 -53
- package/dist/two-d/Scene2D.js.map +0 -1
- package/dist/two-d/index.d.ts +0 -22
- package/dist/two-d/index.d.ts.map +0 -1
- package/dist/two-d/index.js +0 -19
- package/dist/two-d/index.js.map +0 -1
- package/dist/two-d/pixi-interop.d.ts +0 -66
- package/dist/two-d/pixi-interop.d.ts.map +0 -1
- package/dist/two-d/pixi-interop.js +0 -72
- package/dist/two-d/pixi-interop.js.map +0 -1
- package/dist/two-d/presentation/MwlPresentation.d.ts +0 -117
- package/dist/two-d/presentation/MwlPresentation.d.ts.map +0 -1
- package/dist/two-d/presentation/MwlPresentation.js +0 -755
- package/dist/two-d/presentation/MwlPresentation.js.map +0 -1
- package/dist/two-d/presentation/index.d.ts +0 -3
- package/dist/two-d/presentation/index.d.ts.map +0 -1
- package/dist/two-d/presentation/index.js +0 -2
- package/dist/two-d/presentation/index.js.map +0 -1
- package/dist/two-d/render/ActorAnimator.d.ts +0 -92
- package/dist/two-d/render/ActorAnimator.d.ts.map +0 -1
- package/dist/two-d/render/ActorAnimator.js +0 -97
- package/dist/two-d/render/ActorAnimator.js.map +0 -1
- package/dist/two-d/render/AnimatedSprite.d.ts +0 -154
- package/dist/two-d/render/AnimatedSprite.d.ts.map +0 -1
- package/dist/two-d/render/AnimatedSprite.js +0 -197
- package/dist/two-d/render/AnimatedSprite.js.map +0 -1
- package/dist/two-d/render/Autotile.d.ts +0 -74
- package/dist/two-d/render/Autotile.d.ts.map +0 -1
- package/dist/two-d/render/Autotile.js +0 -149
- package/dist/two-d/render/Autotile.js.map +0 -1
- package/dist/two-d/render/Beam.d.ts +0 -136
- package/dist/two-d/render/Beam.d.ts.map +0 -1
- package/dist/two-d/render/Beam.js +0 -203
- package/dist/two-d/render/Beam.js.map +0 -1
- package/dist/two-d/render/Camera.d.ts +0 -255
- package/dist/two-d/render/Camera.d.ts.map +0 -1
- package/dist/two-d/render/Camera.js +0 -376
- package/dist/two-d/render/Camera.js.map +0 -1
- package/dist/two-d/render/Capabilities.d.ts +0 -84
- package/dist/two-d/render/Capabilities.d.ts.map +0 -1
- package/dist/two-d/render/Capabilities.js +0 -129
- package/dist/two-d/render/Capabilities.js.map +0 -1
- package/dist/two-d/render/ClothSprite.d.ts +0 -83
- package/dist/two-d/render/ClothSprite.d.ts.map +0 -1
- package/dist/two-d/render/ClothSprite.js +0 -105
- package/dist/two-d/render/ClothSprite.js.map +0 -1
- package/dist/two-d/render/ColorBlindness.d.ts +0 -39
- package/dist/two-d/render/ColorBlindness.d.ts.map +0 -1
- package/dist/two-d/render/ColorBlindness.js +0 -45
- package/dist/two-d/render/ColorBlindness.js.map +0 -1
- package/dist/two-d/render/ColorTransformBatcher.d.ts +0 -143
- package/dist/two-d/render/ColorTransformBatcher.d.ts.map +0 -1
- package/dist/two-d/render/ColorTransformBatcher.js +0 -395
- package/dist/two-d/render/ColorTransformBatcher.js.map +0 -1
- package/dist/two-d/render/Flights.d.ts +0 -90
- package/dist/two-d/render/Flights.d.ts.map +0 -1
- package/dist/two-d/render/Flights.js +0 -135
- package/dist/two-d/render/Flights.js.map +0 -1
- package/dist/two-d/render/FogLayer.d.ts +0 -68
- package/dist/two-d/render/FogLayer.d.ts.map +0 -1
- package/dist/two-d/render/FogLayer.js +0 -83
- package/dist/two-d/render/FogLayer.js.map +0 -1
- package/dist/two-d/render/Halo.d.ts +0 -58
- package/dist/two-d/render/Halo.d.ts.map +0 -1
- package/dist/two-d/render/Halo.js +0 -48
- package/dist/two-d/render/Halo.js.map +0 -1
- package/dist/two-d/render/HazeLayer.d.ts +0 -112
- package/dist/two-d/render/HazeLayer.d.ts.map +0 -1
- package/dist/two-d/render/HazeLayer.js +0 -186
- package/dist/two-d/render/HazeLayer.js.map +0 -1
- package/dist/two-d/render/ImageModifiers.d.ts +0 -312
- package/dist/two-d/render/ImageModifiers.d.ts.map +0 -1
- package/dist/two-d/render/ImageModifiers.js +0 -728
- package/dist/two-d/render/ImageModifiers.js.map +0 -1
- package/dist/two-d/render/LayeredSprite.d.ts +0 -54
- package/dist/two-d/render/LayeredSprite.d.ts.map +0 -1
- package/dist/two-d/render/LayeredSprite.js +0 -80
- package/dist/two-d/render/LayeredSprite.js.map +0 -1
- package/dist/two-d/render/LightningArc.d.ts +0 -57
- package/dist/two-d/render/LightningArc.d.ts.map +0 -1
- package/dist/two-d/render/LightningArc.js +0 -91
- package/dist/two-d/render/LightningArc.js.map +0 -1
- package/dist/two-d/render/LiquidLayer.d.ts +0 -62
- package/dist/two-d/render/LiquidLayer.d.ts.map +0 -1
- package/dist/two-d/render/LiquidLayer.js +0 -102
- package/dist/two-d/render/LiquidLayer.js.map +0 -1
- package/dist/two-d/render/Minimap.d.ts +0 -100
- package/dist/two-d/render/Minimap.d.ts.map +0 -1
- package/dist/two-d/render/Minimap.js +0 -157
- package/dist/two-d/render/Minimap.js.map +0 -1
- package/dist/two-d/render/NeonGlow.d.ts +0 -100
- package/dist/two-d/render/NeonGlow.d.ts.map +0 -1
- package/dist/two-d/render/NeonGlow.js +0 -184
- package/dist/two-d/render/NeonGlow.js.map +0 -1
- package/dist/two-d/render/PaletteRemap.d.ts +0 -154
- package/dist/two-d/render/PaletteRemap.d.ts.map +0 -1
- package/dist/two-d/render/PaletteRemap.js +0 -217
- package/dist/two-d/render/PaletteRemap.js.map +0 -1
- package/dist/two-d/render/Particles.d.ts +0 -262
- package/dist/two-d/render/Particles.d.ts.map +0 -1
- package/dist/two-d/render/Particles.js +0 -371
- package/dist/two-d/render/Particles.js.map +0 -1
- package/dist/two-d/render/Projectile.d.ts +0 -67
- package/dist/two-d/render/Projectile.d.ts.map +0 -1
- package/dist/two-d/render/Projectile.js +0 -78
- package/dist/two-d/render/Projectile.js.map +0 -1
- package/dist/two-d/render/RpgmAutotile.d.ts +0 -324
- package/dist/two-d/render/RpgmAutotile.d.ts.map +0 -1
- package/dist/two-d/render/RpgmAutotile.js +0 -933
- package/dist/two-d/render/RpgmAutotile.js.map +0 -1
- package/dist/two-d/render/SceneTransition.d.ts +0 -301
- package/dist/two-d/render/SceneTransition.d.ts.map +0 -1
- package/dist/two-d/render/SceneTransition.js +0 -458
- package/dist/two-d/render/SceneTransition.js.map +0 -1
- package/dist/two-d/render/ScreenEffects.d.ts +0 -124
- package/dist/two-d/render/ScreenEffects.d.ts.map +0 -1
- package/dist/two-d/render/ScreenEffects.js +0 -215
- package/dist/two-d/render/ScreenEffects.js.map +0 -1
- package/dist/two-d/render/Shape2D.d.ts +0 -146
- package/dist/two-d/render/Shape2D.d.ts.map +0 -1
- package/dist/two-d/render/Shape2D.js +0 -166
- package/dist/two-d/render/Shape2D.js.map +0 -1
- package/dist/two-d/render/SkeletalSprite.d.ts +0 -121
- package/dist/two-d/render/SkeletalSprite.d.ts.map +0 -1
- package/dist/two-d/render/SkeletalSprite.js +0 -214
- package/dist/two-d/render/SkeletalSprite.js.map +0 -1
- package/dist/two-d/render/SpringSprite.d.ts +0 -40
- package/dist/two-d/render/SpringSprite.d.ts.map +0 -1
- package/dist/two-d/render/SpringSprite.js +0 -39
- package/dist/two-d/render/SpringSprite.js.map +0 -1
- package/dist/two-d/render/SpriteAttachment.d.ts +0 -55
- package/dist/two-d/render/SpriteAttachment.d.ts.map +0 -1
- package/dist/two-d/render/SpriteAttachment.js +0 -60
- package/dist/two-d/render/SpriteAttachment.js.map +0 -1
- package/dist/two-d/render/SpriteDeform.d.ts +0 -156
- package/dist/two-d/render/SpriteDeform.d.ts.map +0 -1
- package/dist/two-d/render/SpriteDeform.js +0 -278
- package/dist/two-d/render/SpriteDeform.js.map +0 -1
- package/dist/two-d/render/SpriteGroup.d.ts +0 -83
- package/dist/two-d/render/SpriteGroup.d.ts.map +0 -1
- package/dist/two-d/render/SpriteGroup.js +0 -107
- package/dist/two-d/render/SpriteGroup.js.map +0 -1
- package/dist/two-d/render/SpriteMotion.d.ts +0 -121
- package/dist/two-d/render/SpriteMotion.d.ts.map +0 -1
- package/dist/two-d/render/SpriteMotion.js +0 -193
- package/dist/two-d/render/SpriteMotion.js.map +0 -1
- package/dist/two-d/render/SpriteSheet.d.ts +0 -62
- package/dist/two-d/render/SpriteSheet.d.ts.map +0 -1
- package/dist/two-d/render/SpriteSheet.js +0 -122
- package/dist/two-d/render/SpriteSheet.js.map +0 -1
- package/dist/two-d/render/StatusVisuals.d.ts +0 -86
- package/dist/two-d/render/StatusVisuals.d.ts.map +0 -1
- package/dist/two-d/render/StatusVisuals.js +0 -111
- package/dist/two-d/render/StatusVisuals.js.map +0 -1
- package/dist/two-d/render/SvgSkeleton.d.ts +0 -54
- package/dist/two-d/render/SvgSkeleton.d.ts.map +0 -1
- package/dist/two-d/render/SvgSkeleton.js +0 -112
- package/dist/two-d/render/SvgSkeleton.js.map +0 -1
- package/dist/two-d/render/TerrainGraphics.d.ts +0 -142
- package/dist/two-d/render/TerrainGraphics.d.ts.map +0 -1
- package/dist/two-d/render/TerrainGraphics.js +0 -161
- package/dist/two-d/render/TerrainGraphics.js.map +0 -1
- package/dist/two-d/render/TerrainGraphicsLayer.d.ts +0 -55
- package/dist/two-d/render/TerrainGraphicsLayer.d.ts.map +0 -1
- package/dist/two-d/render/TerrainGraphicsLayer.js +0 -54
- package/dist/two-d/render/TerrainGraphicsLayer.js.map +0 -1
- package/dist/two-d/render/TileMap.d.ts +0 -395
- package/dist/two-d/render/TileMap.d.ts.map +0 -1
- package/dist/two-d/render/TileMap.js +0 -967
- package/dist/two-d/render/TileMap.js.map +0 -1
- package/dist/two-d/render/TiledMap.d.ts +0 -113
- package/dist/two-d/render/TiledMap.d.ts.map +0 -1
- package/dist/two-d/render/TiledMap.js +0 -129
- package/dist/two-d/render/TiledMap.js.map +0 -1
- package/dist/two-d/render/TintedSprite.d.ts +0 -60
- package/dist/two-d/render/TintedSprite.d.ts.map +0 -1
- package/dist/two-d/render/TintedSprite.js +0 -88
- package/dist/two-d/render/TintedSprite.js.map +0 -1
- package/dist/two-d/render/Types2D.d.ts +0 -56
- package/dist/two-d/render/Types2D.d.ts.map +0 -1
- package/dist/two-d/render/Types2D.js +0 -45
- package/dist/two-d/render/Types2D.js.map +0 -1
- package/dist/two-d/render/Viewport.d.ts +0 -68
- package/dist/two-d/render/Viewport.d.ts.map +0 -1
- package/dist/two-d/render/Viewport.js +0 -74
- package/dist/two-d/render/Viewport.js.map +0 -1
- package/dist/two-d/render/index.d.ts +0 -81
- package/dist/two-d/render/index.d.ts.map +0 -1
- package/dist/two-d/render/index.js +0 -43
- package/dist/two-d/render/index.js.map +0 -1
- package/dist/two-d/stage/DialogueStage.d.ts +0 -90
- package/dist/two-d/stage/DialogueStage.d.ts.map +0 -1
- package/dist/two-d/stage/DialogueStage.js +0 -218
- package/dist/two-d/stage/DialogueStage.js.map +0 -1
- package/dist/two-d/stage/StoryScreen.d.ts +0 -110
- package/dist/two-d/stage/StoryScreen.d.ts.map +0 -1
- package/dist/two-d/stage/StoryScreen.js +0 -178
- package/dist/two-d/stage/StoryScreen.js.map +0 -1
- package/dist/two-d/stage/dialogue-text.d.ts +0 -81
- package/dist/two-d/stage/dialogue-text.d.ts.map +0 -1
- package/dist/two-d/stage/dialogue-text.js +0 -95
- package/dist/two-d/stage/dialogue-text.js.map +0 -1
- package/dist/two-d/stage/index.d.ts +0 -10
- package/dist/two-d/stage/index.d.ts.map +0 -1
- package/dist/two-d/stage/index.js +0 -6
- package/dist/two-d/stage/index.js.map +0 -1
- package/dist/two-d/stage/script.d.ts +0 -160
- package/dist/two-d/stage/script.d.ts.map +0 -1
- package/dist/two-d/stage/script.js +0 -207
- package/dist/two-d/stage/script.js.map +0 -1
- package/dist/two-d/stage/twee.d.ts +0 -35
- package/dist/two-d/stage/twee.d.ts.map +0 -1
- package/dist/two-d/stage/twee.js +0 -28
- package/dist/two-d/stage/twee.js.map +0 -1
- package/dist/two-d/ui/Bar.d.ts +0 -83
- package/dist/two-d/ui/Bar.d.ts.map +0 -1
- package/dist/two-d/ui/Bar.js +0 -110
- package/dist/two-d/ui/Bar.js.map +0 -1
- package/dist/two-d/ui/BitmapLabel.d.ts +0 -58
- package/dist/two-d/ui/BitmapLabel.d.ts.map +0 -1
- package/dist/two-d/ui/BitmapLabel.js +0 -82
- package/dist/two-d/ui/BitmapLabel.js.map +0 -1
- package/dist/two-d/ui/Button.d.ts +0 -133
- package/dist/two-d/ui/Button.d.ts.map +0 -1
- package/dist/two-d/ui/Button.js +0 -254
- package/dist/two-d/ui/Button.js.map +0 -1
- package/dist/two-d/ui/Checkbox.d.ts +0 -44
- package/dist/two-d/ui/Checkbox.d.ts.map +0 -1
- package/dist/two-d/ui/Checkbox.js +0 -89
- package/dist/two-d/ui/Checkbox.js.map +0 -1
- package/dist/two-d/ui/DataTable.d.ts +0 -79
- package/dist/two-d/ui/DataTable.d.ts.map +0 -1
- package/dist/two-d/ui/DataTable.js +0 -164
- package/dist/two-d/ui/DataTable.js.map +0 -1
- package/dist/two-d/ui/Dropdown.d.ts +0 -79
- package/dist/two-d/ui/Dropdown.d.ts.map +0 -1
- package/dist/two-d/ui/Dropdown.js +0 -136
- package/dist/two-d/ui/Dropdown.js.map +0 -1
- package/dist/two-d/ui/DropdownView.d.ts +0 -100
- package/dist/two-d/ui/DropdownView.d.ts.map +0 -1
- package/dist/two-d/ui/DropdownView.js +0 -234
- package/dist/two-d/ui/DropdownView.js.map +0 -1
- package/dist/two-d/ui/EventDialogue.d.ts +0 -23
- package/dist/two-d/ui/EventDialogue.d.ts.map +0 -1
- package/dist/two-d/ui/EventDialogue.js +0 -33
- package/dist/two-d/ui/EventDialogue.js.map +0 -1
- package/dist/two-d/ui/FloatingText.d.ts +0 -123
- package/dist/two-d/ui/FloatingText.d.ts.map +0 -1
- package/dist/two-d/ui/FloatingText.js +0 -153
- package/dist/two-d/ui/FloatingText.js.map +0 -1
- package/dist/two-d/ui/FloatingTextStack.d.ts +0 -150
- package/dist/two-d/ui/FloatingTextStack.d.ts.map +0 -1
- package/dist/two-d/ui/FloatingTextStack.js +0 -170
- package/dist/two-d/ui/FloatingTextStack.js.map +0 -1
- package/dist/two-d/ui/HelpScreen.d.ts +0 -45
- package/dist/two-d/ui/HelpScreen.d.ts.map +0 -1
- package/dist/two-d/ui/HelpScreen.js +0 -59
- package/dist/two-d/ui/HelpScreen.js.map +0 -1
- package/dist/two-d/ui/IconGrid.d.ts +0 -143
- package/dist/two-d/ui/IconGrid.d.ts.map +0 -1
- package/dist/two-d/ui/IconGrid.js +0 -327
- package/dist/two-d/ui/IconGrid.js.map +0 -1
- package/dist/two-d/ui/Label.d.ts +0 -63
- package/dist/two-d/ui/Label.d.ts.map +0 -1
- package/dist/two-d/ui/Label.js +0 -134
- package/dist/two-d/ui/Label.js.map +0 -1
- package/dist/two-d/ui/Layout.d.ts +0 -139
- package/dist/two-d/ui/Layout.d.ts.map +0 -1
- package/dist/two-d/ui/Layout.js +0 -221
- package/dist/two-d/ui/Layout.js.map +0 -1
- package/dist/two-d/ui/ListView.d.ts +0 -130
- package/dist/two-d/ui/ListView.d.ts.map +0 -1
- package/dist/two-d/ui/ListView.js +0 -326
- package/dist/two-d/ui/ListView.js.map +0 -1
- package/dist/two-d/ui/LoadingScreen.d.ts +0 -54
- package/dist/two-d/ui/LoadingScreen.d.ts.map +0 -1
- package/dist/two-d/ui/LoadingScreen.js +0 -87
- package/dist/two-d/ui/LoadingScreen.js.map +0 -1
- package/dist/two-d/ui/MarkupText.d.ts +0 -66
- package/dist/two-d/ui/MarkupText.d.ts.map +0 -1
- package/dist/two-d/ui/MarkupText.js +0 -156
- package/dist/two-d/ui/MarkupText.js.map +0 -1
- package/dist/two-d/ui/MessageBox.d.ts +0 -134
- package/dist/two-d/ui/MessageBox.d.ts.map +0 -1
- package/dist/two-d/ui/MessageBox.js +0 -263
- package/dist/two-d/ui/MessageBox.js.map +0 -1
- package/dist/two-d/ui/MessageLog.d.ts +0 -90
- package/dist/two-d/ui/MessageLog.d.ts.map +0 -1
- package/dist/two-d/ui/MessageLog.js +0 -131
- package/dist/two-d/ui/MessageLog.js.map +0 -1
- package/dist/two-d/ui/Meter.d.ts +0 -76
- package/dist/two-d/ui/Meter.d.ts.map +0 -1
- package/dist/two-d/ui/Meter.js +0 -134
- package/dist/two-d/ui/Meter.js.map +0 -1
- package/dist/two-d/ui/NinePatch.d.ts +0 -49
- package/dist/two-d/ui/NinePatch.d.ts.map +0 -1
- package/dist/two-d/ui/NinePatch.js +0 -59
- package/dist/two-d/ui/NinePatch.js.map +0 -1
- package/dist/two-d/ui/OnScreenKeyboard.d.ts +0 -91
- package/dist/two-d/ui/OnScreenKeyboard.d.ts.map +0 -1
- package/dist/two-d/ui/OnScreenKeyboard.js +0 -109
- package/dist/two-d/ui/OnScreenKeyboard.js.map +0 -1
- package/dist/two-d/ui/RadioGroup.d.ts +0 -68
- package/dist/two-d/ui/RadioGroup.d.ts.map +0 -1
- package/dist/two-d/ui/RadioGroup.js +0 -177
- package/dist/two-d/ui/RadioGroup.js.map +0 -1
- package/dist/two-d/ui/RebindScreen.d.ts +0 -70
- package/dist/two-d/ui/RebindScreen.d.ts.map +0 -1
- package/dist/two-d/ui/RebindScreen.js +0 -129
- package/dist/two-d/ui/RebindScreen.js.map +0 -1
- package/dist/two-d/ui/RichLabel.d.ts +0 -62
- package/dist/two-d/ui/RichLabel.d.ts.map +0 -1
- package/dist/two-d/ui/RichLabel.js +0 -146
- package/dist/two-d/ui/RichLabel.js.map +0 -1
- package/dist/two-d/ui/ScrollBox.d.ts +0 -163
- package/dist/two-d/ui/ScrollBox.d.ts.map +0 -1
- package/dist/two-d/ui/ScrollBox.js +0 -340
- package/dist/two-d/ui/ScrollBox.js.map +0 -1
- package/dist/two-d/ui/ScrollText.d.ts +0 -131
- package/dist/two-d/ui/ScrollText.d.ts.map +0 -1
- package/dist/two-d/ui/ScrollText.js +0 -218
- package/dist/two-d/ui/ScrollText.js.map +0 -1
- package/dist/two-d/ui/SelectionModel.d.ts +0 -50
- package/dist/two-d/ui/SelectionModel.d.ts.map +0 -1
- package/dist/two-d/ui/SelectionModel.js +0 -73
- package/dist/two-d/ui/SelectionModel.js.map +0 -1
- package/dist/two-d/ui/SettingsScreen.d.ts +0 -112
- package/dist/two-d/ui/SettingsScreen.d.ts.map +0 -1
- package/dist/two-d/ui/SettingsScreen.js +0 -338
- package/dist/two-d/ui/SettingsScreen.js.map +0 -1
- package/dist/two-d/ui/Skins.d.ts +0 -59
- package/dist/two-d/ui/Skins.d.ts.map +0 -1
- package/dist/two-d/ui/Skins.js +0 -77
- package/dist/two-d/ui/Skins.js.map +0 -1
- package/dist/two-d/ui/Slider.d.ts +0 -91
- package/dist/two-d/ui/Slider.d.ts.map +0 -1
- package/dist/two-d/ui/Slider.js +0 -170
- package/dist/two-d/ui/Slider.js.map +0 -1
- package/dist/two-d/ui/Spinner.d.ts +0 -67
- package/dist/two-d/ui/Spinner.d.ts.map +0 -1
- package/dist/two-d/ui/Spinner.js +0 -137
- package/dist/two-d/ui/Spinner.js.map +0 -1
- package/dist/two-d/ui/StatsScreen.d.ts +0 -40
- package/dist/two-d/ui/StatsScreen.d.ts.map +0 -1
- package/dist/two-d/ui/StatsScreen.js +0 -42
- package/dist/two-d/ui/StatsScreen.js.map +0 -1
- package/dist/two-d/ui/TabbedList.d.ts +0 -118
- package/dist/two-d/ui/TabbedList.d.ts.map +0 -1
- package/dist/two-d/ui/TabbedList.js +0 -221
- package/dist/two-d/ui/TabbedList.js.map +0 -1
- package/dist/two-d/ui/TextModel.d.ts +0 -90
- package/dist/two-d/ui/TextModel.d.ts.map +0 -1
- package/dist/two-d/ui/TextModel.js +0 -175
- package/dist/two-d/ui/TextModel.js.map +0 -1
- package/dist/two-d/ui/TextPrompt.d.ts +0 -122
- package/dist/two-d/ui/TextPrompt.d.ts.map +0 -1
- package/dist/two-d/ui/TextPrompt.js +0 -236
- package/dist/two-d/ui/TextPrompt.js.map +0 -1
- package/dist/two-d/ui/TextSharpness.d.ts +0 -33
- package/dist/two-d/ui/TextSharpness.d.ts.map +0 -1
- package/dist/two-d/ui/TextSharpness.js +0 -56
- package/dist/two-d/ui/TextSharpness.js.map +0 -1
- package/dist/two-d/ui/Toast.d.ts +0 -57
- package/dist/two-d/ui/Toast.d.ts.map +0 -1
- package/dist/two-d/ui/Toast.js +0 -101
- package/dist/two-d/ui/Toast.js.map +0 -1
- package/dist/two-d/ui/Tooltip.d.ts +0 -177
- package/dist/two-d/ui/Tooltip.d.ts.map +0 -1
- package/dist/two-d/ui/Tooltip.js +0 -275
- package/dist/two-d/ui/Tooltip.js.map +0 -1
- package/dist/two-d/ui/TreeView.d.ts +0 -68
- package/dist/two-d/ui/TreeView.d.ts.map +0 -1
- package/dist/two-d/ui/TreeView.js +0 -133
- package/dist/two-d/ui/TreeView.js.map +0 -1
- package/dist/two-d/ui/VerticalLabel.d.ts +0 -69
- package/dist/two-d/ui/VerticalLabel.d.ts.map +0 -1
- package/dist/two-d/ui/VerticalLabel.js +0 -110
- package/dist/two-d/ui/VerticalLabel.js.map +0 -1
- package/dist/two-d/ui/Window.d.ts +0 -188
- package/dist/two-d/ui/Window.d.ts.map +0 -1
- package/dist/two-d/ui/Window.js +0 -311
- package/dist/two-d/ui/Window.js.map +0 -1
- package/dist/two-d/ui/WindowStack.d.ts +0 -63
- package/dist/two-d/ui/WindowStack.d.ts.map +0 -1
- package/dist/two-d/ui/WindowStack.js +0 -132
- package/dist/two-d/ui/WindowStack.js.map +0 -1
- package/dist/two-d/ui/a11y.d.ts +0 -43
- package/dist/two-d/ui/a11y.d.ts.map +0 -1
- package/dist/two-d/ui/a11y.js +0 -79
- package/dist/two-d/ui/a11y.js.map +0 -1
- package/dist/two-d/ui/contrast.d.ts +0 -30
- package/dist/two-d/ui/contrast.d.ts.map +0 -1
- package/dist/two-d/ui/contrast.js +0 -42
- package/dist/two-d/ui/contrast.js.map +0 -1
- package/dist/two-d/ui/index.d.ts +0 -96
- package/dist/two-d/ui/index.d.ts.map +0 -1
- package/dist/two-d/ui/index.js +0 -49
- package/dist/two-d/ui/index.js.map +0 -1
- package/dist/two-d/ui/markdown.d.ts +0 -55
- package/dist/two-d/ui/markdown.d.ts.map +0 -1
- package/dist/two-d/ui/markdown.js +0 -147
- package/dist/two-d/ui/markdown.js.map +0 -1
- package/dist/two-d/ui/markup.d.ts +0 -189
- package/dist/two-d/ui/markup.d.ts.map +0 -1
- package/dist/two-d/ui/markup.js +0 -387
- package/dist/two-d/ui/markup.js.map +0 -1
- package/dist/two-d/ui/reveal.d.ts +0 -41
- package/dist/two-d/ui/reveal.d.ts.map +0 -1
- package/dist/two-d/ui/reveal.js +0 -22
- package/dist/two-d/ui/reveal.js.map +0 -1
- package/dist/two-d/ui/theme.d.ts +0 -133
- package/dist/two-d/ui/theme.d.ts.map +0 -1
- package/dist/two-d/ui/theme.js +0 -122
- package/dist/two-d/ui/theme.js.map +0 -1
- package/dist/two-d/ui/themedText.d.ts +0 -20
- package/dist/two-d/ui/themedText.d.ts.map +0 -1
- package/dist/two-d/ui/themedText.js +0 -9
- package/dist/two-d/ui/themedText.js.map +0 -1
- package/dist/version.d.ts +0 -13
- package/dist/version.d.ts.map +0 -1
- package/dist/version.js +0 -13
- package/dist/version.js.map +0 -1
- package/dist/world/Encounters.d.ts +0 -32
- package/dist/world/Encounters.d.ts.map +0 -1
- package/dist/world/Encounters.js +0 -9
- package/dist/world/Encounters.js.map +0 -1
- package/dist/world/Environment.d.ts +0 -58
- package/dist/world/Environment.d.ts.map +0 -1
- package/dist/world/Environment.js +0 -89
- package/dist/world/Environment.js.map +0 -1
- package/dist/world/Overworld.d.ts +0 -39
- package/dist/world/Overworld.d.ts.map +0 -1
- package/dist/world/Overworld.js +0 -40
- package/dist/world/Overworld.js.map +0 -1
- package/dist/world/SideTurns.d.ts +0 -115
- package/dist/world/SideTurns.d.ts.map +0 -1
- package/dist/world/SideTurns.js +0 -138
- package/dist/world/SideTurns.js.map +0 -1
- package/dist/world/TurnClock.d.ts +0 -41
- package/dist/world/TurnClock.d.ts.map +0 -1
- package/dist/world/TurnClock.js +0 -49
- package/dist/world/TurnClock.js.map +0 -1
- package/dist/world/World.d.ts +0 -64
- package/dist/world/World.d.ts.map +0 -1
- package/dist/world/World.js +0 -91
- package/dist/world/World.js.map +0 -1
- package/dist/world/index.d.ts +0 -12
- package/dist/world/index.d.ts.map +0 -1
- package/dist/world/index.js +0 -7
- package/dist/world/index.js.map +0 -1
- package/sbom.cdx.json +0 -5996
- package/tools/mwl.mjs +0 -466
- package/tools/vendored/rgssad-wasm/LICENSE-MIT +0 -21
- package/tools/vendored/rgssad-wasm/README.md +0 -15
- package/tools/vendored/rgssad-wasm/package.json +0 -17
- package/tools/vendored/rgssad-wasm/rgssad_wasm.d.ts +0 -41
- package/tools/vendored/rgssad-wasm/rgssad_wasm.js +0 -6
- package/tools/vendored/rgssad-wasm/rgssad_wasm_bg.js +0 -399
- package/tools/vendored/rgssad-wasm/rgssad_wasm_bg.wasm +0 -0
- package/tools/vendored/rgssad-wasm/rgssad_wasm_bg.wasm.d.ts +0 -17
- package/tools.md +0 -219
package/CHANGELOG.md
DELETED
|
@@ -1,3196 +0,0 @@
|
|
|
1
|
-
# Changelog
|
|
2
|
-
|
|
3
|
-
All notable changes to `mwg` are documented here. Format follows
|
|
4
|
-
[Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and versioning follows
|
|
5
|
-
[Semantic Versioning](https://semver.org/) as of this first release - a 0.y.z version means
|
|
6
|
-
the public API may still change between minor versions.
|
|
7
|
-
|
|
8
|
-
## [Unreleased]
|
|
9
|
-
|
|
10
|
-
## [0.44.2] - 2026-10-17
|
|
11
|
-
|
|
12
|
-
Hardening of `.mwp` content package loading, found by security reviews of 0.44.0 and 0.44.1.
|
|
13
|
-
Versions 0.44.0 and 0.44.1 were tagged and released on GitHub but their npm stages were rejected and
|
|
14
|
-
they were never published, so 0.44.2 is the first public release of everything in their entries below.
|
|
15
|
-
|
|
16
|
-
### Fixed
|
|
17
|
-
|
|
18
|
-
- A WAV header with a zero sample rate or block align fell back to its declared `byteRate`, so
|
|
19
|
-
a lying header could still shorten the measured duration. The rate is now the lowest of the
|
|
20
|
-
declared one, `sampleRate * blockAlign` and `sampleRate * channels * ceil(bits / 8)`, and a zero in
|
|
21
|
-
any of them refuses the file as unreadable.
|
|
22
|
-
|
|
23
|
-
## [0.44.1] - 2026-10-17
|
|
24
|
-
|
|
25
|
-
> Superseded by 0.44.2 and never published to npm.
|
|
26
|
-
|
|
27
|
-
Hardening of `.mwp` content package loading, found by a security review of 0.44.0.
|
|
28
|
-
|
|
29
|
-
### Fixed
|
|
30
|
-
|
|
31
|
-
- A package could multiply its work through repeated file imports: depth was bounded at 4 but
|
|
32
|
-
the total was not. Imports now share a budget of 64 reads per package document.
|
|
33
|
-
- An import or a `main` document named like an `Object.prototype` member (`constructor`) crashed
|
|
34
|
-
the loader with a `TypeError`; lookups are now own-property only and report a
|
|
35
|
-
`PackageFormatError`.
|
|
36
|
-
- A WAV header declaring a large `byteRate` could shorten the duration measured against
|
|
37
|
-
`maxAudioSeconds`; the lower of the declared rate and `sampleRate * blockAlign` is used.
|
|
38
|
-
|
|
39
|
-
## [0.44.0] - 2026-10-17
|
|
40
|
-
|
|
41
|
-
> Superseded by 0.44.2 and never published to npm.
|
|
42
|
-
|
|
43
|
-
Retro-audio integration contracts (a MIDI engine registry, streaming playback, budgets, content packages and a command line tool), player-facing audio settings, and the interface follow-ups of the last Pontifex round. The parked items 393, 394, Syzygy and NNUE are closed rather than waiting on files or weights that will not arrive, and a simplification pass over the whole tree removes duplicated code.
|
|
44
|
-
|
|
45
|
-
### Added
|
|
46
|
-
|
|
47
|
-
- Pontifex follow-up points 51-54 (roadmap 443-446): `ScrollBox` now owns its `hitArea`
|
|
48
|
-
(its viewport, kept current by `resize`/`setContentHeight`, with a `viewportWidth`
|
|
49
|
-
getter); `DropdownView` and `ScrollText` gain `resize(width)`, and `DropdownViewOptions`
|
|
50
|
-
gains `maxWidth` capping `autoWidth`; a transition requested while one is playing is
|
|
51
|
-
ignored by default, with `queue: true` / `interrupt: true` in `TransitionOptions` and the
|
|
52
|
-
`transitionDisposition` rule exported, `Game.transitioning` also reporting a queued
|
|
53
|
-
transition; and `Dropdown.setHighlight` now opens the list as documented, so
|
|
54
|
-
`setHighlight(i); confirm()` picks a row and the next opening shows it.
|
|
55
|
-
- Retro-audio integration (roadmap 431-442): a named `MidiSynth` engine
|
|
56
|
-
registry with fallback diagnostics, the streaming `Playable` contract, bus render budgets
|
|
57
|
-
and decoder guards, `.mwp` content packages with capability policy and ROM refusal, data
|
|
58
|
-
sound effects, an off-main-thread audio host, adaptive music, the `mwg-audio` tool, and
|
|
59
|
-
the `testing` doubles (`FakeRetroPlayer`, fake WebAudio graph) - documented in the
|
|
60
|
-
README's "Retro audio" section, REFERENCE and `docs/listening-protocol.md`. Player-facing
|
|
61
|
-
settings (`AudioSettings` with PAL/NTSC, dynamics and softening rules), live Web MIDI
|
|
62
|
-
(`connectWebMidi`), dropped `.syx` banks with DX7 patch names and audition (`SyxBank`),
|
|
63
|
-
and the oscilloscope/tracker data cores (`waveformEnvelope`, `trackerPattern`) complete
|
|
64
|
-
item 441.
|
|
65
|
-
|
|
66
|
-
### Changed
|
|
67
|
-
|
|
68
|
-
- Simplification pass over the tree, with no change to the public API: one shared radix-2 FFT
|
|
69
|
-
in `audio`, `HexSkirmish.reachableCosts` built on `core`'s `weightedFlood` (a negative
|
|
70
|
-
terrain move cost is now ignored instead of accepted), `tourney` and `Tactics` using the
|
|
71
|
-
`Engine` job default and `core`'s `cellInside`, a single byte-joining helper in the
|
|
72
|
-
`mwl` package container, and hand-written clamps replaced by `core`'s `clamp` across
|
|
73
|
-
`ui`, `render`, `battle`, `physics` and `audio`.
|
|
74
|
-
- Roadmap: items 393 (Ableton and Reaper groove formats), 394 (the Magenta humanizer tier),
|
|
75
|
-
Syzygy and NNUE are closed; 401 is the only numbered item left, waiting on a port session.
|
|
76
|
-
|
|
77
|
-
## [0.43.0] - 2026-10-17
|
|
78
|
-
|
|
79
|
-
Scrolling, tooltips and screen transitions for interface-heavy games, a MIDI music player and
|
|
80
|
-
SoundFont tooling, and the shipped command line tools made to work from an installed package on
|
|
81
|
-
Node 20.19. `@datamoc/pyroeis` moves to 0.9.1, which ends the last moderate audit advisory.
|
|
82
|
-
|
|
83
|
-
### Added
|
|
84
|
-
|
|
85
|
-
- Scrolling and transitions asked for by a bridge game (Pontifex feedback 45-50):
|
|
86
|
-
- `ScrollBox`: `touch` (drag to scroll, coasting on release, `ScrollDrag`), `handleKey` for line, page and
|
|
87
|
-
ends, a draggable scrollbar thumb and a clickable track, and `autoHeight`. A drag no longer clicks the row
|
|
88
|
-
it ends on.
|
|
89
|
-
- `DropdownView`: `maxVisibleRows` (the list scrolls), an opaque backdrop, `autoWidth`, opening with the chosen
|
|
90
|
-
row in view, `handleKey`, `handleOutsideClick` and `fitBelow`.
|
|
91
|
-
- `ScrollText` (a wrapped label that sizes itself and scrolls), `MarqueeLabel` (a long line sliding inside
|
|
92
|
-
its width, still under reduced motion), `ellipsize` and `truncateLines`.
|
|
93
|
-
- `TooltipHost`: tooltips on a touch long-press and on disabled buttons, from rectangles instead of pointer
|
|
94
|
-
events. `Button` gains `tooltip`, `setIcon` and a second icon for the selected state (`iconSelected`).
|
|
95
|
-
- `Game.switchScene(Next, { transition, duration, easing, pause })`, `Game.transition(swap, options)` and
|
|
96
|
-
`Scene2D.transitionTo`: `tileShrink`, `shrink`, `pop`, `grow`, `slide`, `iris` and `dissolve` over a snapshot of
|
|
97
|
-
the outgoing scene, skipped under reduced motion, with `Game.transitioning` and `Game.active`. `Window.open`
|
|
98
|
-
and `Window.close` take an animation (`pop`, `grow`, `slide`, `fade`). The bridge example switches level
|
|
99
|
-
with `tileShrink`.
|
|
100
|
-
- The dist grew 3.8% with them; the size baseline is moved to match.
|
|
101
|
-
- `limits` (`SoundFontLimits`: `sampleFrames`, `totalFrames`) on `decodeSoundFont`, `loadSoundFont` and
|
|
102
|
-
`webAudioSampleDecoder` raises or lowers what a SoundFont 3 may decode to, instead of the fixed 16 M
|
|
103
|
-
frames per sample and 128 M per font. The sample-rate bounds stay: the format itself stops at 50 kHz.
|
|
104
|
-
- `@example`s for the `3d` functions that need no renderer (`gridPoint3D`, `cellAt`, `heightAt`,
|
|
105
|
-
`buildHeightIndex`, `resolveCapsuleAgainstGrid`, `parseVox`). The generated API reference now covers
|
|
106
|
-
the subpaths the root barrel does not re-export (`3d`, `physics`, `ai/lua`, `mwl/pyroeis`, `testing`,
|
|
107
|
-
`threads`, `headless`, `assets/binary`), so the examples index links 803 of 813 symbols to a page.
|
|
108
|
-
- `npm run build:bridge-tutorial` regenerates the bridge tutorial from `tools/templates` and the example's
|
|
109
|
-
own source. `npm run bins:smoke` packs the project, installs it in an empty folder and runs every `mwg-*`
|
|
110
|
-
bin with `--help`; CI runs it, with the library build, on Node 20.19.0, the floor `engines` claims.
|
|
111
|
-
- `.gitattributes` (`* text=auto eol=lf`) ends the CRLF warnings on Windows checkouts.
|
|
112
|
-
- An optional, reproducible 314 KB SoundFont subset covering six essential presets,
|
|
113
|
-
with provenance and synthetic fallback for the instruments outside it.
|
|
114
|
-
- `AudioBus` loads embedded audio and MIDI by default through `createAudioLoader`, with
|
|
115
|
-
shared decoding, worker MIDI rendering and optional SoundFont settings across lifetimes.
|
|
116
|
-
- `MusicPlayer` controls rendered MIDI or decoded buffers with pause, resume, seek,
|
|
117
|
-
volume and a track-completion signal; `toAudioBuffer` copies rendered stereo samples
|
|
118
|
-
into a Web Audio buffer. The README shows the supplied SoundFont and worker playback path.
|
|
119
|
-
- Page byte budgets and potentially unused asset reports in the standalone build pipeline.
|
|
120
|
-
- XPBD link payloads, explicit rupture, geometric queries and state comparison helpers.
|
|
121
|
-
- Schema-directed `nodesToObjects` conversion and optional literal unions generated from
|
|
122
|
-
MWL table columns. Optional attributes are documented alongside the schema.
|
|
123
|
-
- Generated starter projects include a pre-commit hook for typecheck and tests, an activation
|
|
124
|
-
command and ignores for local agent state.
|
|
125
|
-
- Sawtooth sound synthesis, playback attempt counts and a shared browser test exposure hook.
|
|
126
|
-
|
|
127
|
-
### Fixed
|
|
128
|
-
|
|
129
|
-
- `mwg-uci`, `mwg-openings` and `mwg-tablebases` imported `../src/...`, which the package does not ship, so
|
|
130
|
-
they failed in every installed copy; they load `dist` there, as the other tools already did.
|
|
131
|
-
- The bridge example keeps a saved best only when the new crossing costs less, or costs the same and sags
|
|
132
|
-
less, instead of replacing it by any cheaper one.
|
|
133
|
-
- Fixed waits that failed on a loaded machine: the browser smoke waits for drawn frames instead of 250 ms,
|
|
134
|
-
the driver test polls for its tap instead of sleeping 300 ms, and the WebP noise test is seeded.
|
|
135
|
-
|
|
136
|
-
## [0.42.0] - 2026-10-16
|
|
137
|
-
|
|
138
|
-
The documentation and asset follow-ups to 0.41.0: SVG minification, a policy for the instruments a
|
|
139
|
-
SoundFont lacks, a playable bridge game with its tutorial, an examples index, and function-level
|
|
140
|
-
examples. One behaviour changes: a drum kit a font lacks now falls back to the standard kit instead of
|
|
141
|
-
a melodic preset.
|
|
142
|
-
|
|
143
|
-
### Added
|
|
144
|
-
|
|
145
|
-
- Function-level `@example`s where the examples used to sit on a file or an interface, so an
|
|
146
|
-
editor's hover shows them: `SaveSystem` (with a migration), `parseDialogueLines`,
|
|
147
|
-
`parseTwee` (walking a story), `motionDuration` (reduced motion on a slide and on a
|
|
148
|
-
meaningful bar) and `Theme` (a custom theme, `themeChanged`, the high-contrast swap).
|
|
149
|
-
- `XpbdWorld` documents a bridge: a Warren truss with beams, a `tensionOnly` cable note and a
|
|
150
|
-
breaking load, tested to hold a light cart, break under a heavy one and repeat exactly.
|
|
151
|
-
- `REFERENCE.md` records what subsetting the bundled bank costs (piano and drums 264 KB,
|
|
152
|
-
eight essential programs 421 KB, sixteen 585 KB) and what plays for a program the font lacks.
|
|
153
|
-
- `svgo: true` on `compileResources`, `emitPage` and `mwgPage` (and `--svgo` on `mwg-emit`) minifies
|
|
154
|
-
embedded `.svg` assets through the optional `svgo` package, version 4 or newer, imported only when
|
|
155
|
-
used. Ids and the `viewBox` are left alone, a file is embedded optimised only when that is smaller,
|
|
156
|
-
and one svgo cannot parse fails the build by name. On the repository's own 30 SVGs: 13.6%
|
|
157
|
-
smaller, worst rendered pixel difference 1 in 255. `@datamoc/mw_games/tools/svg-optimise` is the
|
|
158
|
-
standalone half.
|
|
159
|
-
- `missingProgram: 'piano' | 'synth'` on `parseSoundFont`, `loadSoundFont` and
|
|
160
|
-
`renderMidiToBufferAsync`: what plays for a program the font lacks, the font's own piano as
|
|
161
|
-
before or the built-in synthesizer, so a game with a trimmed bank hears the synthesizer's timbre
|
|
162
|
-
for an instrument it did not ship instead of a piano line.
|
|
163
|
-
- `missingSoundFontPrograms` (`audio`) lists the programs a MIDI usage asks for that a SoundFont 2 or
|
|
164
|
-
3 does not carry. The asset compiler runs it: each embedded font's result has a `missing` list and
|
|
165
|
-
`mwg-emit` and `compile-resources` warn about them.
|
|
166
|
-
- `examples/bridge` and the "Build a bridge game" tutorial (`webpage/tutorials/bridge`): a playable
|
|
167
|
-
truss builder on `XpbdWorld` (three levels, a budget, cables, beams coloured by load, breaking),
|
|
168
|
-
a deterministic replay of the player's build through `Recorder`/`Player`, best results through
|
|
169
|
-
`SaveSystem`, reduced motion and the high-contrast theme. The simulation is renderer-free and
|
|
170
|
-
tested, every tutorial snippet is checked to appear verbatim in the example, and the interface
|
|
171
|
-
step points at `examples/mwl-presentation` for HUD and windows described as MWL content.
|
|
172
|
-
- An examples index (`tools/build-example-index.mjs`, written by `npm run webpage:docs` to
|
|
173
|
-
`documentation/examples.html`): for each public module every exported symbol with an `@example`,
|
|
174
|
-
its first lines and a link to its API page, plus the runnable examples that import the module.
|
|
175
|
-
|
|
176
|
-
### Fixed
|
|
177
|
-
|
|
178
|
-
- A request for a drum kit the font lacks falls back to the standard kit, never to a melodic
|
|
179
|
-
preset: it used to take the same program number from bank 0, so a font with a piano and no drums
|
|
180
|
-
played the piano where the kick should be.
|
|
181
|
-
|
|
182
|
-
## [0.41.0] - 2026-10-16
|
|
183
|
-
|
|
184
|
-
`microgm-opt` stays the default SoundFont, and a game that wants another one can now pick it:
|
|
185
|
-
a licence-classified catalogue of a per-instrument collection, a tool that fetches only the
|
|
186
|
-
instruments the game plays, and SoundFont 3 support from the build to the browser, so the
|
|
187
|
-
font reaches the page compressed and is decoded at load.
|
|
188
|
-
|
|
189
|
-
### Added
|
|
190
|
-
|
|
191
|
-
- `mwg-soundfonts` (`list`, `fetch`, `convert`, and `@datamoc/mw_games/tools/soundfonts`):
|
|
192
|
-
`data/soundfont-catalog.json` lists the bundled bank and 18 fonts of the marmooo
|
|
193
|
-
free-soundfonts collection with each licence classified (public domain, permissive and
|
|
194
|
-
attribution fetch freely; share-alike, copyleft and unclear ones need `--accept-licence`;
|
|
195
|
-
TimGM6mb is listed as GPL-2.0 where the collection says public domain). `fetch` takes the
|
|
196
|
-
instruments named by `--midi` files or `--programs` and merges them into one SoundFont 3 with
|
|
197
|
-
a `.credits.txt` beside it: nothing is decoded, so no `ffmpeg`. `--sf2` and `convert` decode
|
|
198
|
-
to a plain SoundFont 2 instead (Ogg Vorbis through `ffmpeg`, a developer-machine tool), about
|
|
199
|
-
eight times larger.
|
|
200
|
-
- `loadSoundFont`, `decodeSoundFont` and `webAudioSampleDecoder` (`audio`): a game reads the
|
|
201
|
-
SoundFont 2 or 3 it ships with `loadSoundFont`, a SoundFont 3 decoded once at load through
|
|
202
|
-
`decodeAudioData` (each sample in a context at its own rate, so no resampling), or through a
|
|
203
|
-
decoder the caller passes. Checked in Chrome against `ffmpeg`: the same frames, rates and
|
|
204
|
-
loop points, and the same render. `decodeSoundFont` returns the SoundFont 2 bytes for
|
|
205
|
-
anything that takes them.
|
|
206
|
-
- `compileResources`, `emitPage` and `mwgPage` embed `.sf3` assets and subset them to the
|
|
207
|
-
programs the game's MIDI files use, the Ogg bytes copied untouched.
|
|
208
|
-
- `mergeSoundFonts` (`audio`): joins SoundFont 2 files, or SoundFont 3 files with their Ogg
|
|
209
|
-
bytes untouched, into one, the first font winning a shared (bank, program).
|
|
210
|
-
|
|
211
|
-
### Fixed
|
|
212
|
-
|
|
213
|
-
- `parseSoundFont` refuses a SoundFont 3 by name (pointing at `loadSoundFont`) instead of
|
|
214
|
-
reading its Ogg bytes as PCM and playing noise.
|
|
215
|
-
- A SoundFont whose sample offsets point outside its sample data is refused when read, rather
|
|
216
|
-
than read beyond it.
|
|
217
|
-
- Decoding a SoundFont 3 bounds what the file can make it allocate: a sample rate outside 400 to
|
|
218
|
-
200000 Hz is refused, a decoded sample is capped at sixteen million frames and a whole font at
|
|
219
|
-
134 million (256 MB of audio), in both `decodeSoundFont` and the WebAudio decoder.
|
|
220
|
-
- `mwg-soundfonts` treats the font as untrusted input: a sample whose offsets point outside the
|
|
221
|
-
sample data is refused instead of copied from beyond it, and `ffmpeg` only ever receives bytes
|
|
222
|
-
that start with the Ogg magic, with the demuxer forced to Ogg and only the `pipe` protocol
|
|
223
|
-
allowed, so a crafted "sample" cannot be probed as a playlist that names local files.
|
|
224
|
-
|
|
225
|
-
## [0.40.1] - 2026-10-15
|
|
226
|
-
|
|
227
|
-
The published package now carries its documentation the way npm expects to find it: a
|
|
228
|
-
homepage that opens the documentation site, the reference and the tools guide inside the
|
|
229
|
-
tarball, declared Node support, and a `--help` on every command line tool.
|
|
230
|
-
|
|
231
|
-
### Added
|
|
232
|
-
|
|
233
|
-
- `package.json` declares `homepage` (the documentation site, so `npm docs` opens it
|
|
234
|
-
instead of the GitHub README), `bugs` and `engines` (`node >=20.19.0`), and exports
|
|
235
|
-
`./package.json` so a tool can read an installed module's metadata. `@datamoc/mwg`
|
|
236
|
-
inherits all of them, plus the keywords it lacked.
|
|
237
|
-
- `REFERENCE.md` and `tools.md` ship in the tarball, so the README's relative links
|
|
238
|
-
resolve offline from `node_modules`.
|
|
239
|
-
- `REFERENCE.md` sections for `skeleton`, `physics` and `mwl/pyroeis`.
|
|
240
|
-
- JSDoc on the exported symbols of the least documented entry points
|
|
241
|
-
(`mwl/presentation`, `ai/lua`, `physics/xpbd`, `two-d/presentation`, `3d`, `mwl/pyroeis`,
|
|
242
|
-
`physics`).
|
|
243
|
-
|
|
244
|
-
### Fixed
|
|
245
|
-
|
|
246
|
-
- `mwg-bench`, `mwg-size`, `mwg-sbom`, `mwg-lockstep-server`, `mwg-mwl`, `mwg-uci` now print
|
|
247
|
-
their usage for `--help` instead of running. `mwg-init --help` no longer creates a folder
|
|
248
|
-
named `--help`, `mwg-scenarios --help` no longer hangs, and `mwg-placeholder-assets --help`
|
|
249
|
-
no longer rewrites the assets.
|
|
250
|
-
|
|
251
|
-
## [0.40.0] - 2026-10-15
|
|
252
|
-
|
|
253
|
-
A game that plays sampled MIDI no longer ships a whole SoundFont: the asset
|
|
254
|
-
compiler subsets the bank to the instruments its tracks actually use, and the
|
|
255
|
-
package now carries a small WTFPL General MIDI bank to subset from.
|
|
256
|
-
|
|
257
|
-
### Added
|
|
258
|
-
|
|
259
|
-
- Build-time SoundFont subsetting: `compileResources`, `emitPage` and `mwgPage` now
|
|
260
|
-
embed `.mid`/`.midi` and `.sf2` assets, and every embedded SoundFont is subset to
|
|
261
|
-
the programs the embedded MIDI files actually use (`collectSoundFontUsage` over
|
|
262
|
-
the shipped tracks, drums as bank 128). `soundFont: false` embeds a font whole,
|
|
263
|
-
`soundFontUsage` (or `--soundfont-usage=bank:program,...`) names the programs
|
|
264
|
-
explicitly, and a font with no shipped MIDI embeds whole. An unreadable MIDI or
|
|
265
|
-
SoundFont fails the build by name instead of shipping silently. The result and
|
|
266
|
-
both CLIs report each font's kept programs and byte saving: the reference bank
|
|
267
|
-
`data/microgm-opt.sf2` (2.6 MB, 137 presets, WTFPL, shipped in the npm package
|
|
268
|
-
for a game to copy into its assets) embeds as 25 KB for a piano-only track.
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
## [0.39.1] - 2026-10-15
|
|
272
|
-
|
|
273
|
-
Fixes the 0.39.0 publish gate on Linux: the WebP skip-shrink test asserted one
|
|
274
|
-
platform's encoder answer instead of the real guarantee, and failed where sharp
|
|
275
|
-
genuinely shrinks the noise fixture.
|
|
276
|
-
|
|
277
|
-
### Fixed
|
|
278
|
-
|
|
279
|
-
- The WebP test embeds whichever encoding is smaller and asserts byte-exact output
|
|
280
|
-
with a lossless round-trip either way, instead of assuming the conversion always
|
|
281
|
-
loses on tiny noise.
|
|
282
|
-
|
|
283
|
-
## [0.39.0] - 2026-10-15
|
|
284
|
-
|
|
285
|
-
The skeleton cluster (two-bone IK, joint limits, full clip channels, diagnostics, SVG
|
|
286
|
-
parts loading), the asset and deformation cluster (pinned deformation, SVG skeletons,
|
|
287
|
-
asset filtering and the embedded assets report), and the effects cluster (cloth, spring,
|
|
288
|
-
haze and neon glow, each with a stated frame budget and reduced-motion handling).
|
|
289
|
-
`PhysicsWorld` leaves `matter-js` behind for an in-repo solver, so the dependency is gone.
|
|
290
|
-
|
|
291
|
-
### Added
|
|
292
|
-
|
|
293
|
-
- Pinned sprite deformation with atomic vertex batches and one GPU upload per batch, checked
|
|
294
|
-
against a local Pontifex bird with fixed attachments and unchanged UVs.
|
|
295
|
-
- `loadSvgSkeleton`: SVG limb extraction, authored/manifest pivots, rest-angle normalization
|
|
296
|
-
and automatic `SkeletalSprite` binding, including nested parts without duplicate drawing.
|
|
297
|
-
- `assetFiles` on `mwgPage`, `emitPage` and `compileResources`: exact embedding lists with
|
|
298
|
-
named failures for unknown entries and unchanged defaults when omitted.
|
|
299
|
-
- `mwg-assets` (`assetReport`): per-file raw/gzip/brotli weights with each share of
|
|
300
|
-
the compressed page, plus the embedded source inventory with byte-identical
|
|
301
|
-
duplicates grouped by hash.
|
|
302
|
-
|
|
303
|
-
- Two-bone skeleton IK with named unreachable-target failures, absolute local joint limits,
|
|
304
|
-
and translation/scale clip channels through `sampleTransformPose` and `advancePose`.
|
|
305
|
-
- Explicit `SkeletalSprite.setDiagnostics` overlay for bones, pivots, joints and tips.
|
|
306
|
-
- `loadSvgParts` / `releaseSvgParts`: named SVG group textures with resolution-aware caching,
|
|
307
|
-
compiled local-file asset support and a browser check against a local Pontifex vehicle.
|
|
308
|
-
|
|
309
|
-
- Pinned-point cloth (`Cloth` Verlet mesh plus textured `ClothSprite` on the 414 mesh
|
|
310
|
-
path) with gravity, wind, damping and a browser drape check; a damped 2D chase
|
|
311
|
-
`Spring` for secondary motion with a stated O(1) frame budget, plus a `SpringSprite`
|
|
312
|
-
debug line.
|
|
313
|
-
- `HazeLayer` (with `hazeField` / `paintHazePixels`): drifting atmospheric sheets on
|
|
314
|
-
stacked depth planes, checked in the browser over a painted harbour; `NeonGlow`
|
|
315
|
-
(with `glowFalloff` / `paintGlowPixels`): additive neon light with colour, radius,
|
|
316
|
-
intensity and flicker, checked in the browser over a dark lane of signs.
|
|
317
|
-
|
|
318
|
-
### Removed
|
|
319
|
-
|
|
320
|
-
- The `matter-js` (and `@types/matter-js`) dependency: `PhysicsWorld` is recoded in TypeScript in this repo (semi-implicit Euler, impulse contacts, projected distance joints) with the same options, methods and signals. Bodies no longer spin: `angle` stays a display offset. The dropped `engine` field exposed the whole matter engine; nothing in this repo used it.
|
|
321
|
-
### Fixed
|
|
322
|
-
|
|
323
|
-
- SVG group splitting retains group transforms, shared definitions and styles, and handles
|
|
324
|
-
nested self-closing groups. Skeleton creation reports cycles instead of overflowing the stack.
|
|
325
|
-
|
|
326
|
-
## [0.38.0] - 2026-10-14
|
|
327
|
-
|
|
328
|
-
Optional MWL scene and UI composition with its bridge-editor example, the
|
|
329
|
-
all-scenarios browser verifier, instance palette setters, and a powered-by badge
|
|
330
|
-
games can carry on their login screen. Roadmap 393 and 394 move to parked: no
|
|
331
|
-
fixture files for the proprietary groove formats, and the neural humanizer costs
|
|
332
|
-
more than the game use case justifies.
|
|
333
|
-
|
|
334
|
-
### Added
|
|
335
|
-
|
|
336
|
-
- Optional MWL presentation compiler (`mwl/presentation`) and Pixi runtime
|
|
337
|
-
(`two-d/presentation`): scene layers, camera, reusable UI, responsive layouts, keyed
|
|
338
|
-
collections, typed bindings and biome-selected palette/scenery overrides. The local-file
|
|
339
|
-
bridge-editor example checks keyboard/pointer focus, modal input, cleanup and update cost.
|
|
340
|
-
- `Button.setColors`, `Window.setColors` and `Bar.setBackground` update instance palettes
|
|
341
|
-
without rebuilding widgets.
|
|
342
|
-
|
|
343
|
-
- `mwg-scenarios`: verifies every scenario in one local-file browser page through game-owned
|
|
344
|
-
`SceneControls` steps for entry, bot turns, assertions and cleanup, with bounded execution
|
|
345
|
-
and per-scenario failures.
|
|
346
|
-
- `webpage/assets/powered-by-mwg.svg`: a badge games can copy onto their login screen,
|
|
347
|
-
linked to the framework site, with the snippet in the README's new "Powered by mwg"
|
|
348
|
-
section and the badge itself in the website footer.
|
|
349
|
-
|
|
350
|
-
## [0.37.0] - 2026-10-14
|
|
351
|
-
|
|
352
|
-
Fixes and additions from the first outside game built on mwg (Pontifex, on 0.36.0): sounds compose with synthesized tones, two physics modules (matter-js rigid bodies and a deterministic XPBD structure solver), pointer and dropdown widgets, a project scaffold, and the `@datamoc/mwg` short-name package.
|
|
353
|
-
|
|
354
|
-
### Added
|
|
355
|
-
|
|
356
|
-
- `audio.synthesizeSound(tone, options)`: a pooled `Sound` over a synthesized tone.
|
|
357
|
-
- `core.FixedStepper`: turns the variable frame `dt` into fixed simulation steps with a substep cap.
|
|
358
|
-
- `core.StoredValue` and `core.defaultStorage` are public, so a game can keep structured JSON progress under one key.
|
|
359
|
-
- `Button.setSelected`, `Label.setWrapWidth`, `Window({ closeButton: true })` (a visible ✕), and `ui.flowLayout` (wrapping rows with alignment).
|
|
360
|
-
- `ParticleEmitter.burst(count, { x, y, tint })`, `Shape2D.dashedLine`, `Camera.fit(worldWidth, worldHeight)` and `SpriteSheet.strip(path, frames)`.
|
|
361
|
-
- `BrowserDriver.drag(fromX, fromY, toX, toY, steps)` on Chrome (CDP) and Firefox (in-page pointer events).
|
|
362
|
-
- `Input.attachPointer`: down, move, drag and up signals with target-relative and world positions.
|
|
363
|
-
- `physics.PhysicsWorld` (`@datamoc/mw_games/physics`, optional peer `matter-js`): rigid bodies, constraints, contact events and breakable joints (`maxStretch`, `onBreak`, `stretchOf`) on a fixed clock.
|
|
364
|
-
- `physics.XpbdWorld` (`@datamoc/mw_games/physics/xpbd`, no `matter-js`): a deterministic XPBD structure solver with per-link loads, breaking at a real strength and ground collision, extracted from Pontifex.
|
|
365
|
-
- `ui.DropdownView`, the widget over the `Dropdown` model.
|
|
366
|
-
- `mwg-init <folder>`: writes a starter project that builds to a double-clickable page.
|
|
367
|
-
- `assets/credits.json` becomes `CREDITS.txt` in the compiled output (`compileResources`, `creditsText`).
|
|
368
|
-
- `@datamoc/mwg`, the short name for the package, generated into `packages/mwg` by `npm run alias:write` (publishing it is a separate step).
|
|
369
|
-
- Roadmap 412 is the owner-only step left: publishing `@datamoc/mwg`.
|
|
370
|
-
|
|
371
|
-
### Changed
|
|
372
|
-
|
|
373
|
-
- `assets.resolve` returns a `data:` or `blob:` URL unchanged, so a synthesized tone or a runtime blob composes with `Sound`, `Music` and textures.
|
|
374
|
-
- `SpriteSheet.grid` warns when the frame size does not divide the sheet instead of cutting distorted frames silently.
|
|
375
|
-
- The README status line names the current version and the core row no longer calls the loop fixed-step.
|
|
376
|
-
|
|
377
|
-
### Fixed
|
|
378
|
-
|
|
379
|
-
- `compile-resources`, `compress-dist`, `play-uci`, `build-tablebases` and `compile-openings` took any importer whose file name was a suffix of theirs (`t.mjs` for `compress-dist.mjs`) for their own command line and ran it on import; they now compare real paths.
|
|
380
|
-
- A sound that is missing from the build plays as silence with a warning instead of rejecting inside `Game.start` and leaving a black screen.
|
|
381
|
-
- `tools/vite.mjs` and the build tools it imports no longer use top-level await, so a `vite.config.ts` in a project without `"type": "module"` loads.
|
|
382
|
-
- `mwgPage()` and the examples stop printing the `EMPTY_IMPORT_META` warning on every build.
|
|
383
|
-
|
|
384
|
-
## [0.36.1] - 2026-10-13
|
|
385
|
-
|
|
386
|
-
A maintenance release: the optional Lua dependency catches up with Pyroeis 0.9.0, and the CI no longer hangs on a stuck browser.
|
|
387
|
-
|
|
388
|
-
### Changed
|
|
389
|
-
|
|
390
|
-
- The optional `@datamoc/pyroeis` dependency moves from `^0.6.0` to `^0.9.0`. No API change on the mwg side.
|
|
391
|
-
- The Actions group is bumped (`actions/setup-node` 7.1.0 and `actions/upload-artifact`).
|
|
392
|
-
- The scheduled browser benchmark uses floors fit for a software-rendered runner (10 fps, p95 250 ms) instead of the GPU defaults it failed every week; the 15% history comparison still catches regressions.
|
|
393
|
-
|
|
394
|
-
### Fixed
|
|
395
|
-
|
|
396
|
-
- The browser driver kills the whole browser process group when it times out or closes, instead of only the launcher. Surviving helper processes held the output pipes and kept `npm test` alive until the runner's 6 hour limit.
|
|
397
|
-
- The browser start-up budget is 90 s and the CI `check` job is capped at 30 minutes; Linux Chrome runs with `--disable-dev-shm-usage --disable-gpu`.
|
|
398
|
-
|
|
399
|
-
## [0.36.0] - 2026-10-12
|
|
400
|
-
|
|
401
|
-
The optional Lua integration uses Pyroeis, with a matching public subpath, factories and types. Games using the Lua host must update their imports to `mwl/pyroeis` and the `Pyroeis` names.
|
|
402
|
-
|
|
403
|
-
### Changed
|
|
404
|
-
|
|
405
|
-
- Replace the optional `@datamoc/fengari` dependency with `@datamoc/pyroeis` `^0.6.0` and use `PyroeisVm`. Rename the public Lua subpath to `mwl/pyroeis`, the factories to `createPyroeisScriptHost` and `createPyroeisRuntime`, and all associated `Fengari*` types to `Pyroeis*`.
|
|
406
|
-
|
|
407
|
-
- Docs: the 1.0 checklist's ports line is restated as an external condition rather than an open box, `LuaAI` is described as the Lua 5.4 provider it is, and the Lua host's byte budget is described as the VM's per-call allocation limit rather than the `lua_setallocf` hook it no longer rides. The 0.35.0 entry names the `^0.5.2` range that release shipped with.
|
|
408
|
-
|
|
409
|
-
## [0.35.1] - 2026-10-11
|
|
410
|
-
|
|
411
|
-
The Lua host moves to `@datamoc/fengari` 0.5.4: tighter execution limits and a simpler `ScriptHost` setup.
|
|
412
|
-
|
|
413
|
-
### Changed
|
|
414
|
-
|
|
415
|
-
- The optional Lua dependency moves to `@datamoc/fengari` `^0.5.4`. The `ScriptHost` uses its `print: 'native'` option instead of building the VM without libraries and re-opening them, which also drops the `string.dump` and `__random` clean-up the re-open made necessary. Execution limits now also hold against a limit overrun hidden by a script-created coroutine, global-path lookups and `Coroutine#close()`.
|
|
416
|
-
|
|
417
|
-
## [0.35.0] - 2026-10-11
|
|
418
|
-
|
|
419
|
-
A Lua integration host for games that need synchronous API results and resumable dialogue, an offline Lua to JavaScript translator, and the Lua dependency moves to `@datamoc/fengari` 0.5.2.
|
|
420
|
-
|
|
421
|
-
### Added
|
|
422
|
-
|
|
423
|
-
- `createFengariRuntime` on the optional `mwl/fengari` subpath: synchronous host functions with results, live indexed table bindings, owned Lua callback/table references, embedded `require`/`dofile`, and host-driven coroutines with request values and scene answers. `luaToJs` translates Lua source to readable JavaScript offline (fengari 0.5.0's `lua2js`), flagging untranslatable constructs, for a game leaving Lua scripting. The existing JSON-only `ScriptHost` stays unchanged. Calls, module compilation and coroutine resumes share bounded execution, with a fresh budget for each top-level operation.
|
|
424
|
-
|
|
425
|
-
### Changed
|
|
426
|
-
|
|
427
|
-
- The optional Lua dependency moves to `@datamoc/fengari` `^0.5.2`, whose shipped TypeScript declarations replace the old `@ts-expect-error` import and the hand-written `luaToJs` types, and whose `vm.protect` and `vm.throwLuaError` replace the host-side protected-call code. The host reuses `FengariVm`'s execution guard while retaining text-only compilation, JSON-shaped tables and seeded randomness.
|
|
428
|
-
|
|
429
|
-
### Fixed
|
|
430
|
-
|
|
431
|
-
- Lua instruction limits now interrupt native table moves and string searches, and cannot be swallowed by `pcall`, `xpcall` message handlers or coroutine resumes. Parsing and execution still share the per-call string/buffer allocation budget. The `ScriptHost` sandbox also drops `string.dump` and fengari's internal `__random`, which scripts could still reach.
|
|
432
|
-
|
|
433
|
-
## [0.34.0] - 2026-10-10
|
|
434
|
-
|
|
435
|
-
Hex grids for the cave, dungeon and overworld generators, and the Lua host moves to the `@datamoc/fengari` 0.3.0 fork (`<const>`, `<close>`, `coroutine.close`).
|
|
436
|
-
|
|
437
|
-
### Added
|
|
438
|
-
|
|
439
|
-
- `shape: 'hex'` on `generateDungeon`/`generateDungeonGraph`, `generateCave` and `generateOverworld`: the generators lay their output out on a hex grid (odd-q offsets, as `Level` does) instead of squares. The dungeon and cave `Level` carry the hex shape; a dungeon corridor leg runs as a hex line and `furthestRoom` counts hex steps on a hex level; a cave grows chambers by hex distance and walks passages by true on-screen distance, so a chamber is round rather than a skewed diamond; the overworld samples its value noise where each hex is drawn and steps rivers and roads across the six edges, with settlement spacing and the near-water test in hex steps. Square output is unchanged byte for byte.
|
|
440
|
-
- `generateCave` accepts `random`, a `RandomSource`, in place of `seed`: the cave draws from that stream and advances it, and the ambient `Random` stack is left alone. Passing neither is refused by name.
|
|
441
|
-
|
|
442
|
-
### Changed
|
|
443
|
-
|
|
444
|
-
- `@datamoc/fengari` moves to `^0.3.0`. Lua scripts in `mwl/fengari` and `ai/lua` now accept `<const>` and `<close>` variables and `coroutine.close`; a limit error (instructions or memory) unwinds through pending `__close` handlers, and a handler cannot buy extra instructions after the limit fired.
|
|
445
|
-
|
|
446
|
-
### Fixed
|
|
447
|
-
|
|
448
|
-
- `mwg_emit(name, payload)` called from inside a coroutine read its payload from the main thread's stack, so it returned garbage or failed; it now reads from the calling coroutine.
|
|
449
|
-
|
|
450
|
-
## [0.33.0] - 2026-10-10
|
|
451
|
-
|
|
452
|
-
Seven roadmap items in one release: the Wesnoth port's proposal file is now fully answered
|
|
453
|
-
(405 shipped with 0.32.0, 406/407/409 this release, 408's first half, 401 parked with the
|
|
454
|
-
port), alongside the skeletal puppet pair (399/400), SVG as inbound data (398), the overworld
|
|
455
|
-
generator (410), and the Lua host riding the fork's new allocation hook.
|
|
456
|
-
|
|
457
|
-
### Added
|
|
458
|
-
|
|
459
|
-
- `skeleton`, a new renderer-free root module (roadmap 399): a bone tree where a pose is one
|
|
460
|
-
rotation per bone, keyframed clips (plain JSON, interpolation, looping, playback rate,
|
|
461
|
-
crossfade), and additive layers mixing by priority that displace only the bones they name.
|
|
462
|
-
`two-d/render` gains the drawing half (400): `SkeletalSprite` binds parts to bones by
|
|
463
|
-
name, and `ArticulatedChain`/`ChainRig` draw a follower-rule spine with per-segment
|
|
464
|
-
rotation limits.
|
|
465
|
-
- `roguelike.generateCave` (407): chambers grown as blobs (`jagged`), winding passages
|
|
466
|
-
(`windiness`, `width`, `chance`), starts with cleared rings, village density, and a forced
|
|
467
|
-
join so a cave is always connected. `roguelike.generateOverworld` (410): seeded elevation
|
|
468
|
-
and moisture fields classify seven terrains behind a `seaLevel` knob, rivers run downhill
|
|
469
|
-
to the sea and drown lakes at ridges, settlements place themselves by suitability and join
|
|
470
|
-
into a road tree that prefers flat ground (water a ford, not a wall), points of interest
|
|
471
|
-
carry `leadsTo`, and every cell carries a coarse region id.
|
|
472
|
-
- `assets` SVG inbound rules (398): `sanitizeSvg` refuses what it cannot prove inert by name,
|
|
473
|
-
`svgScaleVariants` rasterizes one source per named scale, `splitSvgGroups` loads one part
|
|
474
|
-
per top-level `<g>` group.
|
|
475
|
-
- `testing` gains `createSceneControls` (408's first half): named steps a game opts into,
|
|
476
|
-
driven by name, refused by name when unknown - the seam a headless driver calls a game's
|
|
477
|
-
private scene flow through.
|
|
478
|
-
|
|
479
|
-
### Changed
|
|
480
|
-
|
|
481
|
-
- `mwl/fengari` now requires `@datamoc/fengari@^0.2.0` and enforces `memoryLimit` through the
|
|
482
|
-
fork's per-state allocation hook (`lua_setallocf`) instead of swapping the global
|
|
483
|
-
`Uint8Array` constructor mid-call: no global mutation (and so no reentrancy hazard between
|
|
484
|
-
hosts on one page), parsing is inside the budget, host callbacks allocate freely, and a
|
|
485
|
-
refused allocation surfaces to scripts as Lua's standard `not enough memory` while the
|
|
486
|
-
host still rejects the call.
|
|
487
|
-
- MWL `test=` expressions can call `have_unit`/`have_location` and registered predicate hooks
|
|
488
|
-
directly (406), `[while]` traces `while_limit` when its cap is reached with the condition
|
|
489
|
-
still true (`on_limit=error` makes it a hard failure), and `[condition]` accepts free
|
|
490
|
-
predicate attributes.
|
|
491
|
-
|
|
492
|
-
## [0.32.0] - 2026-10-10
|
|
493
|
-
|
|
494
|
-
The optional Lua host hardens around what the `@datamoc/fengari` fork offers, and the
|
|
495
|
-
phantom-leader bug the Wesnoth port's scenarios exposed is fixed.
|
|
496
|
-
|
|
497
|
-
### Changed
|
|
498
|
-
|
|
499
|
-
- `mwl/fengari` moves to the `@datamoc/fengari` fork (Lua 5.4) and opens only the
|
|
500
|
-
sandbox-safe Lua standard libraries (base, coroutine, math, string, table, utf8) through
|
|
501
|
-
the fork's `luaL_openselectedlibs`: `io`, `os`, `debug` and `package` with its `require`
|
|
502
|
-
are never constructed - identically in Node and the browser - instead of being opened and
|
|
503
|
-
then nil'd. Chunks now compile in text mode, so a binary `\x1bLua` dump is rejected instead
|
|
504
|
-
of reaching the bytecode undumper.
|
|
505
|
-
- Roadmap item 390 (the tourney chess engine) is closed by accepting its recorded split:
|
|
506
|
-
4-piece tablebases stay a `tools/build-tablebases.mjs` run away rather than shipping tens
|
|
507
|
-
of megabytes per ending; the compiled 3-piece tables stay under `data/tablebases`.
|
|
508
|
-
|
|
509
|
-
### Fixed
|
|
510
|
-
|
|
511
|
-
- `MwlRuntime` no longer spawns a phantom leader when a `[side]`'s `leader=` names an
|
|
512
|
-
already-declared unit: the named unit is the leader, a known unit type still spawns one
|
|
513
|
-
leader per free start cell with its real stats, and a value that is neither is refused by
|
|
514
|
-
name instead of creating a 1-hp, 0-move ghost (roadmap 405, which broke about ten of the
|
|
515
|
-
Wesnoth port's scenarios with "unknown unit type").
|
|
516
|
-
|
|
517
|
-
## [0.31.0] - 2026-10-09
|
|
518
|
-
|
|
519
|
-
Two pixel-dungeon proposals: P43, `SpriteMotion` (squash, hop, bob, wobble, spin, shear and flip over `Tweener`, reduced-motion aware), and P42, camera snapping in whole device pixels, which closes the thin tile seams at a fractional `devicePixelRatio`.
|
|
520
|
-
|
|
521
|
-
### Added
|
|
522
|
-
|
|
523
|
-
- `two-d/render` `SpriteMotion` (pixel-dungeon proposal P43): squash, hop, bob, wobble, spin,
|
|
524
|
-
shear and flip over any display object's transform, through a `Tweener`. Effects compose from
|
|
525
|
-
a captured rest pose, never drift, cancel cleanly, and follow `setReducedMotion` (a looping
|
|
526
|
-
bob holds still; `intent: 'meaningful'` is shortened instead of dropped).
|
|
527
|
-
|
|
528
|
-
### Fixed
|
|
529
|
-
|
|
530
|
-
- `Camera` rounded its screen offset to a whole CSS pixel, which at a fractional
|
|
531
|
-
`devicePixelRatio` (Windows at 150%) left thin seams between tiles. The offset now rounds to
|
|
532
|
-
whole device pixels through the new `CameraOptions.resolution` (supplied by `createCamera`,
|
|
533
|
-
read live), and `snapZoom` takes an optional `resolution` so `pixelPerfectTileSize` snaps to
|
|
534
|
-
whole device pixels too.
|
|
535
|
-
|
|
536
|
-
## [0.30.0] - 2026-10-07
|
|
537
|
-
|
|
538
|
-
P41, the browser driver's four measured gaps: the viewport option (inner size through the
|
|
539
|
-
protocol, not window flags), the trusted keyboard channel (press through CDP key events and
|
|
540
|
-
BiDi key actions, with the WebDriver key-value table), the Firefox tap that actually reaches
|
|
541
|
-
Pixi 8's EventSystem (the in-page synthetic sequence, measured and documented), and headed
|
|
542
|
-
mode. Live-verified on Chrome and Firefox: exact 800x600 viewport, keys delivered, the
|
|
543
|
-
Firefox tap advancing a real Pixi page.
|
|
544
|
-
|
|
545
|
-
## [0.29.0] - 2026-10-07
|
|
546
|
-
|
|
547
|
-
P37's touch half: the on-screen keyboard. Rows of keys as data, rendered through the
|
|
548
|
-
theme's own Button, each tap feeding the same core.Input paths a physical key travels -
|
|
549
|
-
dispatchText for a typing key, the new dispatchAction for an action key - so a TextPrompt
|
|
550
|
-
cannot tell the two apart. TextPrompt grows a keyboard option that hosts one beneath the
|
|
551
|
-
field and resizes the window to fit it, UPPERCASE_KEYBOARD is one shipped default, and
|
|
552
|
-
the interface example's Name prompt carries it as the reviewed touch pattern.
|
|
553
|
-
|
|
554
|
-
## [0.28.0] - 2026-10-07
|
|
555
|
-
|
|
556
|
-
The 0.27.0 consumer wave sharpened asks: the pixel-dungeon port proposal file
|
|
557
|
-
audited what 0.27 shipped against what a real consumer needs, and this release
|
|
558
|
-
closes the four framework-side gaps it found. Flights fades and spins in the
|
|
559
|
-
units games author (fadeIn: progress, spinDegrees), Beam thins as it fades and
|
|
560
|
-
stretches a single art asset along its span with anchor control,
|
|
561
|
-
ParticleEmitter.attach gates visibility (fog-of-war) beside emission, and the
|
|
562
|
-
interface example carries the reviewed TextPrompt hosting pattern a seed or name
|
|
563
|
-
prompt can be copied from.
|
|
564
|
-
|
|
565
|
-
### Added
|
|
566
|
-
|
|
567
|
-
- `Flights` fade and spin in the units consumers author them in (P40): `fadeIn:
|
|
568
|
-
'progress'` (or `true`) eases a sprite's alpha 0 to 1 along the flight's own
|
|
569
|
-
progress - the tween's clock, so the fade cannot desynchronise from a duration
|
|
570
|
-
the caller re-computed - while a number keeps its seconds-from-launch meaning,
|
|
571
|
-
and `spinDegrees` is `spin` in degrees per second, converted once, so an
|
|
572
|
-
authored angular speed needs no radian arithmetic at the call site.
|
|
573
|
-
|
|
574
|
-
- `Beam` thins and stretches (P35): `thin: true` narrows the body with its own
|
|
575
|
-
remaining life the way the alpha fades (a plain line's stroke, a strip's height,
|
|
576
|
-
a stretched sprite's `scale.y`), and the `texture` option's object form -
|
|
577
|
-
`{ source, stretch?, anchor? }` - stretches one art asset along the whole span
|
|
578
|
-
instead of tiling it, anchored across the thickness (0.5 by default) for ray
|
|
579
|
-
art that repeats badly. The bare-texture form tiles exactly as it always has.
|
|
580
|
-
|
|
581
|
-
- `ParticleEmitter.attach` takes a `visible` callback beside `enabled` (P36): a
|
|
582
|
-
false return hides the emitter and every particle it has in the air, so a
|
|
583
|
-
fog-of-war gate keeps an aura's spray out of unexplored space without the
|
|
584
|
-
consumer re-placing `visible` every frame. Drawing only - the simulation
|
|
585
|
-
keeps stepping behind the invisibility, emission keeps following `enabled`,
|
|
586
|
-
and `detach()` leaves the emitter visible.
|
|
587
|
-
|
|
588
|
-
- The interface example's new Name button is the reviewed `TextPrompt` hosting
|
|
589
|
-
pattern (P37): push it on a `WindowStack` and it owns typing, caret edits,
|
|
590
|
-
confirm-gated-by-`validate`, cancellation and closing - a seed or name prompt
|
|
591
|
-
with no DOM `<input>` overlay to copy around.
|
|
592
|
-
|
|
593
|
-
## [0.27.0] - 2026-10-07
|
|
594
|
-
|
|
595
|
-
Two strands in one release. A run is durable and drives the AI (roadmap 396-397): the
|
|
596
|
-
versioned replay envelope refuses another game or framework build by name, `LastRun` keeps
|
|
597
|
-
the newest recording, `runCheckpoint`/`resumeRunPlayer` restore a run mid-run, and the
|
|
598
|
-
`file://` plumbing (download, picker, Blob read) ships with it; `imitationFromReplay` turns
|
|
599
|
-
a recorded run into training samples against its own seeded environment, `runSeededEpisode`
|
|
600
|
-
plays a whole run from a named seed behind any deterministic chooser, and `ai.Suggester`
|
|
601
|
-
is the throttled, non-mutating hint source. The render and UI strand: `Flights` owns live
|
|
602
|
-
projectile flights, `Beam`/`Beams` draw one-shot beams, `TextPrompt` asks for one line with
|
|
603
|
-
IME and screen-reader support, `MessageLog.lastEntries` reads retained entries back, and
|
|
604
|
-
`ParticleEmitter.attach` follows a target; `core.FloatSource` narrows the injectable random
|
|
605
|
-
stream for float-only helpers.
|
|
606
|
-
|
|
607
|
-
### Added
|
|
608
|
-
|
|
609
|
-
- `core.FloatSource` splits `core.RandomSource`: helpers that draw floats only
|
|
610
|
-
(`float`, `chance`, `weighted`, `weightedKey`) accept the narrower
|
|
611
|
-
`{ float(): number }`, so a float-only stream needs no dead `int`. The
|
|
612
|
-
integer helpers (`int`, `range`, `normalRange`, `element`, `shuffle`) keep
|
|
613
|
-
requiring the full source; `element` stays wide deliberately, because it
|
|
614
|
-
draws through `int()` and re-spelling that draw would change its stream.
|
|
615
|
-
|
|
616
|
-
- `MessageLog.lastEntries(n)` reads the newest retained entries back as plain
|
|
617
|
-
`{ text, level }` records, oldest first, without scraping rendered children:
|
|
618
|
-
entries the wrapped-line budget already dropped are gone, over-count reads
|
|
619
|
-
everything retained, and zero or negative reads nothing. The slice lives in
|
|
620
|
-
the pure `takeLastEntries` beside the existing `linesToDrop` budget, so the
|
|
621
|
-
readback contract is testable without a renderer.
|
|
622
|
-
|
|
623
|
-
- `ParticleEmitter.attach(target)` follows a display object or position thunk on
|
|
624
|
-
every update tick and every `burst()`, with `offsetX`/`offsetY`, an `enabled`
|
|
625
|
-
callback gating tick emission, and auto-detach for destroyed targets;
|
|
626
|
-
`detach()` keeps the last position. The follow math is tested headless through
|
|
627
|
-
textureless emitters.
|
|
628
|
-
|
|
629
|
-
- `Flights` owns a scene's live projectile flights over the existing `Projectile`:
|
|
630
|
-
`add(sprite | texture, from, to, { speed, tint?, spin?, fadeIn?, onArrive? })`
|
|
631
|
-
returns a handle, `update(dt)` drives positions with per-flight spin and fade,
|
|
632
|
-
each arrival dispatches once after leaving the list, and `cancel()`/`clear()`
|
|
633
|
-
forget without dispatching. Caller sprites stay caller-owned; texture-built
|
|
634
|
-
sprites are parented here and destroyed with their flight.
|
|
635
|
-
|
|
636
|
-
- `Beam`/`Beams` draw one-shot beams between two screen points: a fading line by
|
|
637
|
-
default, a fading repeating texture strip with `texture`, additive blend unless
|
|
638
|
-
opted out, `retarget` for tracking endpoints, and `update` reporting expiry
|
|
639
|
-
exactly once so the `Beams` group can remove finished beams itself.
|
|
640
|
-
|
|
641
|
-
- `TextPrompt` asks for one line of text over a `TextModel`: typing through
|
|
642
|
-
`onText` (the newest open prompt wins), caret and edits through
|
|
643
|
-
`left`/`right`/`backspace`/`delete` actions, `confirm` gated by `validate` and
|
|
644
|
-
`cancel` giving up. IME compositions preview until they commit, and the
|
|
645
|
-
message plus validation errors announce through `screenReader` (assertive for
|
|
646
|
-
the errors), with an injectable announcer for tests.
|
|
647
|
-
|
|
648
|
-
- A run is durable now (roadmap 396): `exportReplayFile`/`importReplayFile` wrap a
|
|
649
|
-
recording in a versioned, self-describing envelope that refuses another game or
|
|
650
|
-
framework build by name, `LastRun` keeps the newest recording (one deep, bounded,
|
|
651
|
-
over the same storage a save slot uses), and `runCheckpoint`/`resumeRunPlayer`
|
|
652
|
-
pair the partial recording with the saved state so a restored run resumes mid-run
|
|
653
|
-
instead of restarting - `Recorder` and `Player` both take `fromFrame`, and
|
|
654
|
-
`parseReplayEvents` factors out the half of `deserializeReplay`'s check that
|
|
655
|
-
validates an already-parsed array. The `file://` plumbing rides along:
|
|
656
|
-
`downloadReplayFile` (a Blob download, never `fetch()`), `pickReplayFile`
|
|
657
|
-
(the file picker, null on cancel) and `readReplayFile` (any `Blob`, headless
|
|
658
|
-
Node included).
|
|
659
|
-
|
|
660
|
-
- Replays train and drive the AI (roadmap 397): `imitationFromReplay` walks a
|
|
661
|
-
recorded run against the same seeded `TrainingEnvironment` it was played on and
|
|
662
|
-
returns the `(observation, action)` samples a game's own trainer fits;
|
|
663
|
-
`runSeededEpisode` plays a whole run with any deterministic chooser (a heuristic,
|
|
664
|
-
a `NeuralPolicy`'s argmax, not just a `NeuralModel` like `runRollouts`) from a
|
|
665
|
-
named seed, recording every chosen action so runs compare across builds and
|
|
666
|
-
policies; and `ai.Suggester` is the in-game suggestion mode, the same decision
|
|
667
|
-
call pointed at a hint UI instead of the world, throttled by a frame-count budget
|
|
668
|
-
and never mutating state to compute a hint.
|
|
669
|
-
|
|
670
|
-
## [0.26.1] - 2026-10-07
|
|
671
|
-
|
|
672
|
-
The 0.26.0 follow-up: its Chrome end-to-end test failed on every CI run, so the
|
|
673
|
-
`tools/browser-driver` Chrome engine never actually worked on a CI machine (a cold
|
|
674
|
-
Windows runner never reached the debugging endpoint in the old budget; an Ubuntu
|
|
675
|
-
runner crashed in Chrome's sandbox). Chrome now launches against its own profile,
|
|
676
|
-
the endpoint is watched on both output streams with a cold-start budget and a
|
|
677
|
-
diagnostic that names what the browser printed, `close` releases the profile and
|
|
678
|
-
the stdio pipes only after the child exits, and the CI workflows pass
|
|
679
|
-
`--no-sandbox` on Linux through the driver's own `MWG_DRIVER_CHROME_ARGS` channel.
|
|
680
|
-
0.26.0 was tagged before this was known and its npm publish never ran.
|
|
681
|
-
|
|
682
|
-
### Fixed
|
|
683
|
-
|
|
684
|
-
- `tools/browser-driver`'s Chrome engine launches against its own profile
|
|
685
|
-
(`options.profileDir`, or a temp dir the driver creates and removes on `close`)
|
|
686
|
-
instead of the machine's default one, watches both stdout and stderr for the
|
|
687
|
-
debugging endpoint (which stream a build prints it on is not something to bet
|
|
688
|
-
on), waits up to 30 s instead of 15 (a cold CI machine's first Chrome start can
|
|
689
|
-
outrun the old budget), and names what the browser printed when the endpoint
|
|
690
|
-
never arrives. This is the fix for the Chrome end-to-end test failing on every
|
|
691
|
-
CI run since the driver landed: the default profile on a fresh runner never
|
|
692
|
-
reached the endpoint in time. `close` now also destroys the child's stdio
|
|
693
|
-
pipes (surviving browser helper processes could hold a suite open past the
|
|
694
|
-
browser's own death) and releases the profile only after the child exits.
|
|
695
|
-
The failing configuration is now diagnosed, not just reported: the timeout
|
|
696
|
-
names what the browser printed. CI's Linux jobs pass `--no-sandbox` through
|
|
697
|
-
the driver's `MWG_DRIVER_CHROME_ARGS` channel, since an Ubuntu 23.10+ runner
|
|
698
|
-
that disables unprivileged user namespaces is a property of that machine,
|
|
699
|
-
not of the tool.
|
|
700
|
-
|
|
701
|
-
## [0.26.0] - 2026-10-07
|
|
702
|
-
|
|
703
|
-
The machine-readable surface and the audit tooling around it: `api-surface.json` ships as the
|
|
704
|
-
`./api-manifest` subpath (one `{ name, kind, subpath, declaringModule }` row per export), the
|
|
705
|
-
blessed `mwg/headless` entry imports every renderer-free module in one line, `tools/audit-adoptions`
|
|
706
|
-
checks a consumer's imports and local definitions against that manifest, and the dependency-free
|
|
707
|
-
`tools/browser-driver` harness drives real Chrome and Firefox. `core` gained injectable `RandomSource`
|
|
708
|
-
streams for every derived helper and the shared square-grid rulers (`chebyshev`, `manhattan`,
|
|
709
|
-
`euclidean`, `distance` by `DistanceMetric`), the coverage gate now enforces `two-d/ui` instead of
|
|
710
|
-
excluding the whole tree, and the bundle-size baseline is refreshed for the growth those brought.
|
|
711
|
-
|
|
712
|
-
### Added
|
|
713
|
-
|
|
714
|
-
- Exported the types a public signature already names: `mwl` move/evolution/matchup
|
|
715
|
-
definitions, `core` achievement criteria and hex shape types, particle curve and spawn
|
|
716
|
-
area types, screen effect steps, `rpg` route targets, asset loader options, and the
|
|
717
|
-
`core.HttpTransport` base class its four clients already extend.
|
|
718
|
-
|
|
719
|
-
- `core.NEIGHBOURS4`/`NEIGHBOURS8`/`CIRCLE8` share one frozen square-grid offset table
|
|
720
|
-
instead of each module keeping its own: axial, row-major eight, and the clockwise ring
|
|
721
|
-
(`roguelike`'s `neighbourOffsets` returns these now); `core.euclidean` is the
|
|
722
|
-
straight-line ruler beside `roguelike`'s `chebyshevDistance`.
|
|
723
|
-
|
|
724
|
-
- `core.chebyshev` is the king-move ruler beside `euclidean` (a diagonal costs one
|
|
725
|
-
step) and `core.manhattan` the orthogonal-step count; `core.distance` measures with
|
|
726
|
-
the ruler a `DistanceMetric` names, so a data-authored rule picks its geometry by
|
|
727
|
-
name. `roguelike`'s `chebyshevDistance` delegates to `chebyshev` instead of spelling
|
|
728
|
-
the arithmetic out again.
|
|
729
|
-
|
|
730
|
-
- `api-surface.json` is the machine-readable API surface: one
|
|
731
|
-
`{ name, kind, subpath, declaringModule }` entry per export per subpath,
|
|
732
|
-
generated by the same `tools/api-report.mjs` pass that maintains
|
|
733
|
-
`API_REPORT.md`, shipped in the package behind the `./api-manifest` subpath,
|
|
734
|
-
and pinned by `tests/api-manifest.test.ts` (shape and coverage) plus the
|
|
735
|
-
existing `--check` (agreement with the declarations). `node
|
|
736
|
-
tools/api-report.mjs --diff OLD NEW` diffs two releases' surfaces, and the
|
|
737
|
-
report parser no longer drops `export type { ... }` re-export lists.
|
|
738
|
-
|
|
739
|
-
- `core.RandomSource` lets every derived helper (`chance`, `element`,
|
|
740
|
-
`weighted`, `weightedKey`, `shuffle`, `int`, `range`, `normalRange`) draw
|
|
741
|
-
from an injected stream: pass a rule-local `Generator` (or any
|
|
742
|
-
`float`/`int` pair) as the trailing `source` and the ambient stream is left
|
|
743
|
-
untouched, with identical draws and the same `null` reporting.
|
|
744
|
-
|
|
745
|
-
- `node tools/api-report.mjs --diff OLD NEW` lists added, removed and
|
|
746
|
-
kind-changed exports between two `api-surface.json` manifests, so a version
|
|
747
|
-
bump yields a one-command surface diff.
|
|
748
|
-
|
|
749
|
-
- `mwg/headless` is the blessed renderer-free entry: `core`, `simulation`,
|
|
750
|
-
`mwl`, `i18n`, `actors`, `world`, `battle`, `roguelike`, `board`, `audio`,
|
|
751
|
-
`rpg`, `ai`, `testing` and the two renderer-free asset halves, in one import
|
|
752
|
-
with no DOM or WebGL globals. `tests/headless-smoke.test.ts` imports it in
|
|
753
|
-
plain Node, walks the reachable graph for a renderer leak, and replays a
|
|
754
|
-
seeded scenario through it.
|
|
755
|
-
|
|
756
|
-
- `tools/audit-adoptions` (also `mwg-audit-adoptions`) is the shipped consumer
|
|
757
|
-
adoption auditor: manifest plus reasons file plus config (type-only
|
|
758
|
-
directories, subpath deny-lists, per-pattern import budgets), reporting
|
|
759
|
-
unadopted exports, stale reasons, shadowing collisions and config violations
|
|
760
|
-
with `file:line` and a non-zero exit.
|
|
761
|
-
|
|
762
|
-
- `two-d/pixi-interop` now states the interop-only rationale on each
|
|
763
|
-
re-exported primitive's own declaration: every histogram symbol
|
|
764
|
-
(`Rectangle`, `Texture`, `Container`, `Sprite`, `Graphics`, `FillGradient`,
|
|
765
|
-
`TilingSprite`) already has a facade family, so the note names the
|
|
766
|
-
Pixi-typed seam that keeps the raw export, and `tests/pixi-interop-coverage`
|
|
767
|
-
pins both halves.
|
|
768
|
-
|
|
769
|
-
- `tools/browser-driver` is the dependency-free browser harness: a self-served
|
|
770
|
-
static directory on an OS-chosen free port, Chrome over CDP and Firefox over
|
|
771
|
-
WebDriver BiDi behind one surface (`goto`/`waitReady`/`tap` at canvas
|
|
772
|
-
fractions/`evaluate`/`script`/`screenshot`/`consoleErrors`/`close`), reusing
|
|
773
|
-
the `browser-smoke` readiness contract. Verified live on both engines.
|
|
774
|
-
|
|
775
|
-
### Changed
|
|
776
|
-
|
|
777
|
-
- The coverage gate now enforces `two-d/ui` instead of excluding the whole tree:
|
|
778
|
-
the widget tests the suite already ran carry it (97.3/92.6/94.3 against the
|
|
779
|
-
88/89/82 floors), so the exclusion was stale, and a wildcard also left every
|
|
780
|
-
new UI file silently ungated. `EventDialogue` stays excluded as intended, under
|
|
781
|
-
its real path (`two-d/ui`, where the old flag pointed at a nonexistent
|
|
782
|
-
`two-d/stage` copy), and `SelectionModel` gained a direct contract test that
|
|
783
|
-
covers it fully, where before only its embedding widgets exercised it.
|
|
784
|
-
|
|
785
|
-
## [0.25.0] - 2026-10-05
|
|
786
|
-
|
|
787
|
-
Framework support for the Pixel Dungeon port's simulation and content proposals: numeric
|
|
788
|
-
handle leases for clone-safe commands, journal-free dispatch, one shared random stream for
|
|
789
|
-
scene and simulation draws, MWL node-namespace references, and type-safe table rows with a
|
|
790
|
-
type-emission helper for game build scripts.
|
|
791
|
-
|
|
792
|
-
### Added
|
|
793
|
-
|
|
794
|
-
- `core.Random.active()` returns the ambient generator the free functions draw from, so a
|
|
795
|
-
`SimulationRuntime` constructed with it shares one stream with scene code; `snapshot`/
|
|
796
|
-
`restore` of that generator replay identical continuations.
|
|
797
|
-
- `SimulationRuntime.restore()` accepts `random` to adopt an externally-owned generator
|
|
798
|
-
(such as the global one), keeping scene and command draws in lockstep across restore.
|
|
799
|
-
- `core.createHandles()`/`Handles` - numeric leases for values a plain-data command cannot
|
|
800
|
-
carry, with a scoped `with(value, body)` lease that drops even when the body throws.
|
|
801
|
-
- `SimulationRuntime` accepts `journal: null` for a journal-free dispatch facade: no append
|
|
802
|
-
cost, an empty journal in `snapshot()`, and plainly documented replay/undo semantics.
|
|
803
|
-
- `mwl.MwlTableReference` accepts a node-id namespace target (`references: { node: 'monster' }`),
|
|
804
|
-
checking table cells against authored node ids with the same table/row/value report.
|
|
805
|
-
- `mwl.typedRows()`/`MwlTypedRow`/`MwlColumnValueType` read table rows through their declared
|
|
806
|
-
columns (every field optional, an absent cell omits the key), and `mwl.emitTableTypes()`
|
|
807
|
-
emits one named row interface plus one typed accessor per table for a game's build script,
|
|
808
|
-
so a changed column type or a removed column fails type-checking at every use.
|
|
809
|
-
|
|
810
|
-
## [0.24.1] - 2026-10-02
|
|
811
|
-
|
|
812
|
-
Dependency refresh: Babylon.js 9.29, `@capacitor/cli` held at 8.5.2 so it matches the other Capacitor
|
|
813
|
-
packages, and the SBOM and bundle-size baseline regenerated. The global bundle grew 2.5% gzipped
|
|
814
|
-
(356504 to 365318 B) from the newer Pixi and Babylon releases, which is accepted.
|
|
815
|
-
|
|
816
|
-
### Changed
|
|
817
|
-
|
|
818
|
-
- Updated npm dependencies; `cap:sync` verified against Capacitor 8.5.2 on Android.
|
|
819
|
-
- Refreshed `sbom.cdx.json` and `tools/bundle-size.json`.
|
|
820
|
-
|
|
821
|
-
## [0.24.0] - 2026-10-02
|
|
822
|
-
|
|
823
|
-
Small neural policies and renderer-free training now share game simulation rules,
|
|
824
|
-
with worker batches for larger workloads. A playable maze chase AI lab demonstrates
|
|
825
|
-
live controller switching, and chess search keeps the interface responsive.
|
|
826
|
-
|
|
827
|
-
### Added
|
|
828
|
-
|
|
829
|
-
- A playable maze chase example with independent player and ghost AI selectors,
|
|
830
|
-
random turns, chase rules, path heuristics and a small neural policy trained
|
|
831
|
-
without a UI on the same original simulation rules. Includes keyboard and touch
|
|
832
|
-
steering, live mode switching, power dots and local-file browser checks.
|
|
833
|
-
|
|
834
|
-
- `ai.NeuralPolicy`: validated, dependency-free dense-model inference with shared
|
|
835
|
-
weights, legal-action masks, seeded softmax sampling, existing `JavaScriptAI`
|
|
836
|
-
behaviour integration and cancellable worker inference batches.
|
|
837
|
-
- `simulation.TrainingEnvironment`, `runRollouts` and `runRolloutsAsync`: seeded,
|
|
838
|
-
UI-free episodes over game-owned simulation rules, distinct termination and
|
|
839
|
-
truncation, bounded trajectories, resumable environment snapshots and worker
|
|
840
|
-
batches that reuse a model throughout each episode shard.
|
|
841
|
-
- A generated courier example with headless evolution training, resumable trainer
|
|
842
|
-
checkpoints, exported browser weights, serial/parallel benchmarks and a `file://`
|
|
843
|
-
regression check for frame time, input latency and cancellation of stale results.
|
|
844
|
-
- `searchTourneyAsync` returns `rootScores` for choosing among near-best moves using
|
|
845
|
-
the same worker search.
|
|
846
|
-
|
|
847
|
-
### Fixed
|
|
848
|
-
|
|
849
|
-
- Chess example fuzzy moves now search on workers, with cancellation on reset and
|
|
850
|
-
timeout. Clock and memory updates refresh text without rebuilding the board;
|
|
851
|
-
worker lanes are capped at four and timeout fallback selects a legal move without
|
|
852
|
-
blocking on another search.
|
|
853
|
-
|
|
854
|
-
## [0.23.0] - 2026-09-30
|
|
855
|
-
|
|
856
|
-
MIDI humanization and groove tooling (`audio`), plus RPG Maker map details from the MWGP
|
|
857
|
-
player: shadow layers, A2 table-edge strips and richer move routes.
|
|
858
|
-
|
|
859
|
-
### Added
|
|
860
|
-
|
|
861
|
-
- `TileMap.addShadowLayer`: RPG Maker's per-cell shadow bits (map layer 4) as translucent
|
|
862
|
-
quarter-tile quads, editable with `setTile` and left alone by `setCellColor`.
|
|
863
|
-
- `AutotileSet.tableEdge` (MV slot 1) and `rpgmTableEdgeCells`: the front-edge strip the engine
|
|
864
|
-
draws under an A2 table (`Tilemap._drawTableEdge`), with the engine's rule for which cells
|
|
865
|
-
get one (a table tile above, none here, no A3/A4 wall on the ground layer).
|
|
866
|
-
|
|
867
|
-
- `MoveRouteStep` covers what RPG Maker routes use beyond the four directions: `{ step: { dx, dy } }`
|
|
868
|
-
(diagonals), `{ dir: 'forward' | 'backward' }` (from the mover's facing), `{ turn: 'around' | 'left90' | 'right90' }`,
|
|
869
|
-
`{ turn: 'toward' | 'away' }`, and a `target: () => { x, y }` on `toward`/`away` steps for a target
|
|
870
|
-
that keeps moving (`RouteTarget`).
|
|
871
|
-
- MIDI humanization: `humanizeMidi` and `HumanizerFactory` run one shared pass that moves note
|
|
872
|
-
events and nothing else (tempo, program, controller and meta events pass through untouched,
|
|
873
|
-
note durations survive, `intensity: 0` reproduces the input exactly, a `seed` reproduces a
|
|
874
|
-
run, and nothing lands before tick 0) under either shipped engine. `LiteHumanizer` shakes
|
|
875
|
-
timing and velocity with gaussian noise over a seeded gradient drift, scaled by `style`, and
|
|
876
|
-
holds the kick and the lowest notes near their slots; `GrooveHumanizer` applies a
|
|
877
|
-
`GrooveTemplate`'s per-slot offsets and velocities instead, converted through the file's own
|
|
878
|
-
tempo map (a mismatch reports itself through `onWarn`) and accenting local melody peaks. The
|
|
879
|
-
`'magenta'` tier stays in the API and throws naming what it needs, since neither
|
|
880
|
-
`@magenta/music` nor a PerformanceRNN checkpoint can be fetched from a `file://` build, and
|
|
881
|
-
`MidiPlayer.create(file, { humanize })` humanizes before it schedules.
|
|
882
|
-
- `GrooveExtractor` builds a `GrooveTemplate` three ways, each reduced to the median of each
|
|
883
|
-
slot's deviations: a played pass against a straight one (matching within half a slot), a
|
|
884
|
-
single file projected onto its own implied grid, or an `AudioBuffer` (hand-rolled spectral
|
|
885
|
-
flux onset detection, no analysis dependency, tempo as an argument because a recording
|
|
886
|
-
carries none). `GrooveConverter` round-trips a template through JSON exactly and through a
|
|
887
|
-
Standard MIDI File within a tick and a hundredth, with the MIDI path enforcing its anchor
|
|
888
|
-
and velocity bounds rather than rounding past them and reading back with a dedicated parser
|
|
889
|
-
for the metas `parseMidi` drops; `ableton-agr` and `reaper-groove` are named in the format
|
|
890
|
-
union and throw as not shipped. `subdivisionCount`/`assertGrooveTemplate` are the invariants
|
|
891
|
-
both the extractor and the converter run on.
|
|
892
|
-
|
|
893
|
-
### Fixed
|
|
894
|
-
|
|
895
|
-
- `RPGM_FLOOR_AUTOTILE_TABLE[46]` had the wrong bottom-left quadrant (`[0, 3]`, the engine has
|
|
896
|
-
`[0, 5]`), so shape 46 of every floor-table kind, A4 `mixed` wall tops included, drew a stray
|
|
897
|
-
corner.
|
|
898
|
-
|
|
899
|
-
## [0.22.0] - 2026-09-29
|
|
900
|
-
|
|
901
|
-
Audio and event-runner asks from the MWGP player, plus the small widgets the Pixel
|
|
902
|
-
Dungeon port was carrying (roadmap item 392): a message log, liquid and fog layers, a
|
|
903
|
-
window zoom fit, a Java-compatible random generator, and native A4 autotiles.
|
|
904
|
-
|
|
905
|
-
### Added
|
|
906
|
-
|
|
907
|
-
- Item 392, the small widgets the Pixel Dungeon port and the MWGP player were carrying:
|
|
908
|
-
`two-d/ui.MessageLog` (coloured, line-capped message pane, with `linesToDrop`),
|
|
909
|
-
`fitWindowZoom`/`sharpenText` (window zoom fit and crisp text under a zoomed container),
|
|
910
|
-
`two-d/render.LiquidLayer` (scrolling liquid cells with ripples), `FogLayer`/`paintFogPixels`
|
|
911
|
-
(smooth sub-tile fog), `TileMap.stampRect`, `AutotileSet.mode: 'mixed'` (the MV A4 sheet's
|
|
912
|
-
floor and wall rows on one native autotile layer; the default for A4 stays the wall table),
|
|
913
|
-
and `core.JavaRandom` (`java.util.Random` bit for bit, with a draw trace).
|
|
914
|
-
- `rpg.EventRunnerOptions.onUnknownCommand`: called for any command the runner has no
|
|
915
|
-
handler for, and for a `goto` in a straight `run()` (which then ends the list rather
|
|
916
|
-
than throwing), so a converter's dropped commands can be made loud instead of silent.
|
|
917
|
-
- `audio.parseVorbisLoopTags`/`loopRegionFromTags`: read the `LOOPSTART`/`LOOPLENGTH`
|
|
918
|
-
comments of an Ogg Vorbis file (a bounded page walk, null on malformed input) and turn
|
|
919
|
-
them into the `LoopRegion` a bus loader returns.
|
|
920
|
-
- `audio.AudioBus.setMixer`/`mixer`: a per-kind (BGM, BGS, ME, SE) volume and mute on top
|
|
921
|
-
of each track's own volume; snapshots keep reporting the level the game asked for.
|
|
922
|
-
|
|
923
|
-
### Changed
|
|
924
|
-
|
|
925
|
-
- MIDI rendering voices pitch bend: each note is bent by the amount in effect when it
|
|
926
|
-
starts (two semitones either way). `ScheduledNote.bend` carries it and is absent when the
|
|
927
|
-
channel is centered, so files without bends render bit-identically.
|
|
928
|
-
|
|
929
|
-
### Fixed
|
|
930
|
-
|
|
931
|
-
- `Label` ignores `setText`, `setColor` and the reveal calls after `destroy()`, which
|
|
932
|
-
used to throw from Pixi's text update on the released texture (the confirm-spam
|
|
933
|
-
`_getFinalPadding` error seen on a choice loop).
|
|
934
|
-
|
|
935
|
-
## [0.21.0] - 2026-09-27
|
|
936
|
-
|
|
937
|
-
A tournament chess engine beside the small deterministic one, a playable options
|
|
938
|
-
panel around it, and the missing standard form controls: radio groups, multiline
|
|
939
|
-
text, and multi-select lists.
|
|
940
|
-
|
|
941
|
-
### Added
|
|
942
|
-
|
|
943
|
-
- `board` bitboards: the chess rules on twelve 64-bit boards (`startingBitboard`,
|
|
944
|
-
`bitboardFromChess`, `bitboardMoves`, `makeMove`/`unmakeMove`, `perft`), the mutable
|
|
945
|
-
board the tournament engine will search. Differential tests keep it in agreement
|
|
946
|
-
with `chess.ts`, and perft matches the published node counts.
|
|
947
|
-
- `board.probeBook`/`parseUciMove` look a position up in a compiled opening book (ECO,
|
|
948
|
-
name and UCI continuations) and read UCI moves back; `tools/compile-openings`
|
|
949
|
-
(`mwg-openings`) builds the book from vendored CC0 tables, so the framework ships
|
|
950
|
-
the probe and no table.
|
|
951
|
-
- `board` tournament search: `searchTourney`/`searchTourneyAsync` over one
|
|
952
|
-
self-contained `tourneyThink` task (negamax alpha-beta with PVS, null-move pruning,
|
|
953
|
-
late-move reductions, iterative deepening with aspiration windows, a bounded Zobrist
|
|
954
|
-
table, quiescence, hash/MVV-LVA/killer/history ordering, in-house piece-square
|
|
955
|
-
evaluation), beside the small deterministic `board/Engine`, which the minigame path
|
|
956
|
-
keeps.
|
|
957
|
-
- `board` tablebases: `probeTablebase`/`loadTablebaseEnding`/`tablebaseId` plus the
|
|
958
|
-
`huffEncode`/`huffDecode` codec, with WDL-plus-distance 3-piece endings compiled
|
|
959
|
-
under `data/tablebases`; `tools/build-tablebases` (`mwg-tablebases`) generates and
|
|
960
|
-
verifies 3-to-4-piece endings in parallel over `threads.spawn`.
|
|
961
|
-
- `tools/play-uci` (`mwg-uci`): a UCI adapter over book, tablebase and tournament
|
|
962
|
-
search for GUIs and rating runs, a Node tool never in the browser bundle.
|
|
963
|
-
- `two-d/ui` form controls: `RadioGroup` (exactly one choice among several, arrows
|
|
964
|
-
select at once), multiline `TextModel` (real newlines with row navigation and a
|
|
965
|
-
sticky goal column; single-line fields strip them), and multi-select `ListView`
|
|
966
|
-
(`multiple` checks rows instead of picking one).
|
|
967
|
-
|
|
968
|
-
### Changed
|
|
969
|
-
|
|
970
|
-
- The chess example plays through the tournament engine (`board.searchTourneyAsync`,
|
|
971
|
-
worker-parallel with a bounded synchronous fallback), with a thinking indicator,
|
|
972
|
-
play-as-black, engine depth choice, a promotion picker, an in-check highlight, and
|
|
973
|
-
arrow keys that move the cursor the way the board points.
|
|
974
|
-
- The chess example gains an options panel: checkboxes for play-black, fuzzy moves,
|
|
975
|
-
pondering, blitz clock, opening book and WDL tables, a FIDE time-control slider, a
|
|
976
|
-
live search readout (depth reached, score, nodes, best line, opening name, clocks,
|
|
977
|
-
workers and memory), a concede button, and a new-game offer at game over. The
|
|
978
|
-
webpage Examples page shows the stronger game with its keys documented.
|
|
979
|
-
|
|
980
|
-
## [0.20.0] - 2026-09-27
|
|
981
|
-
|
|
982
|
-
Long synchronous work leaves the main thread: a new worker runtime runs self-contained
|
|
983
|
-
functions on a blob worker in the browser and on worker threads in Node, the offline
|
|
984
|
-
MIDI render and the chess search each gain an async twin on top of it, and the
|
|
985
|
-
build-time compressor works files in parallel.
|
|
986
|
-
|
|
987
|
-
### Added
|
|
988
|
-
|
|
989
|
-
- `threads.spawn` runs a self-contained function on a worker thread: a blob worker under
|
|
990
|
-
the shipped `file://` CSP in the browser, `node:worker_threads` in Node, one worker per
|
|
991
|
-
task with transferable results, a failure that rejects instead of hanging, and `timeout`
|
|
992
|
-
/ `AbortSignal` cancellation. Off the root barrel: `@datamoc/mw_games/threads`.
|
|
993
|
-
- `audio.renderMidiToBufferAsync` renders raw MIDI bytes (and optional raw SoundFont bytes)
|
|
994
|
-
on a worker thread, so the seconds a real track costs no longer freeze the caller's
|
|
995
|
-
thread; the result is bit-identical to `renderMidiToBuffer`, because both paths call the
|
|
996
|
-
same render function.
|
|
997
|
-
- `tools/compress-dist` compresses files in parallel over async `zlib`, with the lane
|
|
998
|
-
count from `MWG_COMPRESS_JOBS` (else the machine's thread count, else 4) or the new
|
|
999
|
-
`jobs` option; rows keep walk order, so the report is identical at any lane count.
|
|
1000
|
-
- `ai.rootSplits`/`ai.firstWins` are the root-split halves of an off-thread search: the
|
|
1001
|
-
split pairs each root move with its child in game order, first-wins reduces scored
|
|
1002
|
-
moves keeping the earlier move on ties.
|
|
1003
|
-
- `board.searchAsync` scores each chess root move on a worker thread and combines the
|
|
1004
|
-
scores first-wins, so the 90 ms a depth-3 search costs no longer drops the caller's
|
|
1005
|
-
frames; inside the node budget it chooses exactly the move `search` returns, past it
|
|
1006
|
-
(or when cancelled) it resolves `{ move: null }` the same way.
|
|
1007
|
-
|
|
1008
|
-
## [0.19.0] - 2026-09-26
|
|
1009
|
-
|
|
1010
|
-
A game that plays five instruments no longer ships all 128: the audio module learns which
|
|
1011
|
-
programs its MIDI files actually use and writes a smaller SoundFont carrying only those.
|
|
1012
|
-
|
|
1013
|
-
### Added
|
|
1014
|
-
|
|
1015
|
-
- `audio.collectSoundFontUsage` lists the (bank, program) pairs scheduled notes request
|
|
1016
|
-
across MIDI files, with drums mapped to bank 128 the way the renderer maps them.
|
|
1017
|
-
- `audio.subsetSoundFont` writes a smaller, valid SoundFont 2 file carrying only the used
|
|
1018
|
-
programs, with zones, ranges, tuning, envelopes and sample loops copied verbatim and
|
|
1019
|
-
every index remapped, so a compiled game ships just the samples it plays.
|
|
1020
|
-
|
|
1021
|
-
## [0.18.0] - 2026-09-25
|
|
1022
|
-
|
|
1023
|
-
### Added
|
|
1024
|
-
|
|
1025
|
-
- `audio.parseMidi` keeps program-change, control-change and pitch-bend events and reports
|
|
1026
|
-
the controller-111 loop marker as `loopStartTick`; `scheduleMidi` notes carry their channel
|
|
1027
|
-
voice (`MidiVoice`: program, bank, gain, pan) and `midiLoopStart` resolves the marker to seconds.
|
|
1028
|
-
- `audio.renderMidiToBuffer` renders a parsed MIDI file to stereo PCM frames, offline and
|
|
1029
|
-
deterministic, voiced by an optional game-supplied `SoundFont` or the built-in waveform
|
|
1030
|
-
synth, with the loop region attached.
|
|
1031
|
-
- `audio.parseSoundFont` reads SoundFont 2 bytes into layered preset voices.
|
|
1032
|
-
- `audio.Channel` (a seekable buffered WebAudio voice with volume, pitch, pan and a loop
|
|
1033
|
-
region) and `audio.AudioBus` (independent BGM/BGS loops, ME jingles that suspend and resume
|
|
1034
|
-
the BGM, overlapping SE one-shots, save and replay with playheads, plain-data snapshots).
|
|
1035
|
-
## [0.17.1] - 2026-09-25
|
|
1036
|
-
|
|
1037
|
-
### Fixed
|
|
1038
|
-
|
|
1039
|
-
- A page built on a Windows checkout refused its own inline script. The HTML parser turns
|
|
1040
|
-
newlines into LF before it hashes an inline script, while `contentSecurityPolicy` hashed the
|
|
1041
|
-
CRLF bytes a `core.autocrlf=true` checkout hands over, so Chrome computed a different hash
|
|
1042
|
-
from the one the policy allowed. The page logged a Content-Security-Policy violation that
|
|
1043
|
-
`mwg-smoke`, the visual smoke and `mwg-bench` read as a page error, the source-page fallback
|
|
1044
|
-
script never ran, and the same build on Linux stayed quiet - which is why no browser job had
|
|
1045
|
-
caught it. Inline scripts are now hashed after CRLF and lone CR become LF; the standalone
|
|
1046
|
-
page's unpacker scripts stay hashed as written, since no parser touches those. A CRLF
|
|
1047
|
-
checkout and an LF checkout now produce the same policy, pinned by a test.
|
|
1048
|
-
- The committed-artifact checks no longer read the checkout's line endings. `api:check`,
|
|
1049
|
-
`stats:check`, `sbom:check` and the committed-SBOM test compared generated text against the
|
|
1050
|
-
committed file byte for byte, so a Windows clone failed them on a tree `git diff` called
|
|
1051
|
-
clean; `bundle.distRaw` summed the bytes `tsc` copies out of a source file's comments, which
|
|
1052
|
-
recorded who generated the file rather than what ships.
|
|
1053
|
-
|
|
1054
|
-
### Changed
|
|
1055
|
-
|
|
1056
|
-
- The `check` job runs on `windows-latest` alongside `ubuntu-latest`, so the two failures above
|
|
1057
|
-
fail the push instead of reaching a Windows contributor. The gates themselves are unchanged,
|
|
1058
|
-
and `fail-fast` is off so one OS failing still shows the other.
|
|
1059
|
-
|
|
1060
|
-
## [0.17.0] - 2026-09-25
|
|
1061
|
-
|
|
1062
|
-
### Security
|
|
1063
|
-
|
|
1064
|
-
- One inbound pipeline, on by default (item 372). `core.parseInbound` runs the size cap,
|
|
1065
|
-
the control-character check and a `JSON.parse` that refuses `__proto__`/`constructor`/
|
|
1066
|
-
`prototype` at any depth. `SaveSystem.load`/`list`/`importSlot`, `Collection`, the stored
|
|
1067
|
-
values behind `PlayerStats`/`RunHistory`/`NewsSeenTracker`, `Settings`, `NewsClient` and
|
|
1068
|
-
`LockstepClient` all use it, with no call for a game to add. The reason: under `file://`,
|
|
1069
|
-
Chromium shares one `localStorage` between every local page, so any HTML file opened on
|
|
1070
|
-
the same machine can read or rewrite a game's saves. `load` now returns `null`, and `list`
|
|
1071
|
-
skips the slot, for a tampered or malformed slot (a corrupt slot used to make `list`
|
|
1072
|
-
throw). `importSlot` checks the `meta` shape and throws a named error.
|
|
1073
|
-
`LockstepClient` caps server messages at `maxMessageBytes` (1 MB), type-checks `welcome`/
|
|
1074
|
-
`tick`/`rejected`, and reports anything else on the new `onProtocolError` signal instead of
|
|
1075
|
-
throwing out of `onmessage`. An unknown message type, which was silently ignored, is
|
|
1076
|
-
reported there too.
|
|
1077
|
-
- The Lua host bounds memory, not only instructions (item 373): `memoryLimit` (32 MB by
|
|
1078
|
-
default, also accepted by `LuaAI`) charges every string and buffer a call allocates, so
|
|
1079
|
-
`string.rep("x", 2^28)` or a doubling `s = s .. s` loop fails with "Lua memory limit
|
|
1080
|
-
exceeded" in milliseconds instead of allocating hundreds of megabytes and freezing the tab.
|
|
1081
|
-
A script-level `pcall` cannot swallow it. `getmetatable("")` no longer exposes the string
|
|
1082
|
-
library.
|
|
1083
|
-
- Every page `emitPage` finishes carries a Content-Security-Policy (item 374), so every
|
|
1084
|
-
example and every game built through `mwgPage()`/`mwg-emit` gets it with no configuration:
|
|
1085
|
-
`default-src 'none'`, scripts from the page's own folder plus hashes of its inline scripts
|
|
1086
|
-
(including the scripts a compressed standalone page unpacks), images/fonts/media from
|
|
1087
|
-
`data:`/`blob:` only, and `connect-src` limited to `data:`/`blob:` plus the origins a game
|
|
1088
|
-
declares (`csp: { connect: [...] }`). Measured in Chromium from `file://`: a `fetch`, an image
|
|
1089
|
-
beacon, a remote script and an injected inline script are all refused, and all 22 examples
|
|
1090
|
-
and both standalone variants still start. `'unsafe-eval'` stays allowed, because Pixi 8
|
|
1091
|
-
refuses to start without it unless the game imports `pixi.js/unsafe-eval` (`eval: false`
|
|
1092
|
-
then drops it). `csp: false` leaves the policy out.
|
|
1093
|
-
- Transport defaults (item 375): `FeedbackClient`, `NewsClient`, `SaveSyncClient`,
|
|
1094
|
-
`TelemetryClient` and `LockstepClient` throw at construction for an `http:`/`ws:` url to
|
|
1095
|
-
anything but this machine, unless `allowInsecure: true`. Response bodies stream through
|
|
1096
|
-
`maxResponseBytes` (10 MB), checked against `content-length` first and cancelled as soon as
|
|
1097
|
-
they pass it. `SaveSyncClient.download`/`list` parsed their JSON envelope with a bare
|
|
1098
|
-
`response.json()`; they now go through `parseInbound` like every other reader.
|
|
1099
|
-
- The reference lockstep server could be stopped by any one client (item 385): `ws` reports
|
|
1100
|
-
an oversized or malformed frame as an `error` event on the socket, and with no listener that
|
|
1101
|
-
event threw and ended the process, every room with it. It now has a listener, caps messages
|
|
1102
|
-
at `maxMessageBytes` (64 KB, where `ws` accepted 100 MiB), reads them through `parseInbound`
|
|
1103
|
-
(an input carrying `__proto__` counts as missing), closes a connection naming an invalid
|
|
1104
|
-
room (1008) or a full one (`maxClientsPerRoom`, 64; 1013).
|
|
1105
|
-
- `TelemetryClient` bounds what leaves the machine (item 378): strings (event name, property
|
|
1106
|
-
names and values) are cut at `maxStringLength` (256), at most `maxProperties` (32) are sent,
|
|
1107
|
-
and `allowedProperties`, when given, drops every other name. A path or an error message
|
|
1108
|
-
passed by mistake leaves as a bounded fragment.
|
|
1109
|
-
- README and `SaveSystem`'s doc state the rule item 377 settled on: under `file://`, any local
|
|
1110
|
-
page shares a game's `localStorage`, so nothing in a save is private and no secret belongs
|
|
1111
|
-
there.
|
|
1112
|
-
- CI hardening (item 379): every GitHub Action is pinned to a commit SHA (the tag kept as a
|
|
1113
|
-
comment), `ci.yml` and `benchmark-browser.yml` run with a read-only token, and Dependabot
|
|
1114
|
-
keeps both the action pins and the npm dependencies current. `tests/workflows.test.ts`
|
|
1115
|
-
fails on an unpinned action or a workflow without `permissions`.
|
|
1116
|
-
- `extract-rgssad` wrote each entry to `path.join(outDir, name)` with the name taken from the
|
|
1117
|
-
archive, so a crafted entry (`../x`, or `..\x` on Windows) could write outside the output
|
|
1118
|
-
folder. Entry names are now normalised and refused unless they resolve inside it (item 389).
|
|
1119
|
-
- Seeded fuzzing of every decoder that reads outside input (item 376) found four defects, all
|
|
1120
|
-
fixed: `mwl.parseExpression` overflowed the stack on 13 000 nested parentheses (now bounded at
|
|
1121
|
-
256 levels and 4096 operators, which also bounds `evaluateExpression`'s recursion, and it no
|
|
1122
|
-
longer copies the rest of the source for every token); `parseMapFile` trimmed lines with a
|
|
1123
|
-
backtracking `/[,\s]+$/` that took a second on 28 000 spaces; `parseTerrain` spread every row
|
|
1124
|
-
into `Math.max`, which overflows past about 100 000 rows, and had no size bound (now 1024x1024
|
|
1125
|
-
cells); and `rpg.decodeMarshal` overflowed the stack on nested arrays (now 1000 levels).
|
|
1126
|
-
|
|
1127
|
-
### Added
|
|
1128
|
-
|
|
1129
|
-
- The build step a game needs, shipped (item 381): `@datamoc/mw_games/tools/vite`'s
|
|
1130
|
-
`mwgPage(options)` plugin makes `vite build` alone produce a page that opens from
|
|
1131
|
-
`file://` (IIFE `game.js`, `base: './'`, `assets/` served in dev and compiled into the
|
|
1132
|
-
build, raw copies left out, optional `singleFile`/`compress`/`toWebp`).
|
|
1133
|
-
`@datamoc/mw_games/tools/emit-page` exports the underlying `emitPage(options)`, which every
|
|
1134
|
-
example here still uses through its command line. The getting-started page's step 10 is
|
|
1135
|
-
now that one plugin line; it used to tell users to make the edit by hand.
|
|
1136
|
-
- `mwg-size dist` (`@datamoc/mw_games/tools/bundle-size`, item 386): the size budget this
|
|
1137
|
-
repository gates its own build with, for a game's build. Every file a player receives, raw and
|
|
1138
|
-
gzipped, plus the total, against `size-budget.json` (written on first run or with `--update`),
|
|
1139
|
-
failing past `--tolerance` (2 %).
|
|
1140
|
-
- `mwg-bench <page | dist>` (`@datamoc/mw_games/tools/benchmark-browser`'s `measurePage`, item
|
|
1141
|
-
387): a game's own frame-rate gate in headless Chrome, with mean fps, 95th-percentile frame
|
|
1142
|
-
time, an optional history compared against its best run, and the software-WebGL switch for a
|
|
1143
|
-
runner with no GPU.
|
|
1144
|
-
- `@datamoc/mw_games/testing` (item 388): `memoryStorage`, `fakeAudio`/`fakeAudioWithEnded`,
|
|
1145
|
-
`FakeSocket`, `fakeFetch` and `fakeGamepad`, the doubles for the seams mwg takes by injection. Off the root
|
|
1146
|
-
barrel, renderer-free. This repository's own tests now use them, which removed twelve copies
|
|
1147
|
-
of the same in-memory storage, six of the same fake audio element, two fake sockets and two fake gamepads.
|
|
1148
|
-
`core.MemoryStorage`, the fallback `defaultStorage()` already used, is exported.
|
|
1149
|
-
- Two developer tools ship (item 389): `mwg-placeholder-assets <folder>` writes the generated,
|
|
1150
|
-
licence-free placeholder set the examples use (refusing to overwrite without `--force`), and
|
|
1151
|
-
`mwg-extract-rgssad <archive> <outDir>` unpacks an RPG Maker XP/VX archive through the
|
|
1152
|
-
vendored MIT decoder, now in the package with its licence.
|
|
1153
|
-
- The translation editor ships (item 384): `npx mwg-i18n <base> <target> [--check]`
|
|
1154
|
-
(`@datamoc/mw_games/tools/i18n-edit`) runs from an installed package, loading `dist` there
|
|
1155
|
-
and the TypeScript sources inside this repository, so a game's CI can gate its translations
|
|
1156
|
-
with `--check`.
|
|
1157
|
-
- The reference lockstep server ships (item 385): `npx mwg-lockstep-server [port]
|
|
1158
|
-
[--host=]` (`@datamoc/mw_games/tools/multiplayer-server`), with `ws` an optional peer. The
|
|
1159
|
-
command listens on 127.0.0.1 unless `--host` says otherwise.
|
|
1160
|
-
- CycloneDX SBOMs for a game (item 380): `mwgPage()` writes `dist/sbom.cdx.json`, the SBOM
|
|
1161
|
-
of what the build ships (the packages vite's module graph put in the bundle, with versions
|
|
1162
|
-
and licences, and every shipped file with its SHA-256; `sbom: false` skips it). For a small
|
|
1163
|
-
consumer project, 8 packages and 3 files, where its lockfile lists 60 components.
|
|
1164
|
-
`mwg-sbom [folder]` (`@datamoc/mw_games/tools/sbom`) writes the lockfile SBOM of any
|
|
1165
|
-
project, an `application` when the project is `private`. The framework's own
|
|
1166
|
-
`sbom.cdx.json` now ships in the package.
|
|
1167
|
-
- `mwg-smoke <page | dist>` and `@datamoc/mw_games/tools/browser-smoke`'s `smokePage` (item
|
|
1168
|
-
383): a game's CI can prove its build still opens from `file://` (no page error, a ready game
|
|
1169
|
-
on a WebGL/WebGPU canvas, non-blank pixels, a screenshot), exiting non-zero otherwise.
|
|
1170
|
-
`playwright-core` is an optional peer. The Chrome lookup now also finds the newest Chromium
|
|
1171
|
-
Playwright installed, whatever its revision, and knows the macOS install paths, so a
|
|
1172
|
-
container or CI image no longer needs `CHROME_PATH`.
|
|
1173
|
-
- `bin` entries (item 382): `mwg-emit <folder> [--dist=] [--assets=]` and `mwg-mwl`, so `npx`
|
|
1174
|
-
runs them instead of a `node node_modules/...` path.
|
|
1175
|
-
- `core.cloneData`/`core.uncloneablePath` - `structuredClone` whose failure names the first
|
|
1176
|
-
value that cannot be copied and where it sits (`action.target.reactions.rules[0].when`),
|
|
1177
|
-
plus that path lookup on its own for a game to assert its commands are plain data.
|
|
1178
|
-
|
|
1179
|
-
### Fixed
|
|
1180
|
-
|
|
1181
|
-
- `SimulationRuntime.dispatch` committed a command's state and scheduler cost before
|
|
1182
|
-
journalling it, so a command that could not be copied (one carrying a live actor that owns
|
|
1183
|
-
a `ReactionTable`, say) threw a bare `DataCloneError` after the turn had already
|
|
1184
|
-
happened. It now copies the event batch, the command and (with `history`) the checkpoint
|
|
1185
|
-
state first, and on failure throws a `TypeError` naming the path and restores the random
|
|
1186
|
-
stream, leaving state, scheduler and journal untouched. The plain-data contract for
|
|
1187
|
-
`Command`, `Event` and `State` is now stated on the class.
|
|
1188
|
-
- `ActionJournal.append` stored the caller's action object by reference, so mutating it
|
|
1189
|
-
afterwards rewrote history; the action is now copied like the events, and a refused
|
|
1190
|
-
append no longer consumes a sequence number.
|
|
1191
|
-
- `Campaign.completeCurrent` assigned the carried-over state before copying the level's
|
|
1192
|
-
result, so a result that could not be copied left the new state applied and the result
|
|
1193
|
-
missing. Both are copied first now. `CanonicalState`, `StateRegistry`, `Campaign`,
|
|
1194
|
-
`runHeadlessScenario` and the MWL save reader copy incoming values through
|
|
1195
|
-
`core.cloneData`, so a non-data value names its path there too.
|
|
1196
|
-
|
|
1197
|
-
## [0.16.0] - 2026-09-19
|
|
1198
|
-
|
|
1199
|
-
### Added
|
|
1200
|
-
|
|
1201
|
-
- First-class autotile layers on `TileMap` (item 370): `addAutotileLayer` takes raw
|
|
1202
|
-
MV tile ids or XP tile values plus one `AutotileSet` per family slot (MV) or image
|
|
1203
|
-
index (XP), and the map assembles each cell's quadrant halves straight from the
|
|
1204
|
-
source sheet, no prebuilt atlas canvas in between. `setAutotileFrame`/
|
|
1205
|
-
`getAutotileFrame` advance and read the animation frame (MV kind cycles, XP frame
|
|
1206
|
-
stripes, wrapping); `setTile`/`getTile` keep working with raw ids. The standard MV
|
|
1207
|
-
floor/wall shape tables ship as `RPGM_FLOOR_AUTOTILE_TABLE`/
|
|
1208
|
-
`RPGM_WALL_AUTOTILE_TABLE` with the family address facts
|
|
1209
|
-
(`RPGM_AUTOTILE_SLOT_BASES`/`RPGM_AUTOTILE_SLOT_COUNTS`, `rpgmAutotileSlot`), and
|
|
1210
|
-
the XP side ships `XP_AUTOTILE_PATTERNS`/`XP_NEIGHBORS_TO_PATTERN` with
|
|
1211
|
-
`xpAutotileRef` (baked cells) and `xpAutotilePattern` (procedural neighbourhoods);
|
|
1212
|
-
`autotileCellParts`/`assertAutotileLayout` resolve and validate one cell
|
|
1213
|
-
renderer-free.
|
|
1214
|
-
|
|
1215
|
-
## [0.15.0] - 2026-09-19
|
|
1216
|
-
|
|
1217
|
-
### Added
|
|
1218
|
-
|
|
1219
|
-
- `mwl.MwlTableReference` and `MwlValidationOptions.tableReferences` - declarative
|
|
1220
|
-
cross-table reference checks (item 362, from the Pixel Dungeon study's proposal P21). A
|
|
1221
|
-
table column declares `references: { table, column }` or `oneOf: [...]`, and
|
|
1222
|
-
`validateCatalog` checks every cell once for all tables, reporting `MWL_TABLE_REFERENCE`
|
|
1223
|
-
with the table, the row, and the offending value. The declarations' contents (which column
|
|
1224
|
-
points where, which set is legal) stay game data in the consuming repository; absent or
|
|
1225
|
-
empty cells are skipped and a `list` cell checks each entry under the table's own
|
|
1226
|
-
delimiter.
|
|
1227
|
-
|
|
1228
|
-
- `core.Settings`/`GameSettings`/`SettingsOptions`/`CustomSettingValue` - persisted
|
|
1229
|
-
player settings (item 363): music and sound-effect levels, master mute, zoom
|
|
1230
|
-
preference, key bindings applied to `Input` on load, and a game-defined `custom` bag
|
|
1231
|
-
(`hints`, `violence`, ...). `defaultSettings` names the fresh-game values,
|
|
1232
|
-
`effectiveMusicVolume`/`effectiveSfxVolume` read 0 while muted, and corrupt storage
|
|
1233
|
-
reads as defaults.
|
|
1234
|
-
|
|
1235
|
-
- `two-d/ui.SettingsScreen`/`SettingsCustomRow` - a ready-made settings screen over
|
|
1236
|
-
`core.Settings` (item 364): music/sfx sliders, mute checkbox, zoom slider, one row
|
|
1237
|
-
per `custom` descriptor (boolean/number/choice), an embedded controls page that
|
|
1238
|
-
writes rebinds back into `Settings` on exit, and a reset row.
|
|
1239
|
-
|
|
1240
|
-
- Auto-pause and auto-mute on page hide (item 365): `Game` suspends the loop and
|
|
1241
|
-
silences its `audio` rig while hidden and resumes both on show (`autoPause`, on by
|
|
1242
|
-
default), via `suspend`/`resume` that park the clock at 0 and route through the top
|
|
1243
|
-
scene's `onSuspend`/`onResume`. `Music`/`Sound`/`Orchestrator` gain matching
|
|
1244
|
-
`suspend`/`resume`, and the player's own mute setting is never touched.
|
|
1245
|
-
|
|
1246
|
-
- Frame-time quality scaling over the static device fit (item 366): a `QualityScaler`
|
|
1247
|
-
steps the backing-store ratio down after sustained over-budget frames and back up
|
|
1248
|
-
only after a much longer streak inside budget, wired to `Game` via the
|
|
1249
|
-
`qualityScaling` option (off unless given) with the fitted ratio as its ceiling.
|
|
1250
|
-
|
|
1251
|
-
- Audio ducking for dialogue and menus (item 367): `Music.duck` glides to an
|
|
1252
|
-
attenuated level until `unduck`, through the existing fade path, with tracks started
|
|
1253
|
-
while ducked starting ducked and pending fades retargeted. `Sound` is untouched.
|
|
1254
|
-
|
|
1255
|
-
- A discrete meter widget, `two-d/ui.Meter` (item 368): N icons with a value filled,
|
|
1256
|
-
the heart row or star rating to `Bar`'s continuous fill. Fractions clip mid-icon
|
|
1257
|
-
through a mask, so halves need no extra art; flat theme pips by default, a
|
|
1258
|
-
game-supplied filled/empty texture pair otherwise.
|
|
1259
|
-
|
|
1260
|
-
- Animate only what is on screen, `two-d/render.SpriteGroup`/`isOnScreen` (item 369):
|
|
1261
|
-
`update(camera, dt)` advances the members inside `camera.view` (plus `margin`) and leaves
|
|
1262
|
-
the rest on their current frame. Members are `AnimatedSprite`s, `ParticleEmitter`s, or
|
|
1263
|
-
anything with `x`/`y` in world units plus `update(dt)`; skipped members resume where they
|
|
1264
|
-
left off, and a rotated camera tests the same over-inclusive box `TileMap.cull` uses, so
|
|
1265
|
-
nothing visible ever freezes.
|
|
1266
|
-
|
|
1267
|
-
## [0.14.0] - 2026-09-15
|
|
1268
|
-
|
|
1269
|
-
### Added
|
|
1270
|
-
|
|
1271
|
-
- `core.cellInside`/`cellIndex`/`cellX`/`cellY`/`cellKey`/`cellFromKey` - bounded-grid
|
|
1272
|
-
indexing as one statement of the row-major convention, asked for by the Wesnoth port's own
|
|
1273
|
-
MWG backlog ("primitives `inside`, `cellIndex` and coordinate keys", with the exit criterion
|
|
1274
|
-
"no more duplicated indexing in the game systems; out-of-bounds tested"). The framework had
|
|
1275
|
-
four private copies of exactly these two lines (`roguelike.Level`, `board.Classics`,
|
|
1276
|
-
`board.FogOfWar`, `board/HexSkirmish`); all four now forward to the shared functions and
|
|
1277
|
-
keep their own out-of-bounds policy, which is what differs between them: `Classics` still
|
|
1278
|
-
throws, `FogOfWar` still answers `-1`, and `Level`'s public shape is unchanged. `cellIndex`
|
|
1279
|
-
itself is deliberately unchecked arithmetic so a hot loop pays nothing for a check it has
|
|
1280
|
-
already done, and `cellKey`/`cellFromKey` are the `'x,y'` spelling a `Map`/`Set` wants, which
|
|
1281
|
-
consumers were each inventing for themselves (item 361).
|
|
1282
|
-
|
|
1283
|
-
- `tools.md`'s "Packaging as a native app" section now covers the mobile (Capacitor/Android)
|
|
1284
|
-
target beside the desktop one: the two toolchain prerequisites that stop a clean machine (JDK
|
|
1285
|
-
21 with `JAVA_HOME`, an SDK that Gradle can find), the five commands from a game's own folder
|
|
1286
|
-
to an installed app on a device, and the three things the generated project gets wrong once and
|
|
1287
|
-
never revisits. Each was reproduced rather than restated: the `.gz`/`.br` sidecars break the
|
|
1288
|
-
asset merge (`mergeDebugAssets FAILED ... Duplicate resources`), `ignoreAssetsPattern` gaining
|
|
1289
|
-
`:!*.gz:!*.br` clears it, and an unchanged `versionCode` refuses the second install
|
|
1290
|
-
(`INSTALL_FAILED_VERSION_DOWNGRADE`). Finishes what item 351 left as a scaffold-only
|
|
1291
|
-
verification and P18 asked for (item 357).
|
|
1292
|
-
|
|
1293
|
-
- Package subpaths for the three shipped `tools/*.mjs` helpers a game imports as a library -
|
|
1294
|
-
`./tools/classic-html`, `./tools/extract-html` and `./tools/single-file` - beside the three
|
|
1295
|
-
that already had one. An `exports` map blocks every deep path it does not name, so naming
|
|
1296
|
-
three of the seven shipped helpers left the other four unimportable outright:
|
|
1297
|
-
`import { toClassicScript } from '@datamoc/mw_games/tools/classic-html'` failed with
|
|
1298
|
-
`ERR_PACKAGE_PATH_NOT_EXPORTED` even though the file ships, pushing a consumer to hardcode a
|
|
1299
|
-
`node_modules/@datamoc/mw_games/...` path that stops existing the moment the package is
|
|
1300
|
-
installed under an npm alias. `tools/classic-html.mjs`'s own `@example` showed the
|
|
1301
|
-
`.mjs`-suffixed spelling, which is exactly what the map refuses; it now shows the specifier
|
|
1302
|
-
that resolves. `tools/mwl.mjs` deliberately keeps no subpath: it reads its arguments and
|
|
1303
|
-
dispatches at import time, so one would make importing it run the CLI. Its library half,
|
|
1304
|
-
`@datamoc/mw_games/mwl`, is the typed, already-exported entry point. `tests/package-tools.test.ts`
|
|
1305
|
-
holds all of that (item 358).
|
|
1306
|
-
|
|
1307
|
-
### Changed
|
|
1308
|
-
|
|
1309
|
-
- `desktop/MwgDesktopHost` loads the built game page named as its first argument instead of
|
|
1310
|
-
only this repository's own `tower-defense` example, and a page it cannot find is reported in
|
|
1311
|
-
a dialog naming what it looked for rather than an unhandled `FileNotFoundException`. With no
|
|
1312
|
-
argument it still walks up to the example, so `npm run desktop:run` is unchanged. This is what
|
|
1313
|
-
makes the reference host usable by a game that merely *uses* `mwg`: the published package
|
|
1314
|
-
ships no packaging scaffold at all (`files` excludes `desktop/`, and every `desktop:`/`cap:`
|
|
1315
|
-
script is repo-relative), so such a game copies the host's two files rather than installing
|
|
1316
|
-
them. The consumer recipe is now written up, with the `dotnet publish` line and the
|
|
1317
|
-
`--no-compress` requirement a native build needs, in `tools.md`'s new "Packaging as a native
|
|
1318
|
-
app" section, in `desktop/README.md`, and as an optional step 11 of the getting-started page;
|
|
1319
|
-
README's status note says where the packaging lives, and stops claiming v0.7.7, instead of
|
|
1320
|
-
leaving the distance between its claim and the package for a consumer to discover. The mobile
|
|
1321
|
-
(Capacitor) half of the same recipe followed as item 357, in the same section of `tools.md`.
|
|
1322
|
-
|
|
1323
|
-
- `Game` keeps the renderer's resolution inside what the device reports it can make. The canvas
|
|
1324
|
-
was sized to `window x devicePixelRatio` whatever the viewport, and a backing store past the
|
|
1325
|
-
GPU's `MAX_TEXTURE_SIZE` is refused by WebGL *silently*, by clamping the drawing buffer: the
|
|
1326
|
-
game carries on rendering into a surface that is not the one it asked for, and nothing is
|
|
1327
|
-
reported anywhere. A full-window 816x1812 canvas at `devicePixelRatio` 2.625 asks for
|
|
1328
|
-
2121x4709, which a device reporting a 4096 limit answered with a 2121x4096 buffer (item 360).
|
|
1329
|
-
That process also painted an entirely black screen, and that is *not* attributed here: the
|
|
1330
|
-
failure never reproduced (every later run of the same emulator reported 8192) and a
|
|
1331
|
-
deliberately clamped 1050x10500 request rendered correctly, so the black screen has no cause
|
|
1332
|
-
recorded against it. What stands on its own is the clamped request the game never made. The
|
|
1333
|
-
resolution is now reduced to the largest whole number that fits, with a warning naming the
|
|
1334
|
-
limit, and re-fitted on rotation and on a `devicePixelRatio` change; a device that can afford
|
|
1335
|
-
what it asked for is untouched.
|
|
1336
|
-
|
|
1337
|
-
- `ROADMAP.md`'s one open 1.0 exit-checklist line (both reference ports complete and playable)
|
|
1338
|
-
was corrected and its framework half tested, since the premise it was written on had gone
|
|
1339
|
-
stale. It named a `mwg-wesno` directory that was never used: the Wesnoth port is `mwg-wesnoth`
|
|
1340
|
-
inside a Wesnoth source checkout, and it was pinned at mwg 0.9.0, so it had never been tested
|
|
1341
|
-
against this release. With 0.13.0 placed in its install for both names it imports, that port
|
|
1342
|
-
typechecks, passes all 334 of its tests, builds (124 MB `dist/game.js`) and passes its own
|
|
1343
|
-
headless-browser verification with `"errors": []`; the Pixel Dungeon port, already on
|
|
1344
|
-
`^0.13.0`, builds and plays in a browser. Neither port's README claims completeness, so the
|
|
1345
|
-
line stays unchecked with that evidence recorded beside it.
|
|
1346
|
-
|
|
1347
|
-
### Fixed
|
|
1348
|
-
|
|
1349
|
-
- `tools/single-file.mjs`'s `output` is now documented and enforced as a file *name* written
|
|
1350
|
-
inside `dist`. An absolute path used to be joined onto `dist` and fail later inside
|
|
1351
|
-
`writeFile` with an `ENOENT` naming a doubled-up path; a value containing a separator is now
|
|
1352
|
-
refused up front with an error naming the argument and the value, since the argument is what
|
|
1353
|
-
was wrong. `tools/single-file.d.mts` and `tools/compress-dist.d.mts` gained the prose their
|
|
1354
|
-
`.mjs` counterparts had and their declarations did not: `output` is a name, not a path,
|
|
1355
|
-
`compressDist`'s `dir` is rewritten in place (its `.gz`/`.br`/`.xz` siblings appear inside it,
|
|
1356
|
-
originals untouched), and each result field's meaning is stated, including that an unwritten
|
|
1357
|
-
sibling reports 0 rather than being absent (item 359).
|
|
1358
|
-
|
|
1359
|
-
## [0.13.0] - 2026-09-15
|
|
1360
|
-
|
|
1361
|
-
### Added
|
|
1362
|
-
|
|
1363
|
-
- `core.parseDialogueLines`/`DialogueLine` and `core.parseTwee`/`TweeCommand`/`TweeChoice`/
|
|
1364
|
-
`TweeStory` - the two-speaker `@id`/`-` dialogue-text state machine and the Twee-notation
|
|
1365
|
-
passage/link parser, each shared by a `two-d/stage` and an `rpg` wrapper (`parseDialogueText`,
|
|
1366
|
-
`importTwee`) rather than copied between them, the same precedent `core.parseCSV` already
|
|
1367
|
-
set for a generic text-format parser other modules build a typed result around.
|
|
1368
|
-
`TweeCommand`/`TweeChoice` are structurally compatible with both `StoryScript`/`StageChoice`
|
|
1369
|
-
and `EventStoryScript`/`EventChoice`, so neither wrapper needs a per-field conversion.
|
|
1370
|
-
- `two-d/stage.parseDialogueText`/`extractDialogueCatalog` and `rpg.parseDialogueText`/
|
|
1371
|
-
`extractDialogueCatalog` - a terse line-based dialogue format, alongside `importTwee`, for
|
|
1372
|
-
straight (non-branching) scenes: `@id text` names the speaker, an unprefixed line
|
|
1373
|
-
narrates, and `- text` alternates between the first two speakers a scene establishes
|
|
1374
|
-
(capped at two; a third distinct speaker is refused rather than guessed at). Each is a
|
|
1375
|
-
thin wrapper around `core.parseDialogueLines` naming its own command shape (`StageCommand`'s
|
|
1376
|
-
`as` versus `EventCommand`'s `speaker`), so a text-only RPG needs no Pixi dependency to use
|
|
1377
|
-
it and a Pixi-based visual novel needs no `rpg` dependency either. Each module's
|
|
1378
|
-
`extractDialogueCatalog` builds an identity `i18n` catalog from the result (`two-d/stage`'s
|
|
1379
|
-
also reads a `StoryScript`), the same shape MWL's `extractCatalog` builds from
|
|
1380
|
-
`_("...")`-marked strings, so a translator has real entries to start from (item 355).
|
|
1381
|
-
- `rpg.EventRunner.runStory`/`EventStoryScript`/`EventCommand`'s new `goto` variant/
|
|
1382
|
-
`EventChoice.goto` - a named-passage graph for map-event scripts, the `EventCommand`
|
|
1383
|
-
counterpart to `StageScript.runStory`/`StoryScript`: a `goto` command or a choice's own
|
|
1384
|
-
`goto` jumps to a different passage, and a plain `run()` refuses a stray `goto` instead of
|
|
1385
|
-
silently ignoring it.
|
|
1386
|
-
- `rpg.importTwee`/`EventTwineStory` - imports Twee-notation Twine stories into
|
|
1387
|
-
`EventStoryScript`, a thin wrapper around `core.parseTwee` (the same engine
|
|
1388
|
-
`two-d/stage.importTwee` wraps for `StageCommand`/`StoryScript` instead), so a text-only
|
|
1389
|
-
RPG can import a branching Twee story with no `two-d`/Pixi dependency (item 356).
|
|
1390
|
-
|
|
1391
|
-
## [0.12.0] - 2026-09-14
|
|
1392
|
-
|
|
1393
|
-
### Added
|
|
1394
|
-
|
|
1395
|
-
- `rpg.EventRunner`'s `DialogueRequest` (and `EventCommand`'s `say`/`ask`) gained an optional
|
|
1396
|
-
`portrait` field, threaded through to `two-d/ui.messageBoxPresenter` and `MessageBox`'s own
|
|
1397
|
-
pre-existing `portrait` support - a portrait-bearing line no longer has to bypass `present`
|
|
1398
|
-
and build its own `MessageBox` directly (item 352).
|
|
1399
|
-
- `rpg.GridMover.jumpBy` - an instant reposition with no tween and no walk animation, for a
|
|
1400
|
-
"jump" move-route step over terrain `moveBy`'s glide has no way to skip.
|
|
1401
|
-
- `rpg.MoveRouteRunner`/`MoveRoute`/`MoveRouteStep`/`MoveRouteOptions` - drives any `GridMover`
|
|
1402
|
-
through a scripted route (fixed/random/toward/away steps, turn, jump, wait) with `repeat` and
|
|
1403
|
-
`skippable` policies, built entirely on `GridMover`'s existing primitives (item 353).
|
|
1404
|
-
- `audio.Sound.play(gain, pitch)` - an optional pitch parameter as `HTMLAudioElement.
|
|
1405
|
-
playbackRate`. No matching `pan`: a plain `<audio>` element has none to set, the same reason
|
|
1406
|
-
`Positional.audioPan` only ever reported a number rather than owning a panner node (item 354).
|
|
1407
|
-
|
|
1408
|
-
### Fixed
|
|
1409
|
-
|
|
1410
|
-
- `mobile:build` (and everything built on it: `cap:sync`, `cap:add:android`, `desktop:build`,
|
|
1411
|
-
`desktop:run`) now passes `--no-compress` to `emit-page.mjs`. Item 349/350's `.gz`/`.br`
|
|
1412
|
-
sidecar files, written by default into every build since those items shipped, broke the
|
|
1413
|
-
Android/Capacitor asset merge (`Duplicate resources` from AAPT, which treats `game.js` and
|
|
1414
|
-
`game.js.gz` as colliding) the first time the full pipeline was actually built and run
|
|
1415
|
-
end to end (item 351) - those sidecars were always dead weight for a packaged native app
|
|
1416
|
-
with no server to negotiate `Content-Encoding` for, so this drops them at the source rather
|
|
1417
|
-
than special-casing the generated `android/` project.
|
|
1418
|
-
|
|
1419
|
-
### Changed
|
|
1420
|
-
|
|
1421
|
-
- `android/` is no longer `.gitignore`d (item 110's original choice, kept since). The
|
|
1422
|
-
Capacitor-scaffolded project's own generated `.gitignore` already excludes build output,
|
|
1423
|
-
`local.properties`, and the copied web assets/config that `cap sync` regenerates every
|
|
1424
|
-
build - the 53 files it leaves are ordinary scaffold source (manifest, Java, gradle files,
|
|
1425
|
-
launcher/splash resources), the same kind of thing worth tracking as any other native
|
|
1426
|
-
wrapper customization: this session's own `ignoreAssetsPattern` fix (above) would otherwise
|
|
1427
|
-
have been silently lost the next time someone ran `cap add android` fresh.
|
|
1428
|
-
- `webpage/assets/0c_framework_architecture.svg` regenerated - it had gone stale since the
|
|
1429
|
-
`ai` and `mwl` modules were added to `src/`, so the "generated, never hand-drawn" diagram
|
|
1430
|
-
was quietly wrong about the current module list until `npm run webpage:diagrams` was
|
|
1431
|
-
actually re-run (item 351's Android/Windows verification pass turned this up while
|
|
1432
|
-
double-checking related documentation).
|
|
1433
|
-
- `webpage/design/architecture-explorer.html`, the interactive module-graph explorer, was
|
|
1434
|
-
regenerated via the archify skill for the same reason: authored once at release 0.4.3, it
|
|
1435
|
-
had never been updated and was missing `ai`/`mwl` entirely despite linking to itself as
|
|
1436
|
-
"generated straight from src/'s own import graph". Rebuilt with real, verified import-graph
|
|
1437
|
-
data for all 15 current modules and a fourth guided view ("mwl as data-authoring backbone").
|
|
1438
|
-
- `desktop/README.md` documented only the older, unwired `desktop/webview2` host and never
|
|
1439
|
-
mentioned `desktop/MwgDesktopHost` - the one `desktop:build`/`desktop:run` actually build -
|
|
1440
|
-
or its `SetVirtualHostNameToFolderMapping` capability. Rewritten to cover both hosts and
|
|
1441
|
-
which job each is for.
|
|
1442
|
-
|
|
1443
|
-
## [0.11.0] - 2026-09-14
|
|
1444
|
-
|
|
1445
|
-
### Added
|
|
1446
|
-
|
|
1447
|
-
- `tools/webp-convert.mjs` (`toWebp`) and `compileResources`'s `toWebp`/`webpLossless`/
|
|
1448
|
-
`webpQuality` options - convert `.png`/`.jpg`/`.jpeg` build assets to WebP before embedding,
|
|
1449
|
-
lossless by default (verified pixel-for-pixel identical to the source) and only kept when
|
|
1450
|
-
actually smaller, under the asset's unchanged key so `load('sprite.png')` keeps working the
|
|
1451
|
-
same in dev and built modes. Needs the optional `sharp` devDependency, dynamically imported
|
|
1452
|
-
only when `toWebp` is used, so a build that never asks for it never needs it installed
|
|
1453
|
-
(item 350).
|
|
1454
|
-
- `single-file.mjs`'s `algorithm: 'gzip' | 'brotli'` option (`--brotli[=quality]` on the CLI,
|
|
1455
|
-
`--single-file-brotli[=quality]` on `emit-page`) - brotli compression for the single-file
|
|
1456
|
-
build alongside the existing gzip path. gzip stays the broadly-supported default: a real
|
|
1457
|
-
Chrome (153) tested directly during this feature's own verification throws for
|
|
1458
|
-
`DecompressionStream('br')`, so brotli is documented as an advanced, narrower-reach option
|
|
1459
|
-
rather than an assumed-safe default (item 350).
|
|
1460
|
-
|
|
1461
|
-
### Fixed
|
|
1462
|
-
|
|
1463
|
-
- `single-file.mjs`'s generated bootstrap: `new DecompressionStream(format)` throws
|
|
1464
|
-
synchronously for an unsupported format rather than rejecting a promise, which escaped the
|
|
1465
|
-
bootstrap's own error handling entirely and left the splash screen stuck forever instead of
|
|
1466
|
-
failing visibly - found live in the browser while verifying item 350's brotli option, fixed
|
|
1467
|
-
for both gzip and brotli by converting the throw into a rejection.
|
|
1468
|
-
- `assets.load`'s `data:` URI format hint now comes from the URI's own MIME type first, falling
|
|
1469
|
-
back to the asset path's extension only when that is unavailable. Found while reviewing
|
|
1470
|
-
item 350's WebP conversion: `toWebp` can compile a `sprite.png` path into `image/webp` bytes
|
|
1471
|
-
(keeping the `.png` key so dev and built modes keep agreeing), and the old, path-only hint
|
|
1472
|
-
would have told Pixi's resolver to run the PNG parser over WebP data.
|
|
1473
|
-
|
|
1474
|
-
## [0.10.0] - 2026-09-14
|
|
1475
|
-
|
|
1476
|
-
### Added
|
|
1477
|
-
|
|
1478
|
-
- `tools/single-file.mjs` and `emit-page --single-file [--single-file-compress[=level]]` -
|
|
1479
|
-
a genuinely single-file `file://` build with no sibling `.js` at all: every script an
|
|
1480
|
-
example's build loads is inlined into one additional `standalone.html`, optionally gzipped
|
|
1481
|
-
and unpacked at load through the browser's own `DecompressionStream` behind a splash
|
|
1482
|
-
screen, additive to the existing multi-file output (item 349).
|
|
1483
|
-
|
|
1484
|
-
## [0.9.1] - 2026-09-14
|
|
1485
|
-
|
|
1486
|
-
### Added
|
|
1487
|
-
|
|
1488
|
-
- `rpgmAutotileFrame` and `RpgmAutotileAtlas` - renderer-neutral RPG Maker MV autotile
|
|
1489
|
-
atlas geometry, including four-slot decoding, quadrant selection, validation, and cached
|
|
1490
|
-
frame descriptions (roadmap item 348).
|
|
1491
|
-
|
|
1492
|
-
## [0.9.0] - 2026-09-13
|
|
1493
|
-
|
|
1494
|
-
### Added
|
|
1495
|
-
|
|
1496
|
-
- `core.CanonicalState` - a defensive, JSON-safe root state combined with `StateRegistry`
|
|
1497
|
-
extensions, with snapshots, version migrations, transactions, and atomic restore covering
|
|
1498
|
-
both pieces together (item 341).
|
|
1499
|
-
- `simulation.validateSimulationReplay`, and an optional `history` option on `SimulationRuntime`:
|
|
1500
|
-
replay a recorded journal from a checkpoint and compare deterministic event batches, and
|
|
1501
|
-
restore complete state/scheduler/RNG/journal undo-redo checkpoints (item 341).
|
|
1502
|
-
- `LockstepClient`/`createLockstepServer` carry a session seed and initial state, validate
|
|
1503
|
-
game-supplied commands, and exchange per-tick state checksums, with new `onReject`/`onDesync`
|
|
1504
|
-
signals reporting rejected input and diverging peers (item 341).
|
|
1505
|
-
- MWL JSON5 authoring accepts schema-neutral named-node sugar (`{ unit_type: { id: 'hero' } }`
|
|
1506
|
-
and repeated object children) alongside the generic `tag`/`children` envelope, lowered before
|
|
1507
|
-
validation runs (item 338).
|
|
1508
|
-
- `MwlDomainHook`/`MwlDomainHookRegistry`/`MwlDomainHookDeclaration` - game-declared hook
|
|
1509
|
-
namespaces (`item-effect:potion-strength`) get a typed context/input/output boundary that MWG
|
|
1510
|
-
validates and emits without knowing the domain's own types or rules (item 342).
|
|
1511
|
-
- `HookWorld.random` - every MWL hook, built-in or domain, draws from the runtime's own seeded
|
|
1512
|
-
`core.Generator` instead of `Math.random()`, via the new `MwlRuntimeOptions.random`; the draw
|
|
1513
|
-
position is carried on `MwlWorld.random` and resumes exactly across save/restore (item 342).
|
|
1514
|
-
Any game hand-building its own `HookWorld` (only `MwlRuntime` constructs one today) must now
|
|
1515
|
-
provide this field too, the same rule item 319's `variableAt` addition already established.
|
|
1516
|
-
- `MwlSaveableHookState`/`MwlHookRegistry.saveable` - a game may explicitly expose JSON-safe hook
|
|
1517
|
-
state; `MwlRuntime.save()`/`restore()` round-trip it through the same save envelope (item 341).
|
|
1518
|
-
- `MwlRuntime.journal`/`MwlRuntimeAction` - public runtime operations (running a trigger, firing
|
|
1519
|
-
an event or a moveto watch, answering a dialogue choice) are recorded in order and persisted
|
|
1520
|
-
with the save (item 341).
|
|
1521
|
-
- The MWL parser and compiler retain exact JSON5 attribute and value source locations
|
|
1522
|
-
(`MwlNode.attributeLocations`/`valueLocations`), used by schema, catalog, and macro
|
|
1523
|
-
diagnostics instead of falling back to the owning node's own location (item 342).
|
|
1524
|
-
- Unknown MWL macros and hook references are errors by default, with file/line/column
|
|
1525
|
-
diagnostics; `MwlPreprocessOptions.macroPolicy: 'ignore'` restores the old silent-passthrough
|
|
1526
|
-
behaviour for legacy content (item 342).
|
|
1527
|
-
- `schema10`/`MWL_SCHEMA_10` - the published MWL 1.0 vocabulary: required attributes and child
|
|
1528
|
-
cardinalities on top of the unchanged 0.1 tag/value contract; `mwl migrate --to 1.0` performs
|
|
1529
|
-
a lossless upgrade (item 342).
|
|
1530
|
-
- `validateCatalog` reports `MWL_ALIAS_CYCLE` for cycles in resolved `aliasof` chains, and the new
|
|
1531
|
-
`MwlValidationOptions.mapBounds` rejects authored coordinates outside declared map dimensions
|
|
1532
|
-
(item 342).
|
|
1533
|
-
- `readTableMap`/`readTableIndex`/`tableKey` - typed table-row projections with collision-free
|
|
1534
|
-
native composite keys, and inverse indexes that retain every matching row (items 339, 346).
|
|
1535
|
-
- `mwl diagnostics`/`mwl ci` CLI modes emit stable, machine-readable JSON diagnostics; `mwl
|
|
1536
|
-
format`/`mwl migrate --to 1.0` emit a deterministic canonical document (items 342, 346).
|
|
1537
|
-
- `tests/random.test.ts` gained a hardcoded-output compatibility test for `core.Generator`'s
|
|
1538
|
-
stream, guarding fixed seeds against a future silent algorithm change (item 342).
|
|
1539
|
-
|
|
1540
|
-
### Changed
|
|
1541
|
-
|
|
1542
|
-
- `mwl/grammar.ts`'s macro expansion, gettext rewrite, and tag-site collection now share one
|
|
1543
|
-
`skipStringOrComment` scan instead of three near-identical hand-rolled copies of it.
|
|
1544
|
-
- `LockstepClient.submitInput` accepts an optional per-tick checksum and an optional client-side
|
|
1545
|
-
`validateInput`; rejected input reports through the new `onReject` signal instead of silently
|
|
1546
|
-
going nowhere.
|
|
1547
|
-
|
|
1548
|
-
### Fixed
|
|
1549
|
-
|
|
1550
|
-
- `src/mwl/catalog.ts` carried a literal NUL byte, rather than an escaped `\0`, inside one
|
|
1551
|
-
composite map key, which made the file register as binary to `git diff` and `grep`. Replaced
|
|
1552
|
-
with the same `\0` escape already used for the identical purpose elsewhere in the file; no
|
|
1553
|
-
behaviour change.
|
|
1554
|
-
|
|
1555
|
-
## [0.9.0-alpha] - 2026-09-13
|
|
1556
|
-
|
|
1557
|
-
### Changed
|
|
1558
|
-
|
|
1559
|
-
- MWL authoring syntax is now JSON5 instead of the WML-inspired tag/`key=value`
|
|
1560
|
-
form: every `.mwl` file is a top-level array of `{ tag, ...attributes, children }`
|
|
1561
|
-
nodes, values are real JSON5 numbers, booleans and strings (stringified back to
|
|
1562
|
-
the `Record<string, string>` the schema, compiler and runtime already see), and
|
|
1563
|
-
translatable strings are marked `_("...")` via a preprocessor rewrite. The
|
|
1564
|
-
`#define`/`#include`/`#ifdef` textual pass is unchanged. The `"""..."""` block
|
|
1565
|
-
form (item 317) is superseded by JSON5 `\n` escapes and backslash line
|
|
1566
|
-
continuations. Clean cutover: all fixtures, examples, tests and doc examples
|
|
1567
|
-
are migrated, the old tag parser is deleted, and `json5` (pure JS, no native
|
|
1568
|
-
build) is a runtime dependency.
|
|
1569
|
-
|
|
1570
|
-
## [0.8.2] - 2026-09-13
|
|
1571
|
-
|
|
1572
|
-
### Added
|
|
1573
|
-
|
|
1574
|
-
- `tests/builtin-pipes.test.ts`: regression coverage confirming `TiledSprite`/`NinePatch`
|
|
1575
|
-
resolve to Pixi's own registered `tilingSprite`/`nineSliceSprite` pipes, a guarantee previously
|
|
1576
|
-
verified only by a downstream consumer's own uncommitted script (item 336).
|
|
1577
|
-
|
|
1578
|
-
### Changed
|
|
1579
|
-
|
|
1580
|
-
- `mwl/runtime.ts`'s `executeNode` (a 226-line `switch` over 28 command tags, its own case
|
|
1581
|
-
bodies inline) is now a `commandHandlers` dispatch table plus one small, independently-named
|
|
1582
|
-
private method per command. No public API or behaviour change: `API_REPORT.md`'s diff is
|
|
1583
|
-
purely additive private-method stubs, and all 166 `mwl-*.test.ts` tests pass unmodified
|
|
1584
|
-
(item 337).
|
|
1585
|
-
- `DEVELOPMENT.md` documents why `coverage`/`coverage:check` exclude `Game.ts`,
|
|
1586
|
-
`ColorTransformBatcher.ts`, `Minimap.ts`, `three-d/Vox.ts`, `DialogueStage.ts`,
|
|
1587
|
-
`EventDialogue.ts` and `two-d/ui/**` (Pixi rendering/layout, verified by the visual smokes
|
|
1588
|
-
instead of a coverage percentage), and why `core` holds optional network-facing clients
|
|
1589
|
-
alongside always-needed primitives (item 333, item 334).
|
|
1590
|
-
- `GameOptions.extensions`'s doc comment now names `TiledSprite`/`NinePatch` alongside
|
|
1591
|
-
`TintedSprite` as self-registering their Pixi render pipe automatically, closing a
|
|
1592
|
-
documentation gap that likely explains why a cautious consumer wasn't confident enough to rely
|
|
1593
|
-
on it (item 336).
|
|
1594
|
-
|
|
1595
|
-
### Fixed
|
|
1596
|
-
|
|
1597
|
-
- `mwl`'s `validateWorld` rejects a `__proto__`/`constructor`/`prototype` key anywhere in a
|
|
1598
|
-
decoded save (item 335): `MwlRuntime.restore` merges a decoded save into its own world with
|
|
1599
|
-
`Object.assign`, which honours such a key as a prototype substitution rather than an ordinary
|
|
1600
|
-
value. `core/Sanitize.ts` gains `assertNoForbiddenKeys`, the same rejection `validateSchema`
|
|
1601
|
-
already applied to fixed-shape data, generalised to `mwl`'s dynamic, arbitrarily-nested world
|
|
1602
|
-
shape.
|
|
1603
|
-
- `SaveSystem.load` returns `null` for a corrupted or malformed slot instead of throwing an
|
|
1604
|
-
uncaught `SyntaxError`, the same outcome a missing slot already produced; `importSlot` throws a
|
|
1605
|
-
labelled `SaveSystem.importSlot: payload is not valid save data` error instead of a bare parse
|
|
1606
|
-
error (item 331).
|
|
1607
|
-
- `Container2D`/`Texture2D` in `two-d/render/Types2D.ts` each carried two adjacent JSDoc blocks,
|
|
1608
|
-
so only the generic, less useful one reached generated documentation; merged into one comment
|
|
1609
|
-
each (item 332).
|
|
1610
|
-
|
|
1611
|
-
## [0.8.1] - 2026-09-12
|
|
1612
|
-
|
|
1613
|
-
### Added
|
|
1614
|
-
|
|
1615
|
-
- `MwlValue` is exported from the `mwl` barrel, alongside `MwlWorld`: the recursive
|
|
1616
|
-
`string | number | boolean | MwlValue[] | { [key: string]: MwlValue }` that `MwlWorld.variables`
|
|
1617
|
-
and a hook's own attributes already used, now nameable by a game's own code instead of only
|
|
1618
|
-
inferred.
|
|
1619
|
-
- `MessageParams` takes nested records, and a `{token}` may be a dotted path into them (item 329):
|
|
1620
|
-
`t('hit', { side })` resolves `{side.stored.hitpoints}` by walking the params it was handed, so a
|
|
1621
|
-
game whose scenario state is a tree passes the tree rather than flattening it into names first.
|
|
1622
|
-
A path that names nothing - a step missing, an object where a value belongs, a path past a
|
|
1623
|
-
scalar - leaves the placeholder as written, and an exact entry still wins over the walk, so a
|
|
1624
|
-
literal dotted key resolves as it always did. The placeholder grammar (`tokenizeMessage`, shared
|
|
1625
|
-
with the editor's `diffPlaceholders`) is what widened: a dotted token carries its `:spec` and
|
|
1626
|
-
`!conv` like any other.
|
|
1627
|
-
- `~ROTATE(degrees, linear)` and `rotatePixels`'s `RotateMode` (item 330): a rotation at an angle
|
|
1628
|
-
that is not a quarter turn can now interpolate instead of sampling nearest-neighbour, which is
|
|
1629
|
-
what keeps a tile rotated onto a hex grid from coming out as a staircase. `~ROTATE(45)` and
|
|
1630
|
-
`rotatePixels(..., 'nearest')` are the default and are unchanged, still exact at multiples of 90
|
|
1631
|
-
degrees; `'linear'` blends the four pixels around each sample point, premultiplied by alpha, so a
|
|
1632
|
-
transparent neighbour contributes coverage and never colour - a straight RGBA blend would fringe
|
|
1633
|
-
every cut-out sprite with whatever RGB its transparent pixels happen to hold, which is the one
|
|
1634
|
-
way this can look worse than the fast path rather than better. Both modes are bake-time work, and
|
|
1635
|
-
measured: `linear` costs 2.4 to 4.2 times `nearest` per image (0.45 ms against 0.12 ms for a
|
|
1636
|
-
64x64 tile at 60 degrees, 3.6 ms against 1.5 ms at 256x256), once, while the texture is built.
|
|
1637
|
-
`parseRotateMode` is the argument's parser, exported beside the other path parsers so a game
|
|
1638
|
-
rendering `~ROTATE` through its own canvas pipeline reads the same names.
|
|
1639
|
-
|
|
1640
|
-
### Changed
|
|
1641
|
-
|
|
1642
|
-
- `parsePo` treats a `#, fuzzy` entry as untranslated (the Wesnoth port's non-adoption review),
|
|
1643
|
-
which is what gettext's own tools make of it: the key is left out and the base language wins,
|
|
1644
|
-
rather than shipping a translation a translator has not signed off on. Flags were previously
|
|
1645
|
-
dropped on the floor along with comments; every other flag still changes nothing.
|
|
1646
|
-
- `paletteRangeMapping` shades a reference palette by brightness rather than by position (item 327),
|
|
1647
|
-
which is what a Wesnoth `[color_range]` team colour is defined by: the reference's first colour
|
|
1648
|
-
is its anchor and becomes `mid`, every other entry blends towards `min` or `max` in proportion to
|
|
1649
|
-
how its own channel average compares with the anchor's, and the arithmetic is the engine's own -
|
|
1650
|
-
a floored average, a truncated blend, no rounding - so the shades come out byte for byte as
|
|
1651
|
-
Wesnoth's `recolor_palette` gives them. A list no longer has to be sorted lightest-first for the
|
|
1652
|
-
mapping to make sense, only to keep its anchor first, and the mode it pairs with is `'exact'`:
|
|
1653
|
-
the mapping covers the reference exactly, so the pixels outside it (anti-aliased edges, outlines)
|
|
1654
|
-
stay as the artists painted them, where the previous documentation pointed at `'nearest'` for it
|
|
1655
|
-
and would have repainted the whole image. Verified against the port's own transliteration of the
|
|
1656
|
-
engine over 699,996 sampled colours across five ranges, including the all-black and all-white
|
|
1657
|
-
anchors, with no mismatch.
|
|
1658
|
-
|
|
1659
|
-
## [0.8.0] - 2026-09-12
|
|
1660
|
-
|
|
1661
|
-
### Added
|
|
1662
|
-
|
|
1663
|
-
- `MwlHookDeclaration` and `validateHookAttributes` (item 321), plus `validAttributeValue`/
|
|
1664
|
-
`attributeTypeDescription`: a hook declares the attributes its own `[hook]` calls carry, and
|
|
1665
|
-
`validateCatalog`'s `hooks` option takes that declaration where a bare `type:name` id used to
|
|
1666
|
-
be the only accepted shape. A typo in a hook attribute is now a compile-time `MWL_VALUE` or
|
|
1667
|
-
`MWL_UNKNOWN_ATTRIBUTE` instead of a throw mid-scenario. The tag schema's own value check now
|
|
1668
|
-
calls the same two exported functions, so the two cannot disagree.
|
|
1669
|
-
- `HookWorld.variableAt(path)` (item 319): the read that matches `Emit.setVariable`'s write, both
|
|
1670
|
-
resolving a nested variable through the same walker `[variable] name=` uses, so a hook no
|
|
1671
|
-
longer has to cast away `Readonly` and walk paths itself (which produced flat dotted keys no
|
|
1672
|
-
reader finds). `Emit.setVariable` is documented as the write half. Any game implementing its
|
|
1673
|
-
own `HookWorld` must now provide the method; only the runtime constructs one today.
|
|
1674
|
-
- `[set_variable] path=` (item 318), on both spellings: the computed target a converter needs for
|
|
1675
|
-
a dynamic name, expanded from `$name`/`$(expression)` references before the same path walker a
|
|
1676
|
-
literal `name=` uses resolves it. `name=`/`target=` keep their literal meaning.
|
|
1677
|
-
- `[set_variable] mode=literal|number|expression` (item 316), on both spellings of the effect
|
|
1678
|
-
(`[set_variable]` and `[command] name="set_variable"`): content declares what its own `value=`
|
|
1679
|
-
means instead of `MwlRuntime` inferring it from the text. `literal` keeps the text exactly as
|
|
1680
|
-
written, `number` parses it and throws on anything that is not one, `expression` evaluates it
|
|
1681
|
-
through the same context `[if] test=` uses. A value with no `mode` is inferred as before, so
|
|
1682
|
-
hand-authored content is unaffected.
|
|
1683
|
-
- `mwl.MwlAttributeType` (item 316): a schema attribute's type may be the closed list of values
|
|
1684
|
-
it accepts, not only one of the shared value types. A value outside the list is a compile-time
|
|
1685
|
-
`MWL_VALUE` diagnostic naming the alternatives.
|
|
1686
|
-
- `key="""..."""` attribute values (item 317): the one form that may span lines, taken exactly
|
|
1687
|
-
as written, so wrapped message, objective and option-label text no longer needs a converter to
|
|
1688
|
-
collapse its whitespace. The `_` gettext marker applies to it as to any other value.
|
|
1689
|
-
- `roguelike.coneSector` (item 322): a circular sector aimed at an angle. Rays are cast every 0.5
|
|
1690
|
-
degrees across an arc of `degrees`, each clamped to `range` and stopped by the first wall, so a
|
|
1691
|
-
wall shadows the part of the cone behind it while the rest still reaches. `coneCells` snaps the
|
|
1692
|
-
aim to one of the eight directions and sprays linearly from there; a sector keeps the angle it
|
|
1693
|
-
was aimed at, which is what a breath weapon, a searchlight or a gas cloud wants. It needs the
|
|
1694
|
-
level - that is what stops its rays - so it is a function rather than one of `AreaShape`'s kinds,
|
|
1695
|
-
whose resolver works without one. Ray offsets round away from zero, so a sector aimed along an
|
|
1696
|
-
axis is exactly symmetric rather than a cell wider on one side. Six tests in
|
|
1697
|
-
`tests/targeting-shapes.test.ts`.
|
|
1698
|
-
- `ParticleEmitter` colour ranges, curves and flicker (item 323): `tint` takes a `[from, to]` pair
|
|
1699
|
-
each particle draws its own colour from (mixed channel by channel, where interpolating the packed
|
|
1700
|
-
value would carry from one channel into the next), `scale`/`alpha` take a `ParticleCurve` of the
|
|
1701
|
-
particle's own age instead of only the birth-to-death pair, and `flicker` multiplies the scale by
|
|
1702
|
-
a seeded draw every frame, which is a torch's wobble rather than its fade. Each of those draws
|
|
1703
|
-
happens only when its option is used, so an existing seeded spray is unchanged, and reduced
|
|
1704
|
-
motion drops the flicker along with the travel. Five tests in `tests/particles.test.ts`.
|
|
1705
|
-
- `Window({ blocker: true })` (item 324): a full-viewport child under the window's chrome that
|
|
1706
|
-
swallows clicks, so a window over a map or a toolbar stops passing them to what is underneath,
|
|
1707
|
-
and dismisses the window when the click lands outside it. A window's own widgets are hit first,
|
|
1708
|
-
and a click on the frame or an empty part of the body is swallowed without dismissing, so the
|
|
1709
|
-
body is never a close button by accident. `handleOutsideClick(x, y)` is that decision on its own,
|
|
1710
|
-
headless-testable the way `handleAction` is. Off by default: it changes what the whole screen
|
|
1711
|
-
answers to. Seven tests in `tests/window-blocker.test.ts`.
|
|
1712
|
-
- `WindowStack.handleAction(action)` is public (item 325): a scene with its own keyboard handling
|
|
1713
|
-
can now ask the windows before acting, instead of discovering that registration order decided it.
|
|
1714
|
-
`Input.onAction` offers an action to the most recently registered listener first, and the stack
|
|
1715
|
-
registers in its constructor, so a scene that builds its stack in `create()` and registers a
|
|
1716
|
-
handler after it is offered every key before the open window is, and returning true for one takes
|
|
1717
|
-
it away from the window. The class doc spells the race out and gives the one-line chain
|
|
1718
|
-
(`stack.handleAction(action) || myOwnHandling(action)`), and the same doc now says what a scene
|
|
1719
|
-
that does not chain has to do instead. `Window`'s own doc gains the other half: its frame and
|
|
1720
|
-
empty body are not clickable, which `blocker` is the option that changes. Three tests in
|
|
1721
|
-
`tests/window-stack-routing.test.ts`.
|
|
1722
|
-
- `SpriteSheet.rect(index, x, y, width, height)` (item 326): arbitrary rectangles for the sheets
|
|
1723
|
-
that are not grids - a hand-packed icon atlas, a strip of bar segments, a nine-patch's corners,
|
|
1724
|
-
an item whose art is smaller than its cell. A rect is cached under its index exactly like a grid
|
|
1725
|
-
frame, so `get`/`region`/`name`/`pick` treat it as one and asking twice returns the same
|
|
1726
|
-
`Texture`, where the hand-written path built a fresh one per site (about twenty of them in the
|
|
1727
|
-
port, plus its own helper). Declaring a rect over a grid index replaces that frame, which is what
|
|
1728
|
-
a tightened sub-rect is. `grid`/`fromTexture` now take no frame size at all, leaving a sheet with
|
|
1729
|
-
no grid and only the rects declared on it. Five tests in `tests/sprite-sheet-rects.test.ts`.
|
|
1730
|
-
|
|
1731
|
-
### Changed
|
|
1732
|
-
|
|
1733
|
-
- `MessageBox` swallows clicks by default (item 324), through the same `blocker` layer: a box with
|
|
1734
|
-
a page still to read, or a choice to answer, is not something a click on the world should be able
|
|
1735
|
-
to act past. It is not closable, so this can only ever swallow a click, never dismiss the box,
|
|
1736
|
-
and `blocker: false` is the opt-out for a box the player is meant to click past (the same case
|
|
1737
|
-
`dims: false` is for). `examples/interface` uses both new halves: its bag window takes
|
|
1738
|
-
`blocker: true`, and its map handler now asks `windows.handleAction` rather than relying on
|
|
1739
|
-
having registered before the stack did.
|
|
1740
|
-
- `sbom.cdx.json` carries a `serialNumber` (item 315): a version-5 UUID over the document's own
|
|
1741
|
-
content, so it stays stable for a given lockfile and changes when the dependency set does, which
|
|
1742
|
-
keeps the drift check and gives the serial the meaning CycloneDX asks of it. `metadata.timestamp`
|
|
1743
|
-
stays absent on purpose: a generation time stamped into a committed file is one stale moment
|
|
1744
|
-
every later read is dated to, and `CHANGELOG.md` already dates each version.
|
|
1745
|
-
|
|
1746
|
-
## [0.7.9] - 2026-09-12
|
|
1747
|
-
|
|
1748
|
-
### Added
|
|
1749
|
-
|
|
1750
|
-
- `tools/sbom.mjs` with `npm run sbom`/`npm run sbom:check` (item 315): a CycloneDX 1.6 SBOM
|
|
1751
|
-
(`sbom.cdx.json`) for the framework, built from `package.json` and `package-lock.json` alone
|
|
1752
|
-
with no network access or added dependency, and checked in CI so a dependency change moves the
|
|
1753
|
-
supply-chain document with it.
|
|
1754
|
-
- `core.clamp`, replacing two byte-identical private `clamp` helpers in `rpg.Collision` and
|
|
1755
|
-
`two-d.render.Camera`.
|
|
1756
|
-
- `two-d/pixi-interop`'s `registerBuiltinPipes()` (item 297), plus re-exporting
|
|
1757
|
-
`TilingSpritePipe`/`NineSliceSpritePipe` themselves, for a consumer bundler that tree-shook
|
|
1758
|
-
a built-in Pixi pipe away despite importing the full `pixi.js` package.
|
|
1759
|
-
- `ui.ListView.tapRow(index)` (item 299), the `IconGrid.tapCell`-shaped public method for the
|
|
1760
|
-
select-and-confirm-in-one-step tap a row's own `pointerdown` handler already did.
|
|
1761
|
-
- `assets.setAssetMap(map)` (item 300): hands `resolve`/`has`/`paths`/`isCompiled` a game's
|
|
1762
|
-
own path-to-URI map directly, taking priority over `window.__MWG_ASSETS__` while set, for a
|
|
1763
|
-
game whose own bundler compiles assets a different way than `tools/compile-resources`.
|
|
1764
|
-
- `two-d.render.StatusVisuals.flash(color, strength, duration)` (item 301): a one-shot,
|
|
1765
|
-
linearly-decaying additive pulse layered on top of whatever statuses are active.
|
|
1766
|
-
- `two-d.render.ScreenEffects.sequence(steps)` and a new `hold` phase (item 302): chains
|
|
1767
|
-
fade/hold/flash steps end to end as one call, for the hold-then-fade-back transition
|
|
1768
|
-
`fadeOut`/`fadeIn`/`flash` alone cannot express; `update` keeps returning false at every
|
|
1769
|
-
step boundary, true only once the whole sequence finishes.
|
|
1770
|
-
- `two-d.render.Camera.shakeScreen(intensity, duration)` (item 303): `shake` taking screen
|
|
1771
|
-
pixels instead of world units.
|
|
1772
|
-
- `mwl.MwlValidationOptions.rowIdScope` (item 304): `'file'` scopes `MWL_DUPLICATE_ID`'s
|
|
1773
|
-
`tag:id` key per source file instead of the whole compiled catalog, for a game whose id
|
|
1774
|
-
convention reuses ids across files on purpose.
|
|
1775
|
-
- `two-d.render.spriteColorMatrix(sprite, matrix)` (item 309): attaches any of
|
|
1776
|
-
`blendMatrix`/`channelScaleMatrix`/`channelSwapMatrix`/`colorShiftMatrix` (or a game's own
|
|
1777
|
-
matrix) to a sprite as a `ColorMatrixFilter`, without needing a direct `pixi.js` import just
|
|
1778
|
-
to construct that one class.
|
|
1779
|
-
- `assets.load` now supplies Pixi's `Assets.add` a `format` hint (the original path's own
|
|
1780
|
-
extension) whenever the resolved `src` is a compiled build's `data:` URI (item 308), since
|
|
1781
|
-
the URI itself carries no extension for Pixi's resolver to pick a parser from. No new
|
|
1782
|
-
argument: a game still calls `load(['tiles.png'])` exactly as before.
|
|
1783
|
-
- `[item]` accepts `image`/`icon` (item 307), carried through
|
|
1784
|
-
`MwlItemDefinition.image`/`.icon`; both were already recognised as asset attributes by the
|
|
1785
|
-
manifest scanner, so this closes the schema gate that was blocking them.
|
|
1786
|
-
- `tools/classic-html.mjs`'s `toClassicScript(html)` (item 306), shipped in the npm package:
|
|
1787
|
-
rewrites a bundler build's `<script type="module">` entry tag to a classic deferred one, so
|
|
1788
|
-
the page opens via `file://`. `tools/emit-page.mjs` now uses it too, instead of its own copy
|
|
1789
|
-
of the same rewrite.
|
|
1790
|
-
- `two-d.render.applyAllImageModifiers(sprite, parsed, probe?, scale?)` (item 310): runs
|
|
1791
|
-
`applyTextureModifiers`'s exact pixel-level baking and `applyImageModifiers`'s sprite-level
|
|
1792
|
-
modifiers in the order a caller with a `~BLEND`/`~ROTATE` path needs, so the two no longer
|
|
1793
|
-
have to be driven by hand.
|
|
1794
|
-
- `two-d.render.createLayers(parent, names)` (item 312): builds one labeled `Node2D` per name,
|
|
1795
|
-
attached to `parent` in the order given and returned keyed by name, for the conventionally
|
|
1796
|
-
ordered layer stack (terrain, units, effects, UI, ...) a game otherwise hand-wires.
|
|
1797
|
-
- `ui.RichLabel`/`ui.MarkupText` take `tagStyles` (item 313), the same custom-inline-tag option a
|
|
1798
|
-
bare `Text2D` takes. `markup.parseMarkup` gained `MarkupOptions.tags` and a `MarkupSpan.tag`
|
|
1799
|
-
field so the parser stays renderer-neutral: `MarkupText` applies each tag's Pixi style to its
|
|
1800
|
-
run and measures under it, while `RichLabel` keeps a registered tag as a real element for
|
|
1801
|
-
`HTMLText` and still escapes an unregistered one.
|
|
1802
|
-
- `two-d.render.Projectile` takes an optional `animation` (item 311): the projectile advances
|
|
1803
|
-
the flight frames with its own elapsed time and reports the current one through
|
|
1804
|
-
`frame`/`frameOffset`, so a missile with `[missile_frame]` art no longer needs a parallel
|
|
1805
|
-
animation and clock kept in step by the game.
|
|
1806
|
-
|
|
1807
|
-
### Changed
|
|
1808
|
-
|
|
1809
|
-
- **Breaking:** `two-d.render.StatusVisuals` now composes every active status's colour
|
|
1810
|
-
additively (each channel clipping at 1) instead of one status winning by declaration order,
|
|
1811
|
-
and never writes the multiply `tint` any more, so a sprite's own identity tint survives
|
|
1812
|
-
underneath (item 301). `TintTarget` is now just `{ colorAdd: number }`; `lerpTint`/
|
|
1813
|
-
`resetColor` are no longer part of its contract.
|
|
1814
|
-
|
|
1815
|
-
### Fixed
|
|
1816
|
-
|
|
1817
|
-
- Documented, in `tools/mwl.mjs` and README's MWL section, that a game needing more than
|
|
1818
|
-
`mwl build`'s three standard files should write its own build script against the public MWL
|
|
1819
|
-
library API rather than look for a CLI flag (item 305).
|
|
1820
|
-
- Corrected two contradictory doc comments (item 298): `Shape2D.ts` claimed `Container2D` was
|
|
1821
|
-
a type alias a game could not `new`, when it is a value re-export and always was; and
|
|
1822
|
-
`pixi-interop.ts`'s "no registration needed" guarantee is `pixi.js`'s own `sideEffects` list
|
|
1823
|
-
surviving the consumer's own bundler, not a universal property.
|
|
1824
|
-
- `withTextureCanvas`'s pixel-level modifiers (`~BLIT`/`~MASK`/`~BLEND`/`~ROTATE` in
|
|
1825
|
-
`applyTextureModifiers`, and `recolorTexture`) called a real
|
|
1826
|
-
`CanvasRenderingContext2D.putImageData` with a plain `{data, width, height}` object, which a
|
|
1827
|
-
real browser rejects (it needs an actual `ImageData`); a test-supplied `probe.createCanvas`
|
|
1828
|
-
never hit the real canvas path, so the bug had no unit-test coverage. `withTextureCanvas` now
|
|
1829
|
-
wraps the real context's `putImageData` to build a proper `ImageData` itself, so every
|
|
1830
|
-
pixel-level modifier keeps writing the same plain object.
|
|
1831
|
-
- `[filter]`/`[have_unit]` `x`/`y` now accept the comma-separated lists and inclusive ranges
|
|
1832
|
-
(`x=1,2,4-5`) a moveto event's own `x`/`y` already did (item 314); the schema types them
|
|
1833
|
-
`coordinate` and `unitMatchesFilter` reads them through the one `coordinateMatches`.
|
|
1834
|
-
|
|
1835
|
-
## [0.7.8] - 2026-09-12
|
|
1836
|
-
|
|
1837
|
-
### Added
|
|
1838
|
-
|
|
1839
|
-
- Unit identity usable by the AI. MWL units now carry their own `name`, `role`/function and
|
|
1840
|
-
`can_recruit` leader flag: `[unit]` sets them, a side's own leader is `can_recruit`, `[role]`
|
|
1841
|
-
stamps the role onto the units it matches, `[store_unit]`/save keep them, and `unitMatchesFilter`
|
|
1842
|
-
reads all three - which also wires up the `can_recruit` the `[filter]` schema already allowed but
|
|
1843
|
-
the runtime ignored. On the AI side, `ScoreSubject` and `HeuristicCandidate` carry
|
|
1844
|
-
`type`/`role`/`can_recruit`/`name`, and the new `subjectsWhere`/`ScoreSubjectFilter` select a world
|
|
1845
|
-
on any of them, so a mind can find "the enemy leader" without re-deriving it from ids.
|
|
1846
|
-
- Leader identity on the unit (item 296). An autospawned `[side] leader=` unit carries `leader: true`
|
|
1847
|
-
beside its `can_recruit`, `[store_unit]`/unstore and a save keep it, and `unitMatchesFilter` reads
|
|
1848
|
-
it, so `[filter] leader=yes` finds the side's own leader without recomputing
|
|
1849
|
-
`sides[id].leader === id`.
|
|
1850
|
-
- One variable-path resolver for every reader (item 295). `$name` resolution, `[condition]`/
|
|
1851
|
-
`[filter_condition]` variable reads, message interpolation and the bare `$name` copy all resolve
|
|
1852
|
-
through the same path walker `set_variable` writes with, so a dotted name like `a.b` reads what
|
|
1853
|
-
`[set_variable] name=a.b` wrote. Array indices are in scope (`a[0].b` reads the node `a.0.b` or
|
|
1854
|
-
`a[0].b` wrote), an index that is not a whole number is refused by name rather than becoming a
|
|
1855
|
-
literal key, and the `id` schema type accepts brackets so such a name compiles.
|
|
1856
|
-
- `TerrainGraphicsLayer` (item 257): the renderer half of `[terrain_graphics]`, drawing
|
|
1857
|
-
`resolveTerrainGraphics`'s placements as one `Sprite2D` per placement, in `layer` order (a stable
|
|
1858
|
-
sort, so the rule pass's own row-major walk survives within a layer) at the pixel position a
|
|
1859
|
-
caller-supplied `project` callback reports, with images resolved through the asset resolver.
|
|
1860
|
-
`setPlacements` redraws in place.
|
|
1861
|
-
- The canvas backend for inline markup, closing the three pieces item 258's acceptance still
|
|
1862
|
-
named as open: `positionMarkupLines` places `layoutMarkupLines`'s lines into positioned
|
|
1863
|
-
`PositionedMarkupSpan` runs under a `MarkupLayout`'s `direction`/`align`, so an `rtl` line flows
|
|
1864
|
-
right to left and alignment defaults to the direction's own edge, and `MarkupText` draws them as
|
|
1865
|
-
the counterpart to `RichLabel`'s HTML text - one `Text2D` per styled run, one `Sprite2D` per
|
|
1866
|
-
`<img>` span resolved through the asset resolver, so an image is drawn rather than left to the
|
|
1867
|
-
caller to position. An RTL sample is now covered by `tests/markup.test.ts`.
|
|
1868
|
-
|
|
1869
|
-
### Fixed
|
|
1870
|
-
|
|
1871
|
-
- One rule for the `id` value type, shared by the schema and `mwl.readers`. The schema accepts a
|
|
1872
|
-
bracketed path like `a[0].b` as an `id` (a variable name legitimately carries index brackets),
|
|
1873
|
-
but `readAttributes`' `id` and `id-list` kept a stricter copy of the pattern, so an adapter
|
|
1874
|
-
reading a variable-name attribute raised `MWL_FIELD_TYPE` for a name the compiler had already
|
|
1875
|
-
accepted. Both now call the exported `isMwlId`. One test in `tests/mwl.test.ts`.
|
|
1876
|
-
- `actors.sell` is transactional again. It ignored the result of `Inventory.add`, so selling into
|
|
1877
|
-
a shop stock with no room paid the seller and lost the item: two potions sold into a
|
|
1878
|
-
capacity-1 stock produced 10 gold from nothing and left the potions nowhere. It now rolls the
|
|
1879
|
-
bag back and refuses, exactly as `buy` already did for a full bag. One test in
|
|
1880
|
-
`tests/shop.test.ts`.
|
|
1881
|
-
- `board.goScore` counts territory again. Its `group` helper returned nothing for an empty
|
|
1882
|
-
square, so the area-scoring loop never saw an enclosed empty region and only stones were
|
|
1883
|
-
scored: four stones ringing a 3x3 board reported 4 instead of 9. `group` now groups connected
|
|
1884
|
-
cells by value with `null` included, which leaves `liberties`/`playGo` unchanged because they
|
|
1885
|
-
only ever pass a stone. One test, plus new coverage for `rollBackgammonDice`, a foundation
|
|
1886
|
-
move from a tableau column, and `DiceCup.clearKept`, in `tests/classics.test.ts`.
|
|
1887
|
-
- `board.addTacticalUnit` remembers each unit's own action budget, so `endTacticalTurn` refreshes
|
|
1888
|
-
`actions` to it instead of a hardcoded two. A unit created with `actions: 3` was silently reset
|
|
1889
|
-
to 2 every turn; the per-turn maximum is now `TacticalUnit.maxActions`, filled from the initial
|
|
1890
|
-
`actions` when the caller does not set it. Six tests in `tests/tactics.test.ts`, which also
|
|
1891
|
-
cover the overwatch reaction and attack paths that had none.
|
|
1892
|
-
- `board.backgammonMoves` follows the bearing-off rules. It offered a bear-off from any point
|
|
1893
|
-
whose roll reached past the off edge, so at the opening position a 6 came off from point 18
|
|
1894
|
-
while checkers still sat on 0, 11 and 16. A bear-off now needs every checker in the home
|
|
1895
|
-
board with none on the bar; an exact roll still takes any home checker, and an over-roll takes
|
|
1896
|
-
only the checker nearest the off edge, since a checker must never skip past another. Three
|
|
1897
|
-
tests in `tests/classics.test.ts`.
|
|
1898
|
-
- An `[if]` branch no longer tries to execute its own `[condition]` child. The schema allows a
|
|
1899
|
-
branch to carry one, but the executor ran every child, so an `[if]` whose condition held threw
|
|
1900
|
-
`unknown MWL command: condition` instead of running its body; a false condition hid it because
|
|
1901
|
-
the body never ran. `[if]`/`[else]` now run their command children only, the same rule
|
|
1902
|
-
`[while]` already followed. Two tests in `tests/mwl-conditions.test.ts`.
|
|
1903
|
-
- An `[else]` following an `[if]` is that branch's other half, so only one of the two runs. A
|
|
1904
|
-
taken `[if]` used to run its own body and then fall through to the `[else]` as well, so both
|
|
1905
|
-
branches executed; the `[else]` is now skipped when the `[if]` was taken, and run as the
|
|
1906
|
-
fallback when it was not. Independent pairs still work, and a free-standing `[else]` with no
|
|
1907
|
-
`[if]` before it still runs. Two tests in `tests/mwl-conditions.test.ts`.
|
|
1908
|
-
- `[while]` had the same defect as `[if]`, so a loop body carrying a `[condition]` child threw.
|
|
1909
|
-
It now runs its command children too. One test in `tests/mwl-variables.test.ts`.
|
|
1910
|
-
- The variable-path readers item 295 named are now complete, closing three that were still flat:
|
|
1911
|
-
a dialogue `[choice]`'s `variable=` gate, `[store_unit]`/`[unstore_unit]`/`[recall]`'s stored
|
|
1912
|
-
list, and the hook host's `setVariable`, plus the public `execute()`'s `set_variable`. An
|
|
1913
|
-
indexed path now builds a real array (`a[0]`, `a[1]`), so a stored list and an indexed write
|
|
1914
|
-
agree on their shape. One test each in `tests/mwl-dialogue.test.ts`, `tests/mwl-actions.test.ts`
|
|
1915
|
-
and `tests/mwl.test.ts`, and the `a[0].b` test now asserts the array.
|
|
1916
|
-
|
|
1917
|
-
### Changed
|
|
1918
|
-
|
|
1919
|
-
- `board.skirmishMoves` computes every reachable cell from one Dijkstra pass over the map
|
|
1920
|
-
instead of one per candidate cell. The old per-cell search also re-sorted its own frontier
|
|
1921
|
-
every step and `shift()`ed it, so it went quadratic in path length; the pass now uses a
|
|
1922
|
-
binary min-heap. Behaviour is unchanged, verified by a differential run of the old and new
|
|
1923
|
-
implementations over 58 randomised terrain maps. A `[complexity]` test keeps 20 calls on a
|
|
1924
|
-
40x40 map under a ceiling far below the old cost, and a test pins that a cell held by
|
|
1925
|
-
another unit is never offered as a move.
|
|
1926
|
-
|
|
1927
|
-
## [0.7.7] - 2026-09-11
|
|
1928
|
-
|
|
1929
|
-
### Added
|
|
1930
|
-
|
|
1931
|
-
- Heuristic AI (item 269): `Aspects`, `Difficulty`, `Goals`, `RecruitmentPattern`, and a
|
|
1932
|
-
`HeuristicAI` candidate/stage pipeline with `defaultWeigh`/`keepAwayScore`/`goalScore`. Aspects
|
|
1933
|
-
ship no values; the numbers stay content, and `keep_away` is a real penalty.
|
|
1934
|
-
- Achievements and battle statistics (item 273): `core.Achievements` gained sub-achievements
|
|
1935
|
-
(multi-criterion unlocks via `AchievementDef.criteria`, read back with `subProgress`), and
|
|
1936
|
-
`battle.BattleStats` tracks recruits/recalls/advances/kills/deaths/damage dealt/damage taken by
|
|
1937
|
-
unit type for a `PlayerStats`/`RunHistory` summary to fold in.
|
|
1938
|
-
- Free map rotation (item 286): `Camera.rotateTo`/`animateRotationTo` turn the view to any angle,
|
|
1939
|
-
not only a grid's whole steps, sharing 285's layer-level transform and taking the shorter way
|
|
1940
|
-
around a full turn when animated.
|
|
1941
|
-
- Battle UI models (item 265): `AttackPreview` (damage totals and an animated frame timeline from
|
|
1942
|
-
the game's own numbers), `AttackDialog` (the selector plus the preview and its clock),
|
|
1943
|
-
`UnitSelector` (attacker then target), and `Whiteboard` (planned orders with undo/redo). All
|
|
1944
|
-
renderer-free; the dialog's pixels are `Bar`/`Label` a game composes.
|
|
1945
|
-
- Story screens (item 264): `StoryScreen` (a full-screen backdrop, title and text advanced by a
|
|
1946
|
-
click) over the renderer-free `StorySequence` (`advance`/`back`/`goTo`/`skip`/`restart`, with the
|
|
1947
|
-
current beat's `music` reported as a signal). `StoryBeat` matches `MwlWorld.story`'s shape.
|
|
1948
|
-
- Data-driven shell layout and skins (item 263): `Layout` (`resolveAnchor`/`anchorAlign` over nine
|
|
1949
|
-
named anchors plus `fill`, and a `Grid` of `size`-or-`grow` tracks) and `Skins` (per-widget,
|
|
1950
|
-
per-state looks with a widget-state -> widget-idle -> wildcard fallback chain, and `Skins.from`
|
|
1951
|
-
for plain data). Both renderer-free.
|
|
1952
|
-
- The missing UI widgets (item 261): `Slider` (`sliderFraction`/`sliderValueAt`), `Checkbox`,
|
|
1953
|
-
`Spinner` (`spinValue`), `Dropdown`, `TextModel`, `DataTable`, `TreeView` and `ScrollBox`
|
|
1954
|
-
(`scrollOffset`). The rule-bearing parts are pure functions or renderer-free models tested
|
|
1955
|
-
headlessly, the drawing is a thin theme-driven shell, and text fields pair `TextModel` with a
|
|
1956
|
-
`Label` rather than a separate `TextArea`.
|
|
1957
|
-
- Fixed-angle view rotation on `Camera` (item 285): `grid: 'square' | 'hex'` sets four quarter turns
|
|
1958
|
-
or six 60-degree steps, `setRotationStep`/`rotate` move through them, `toScreen`/`toWorld` invert
|
|
1959
|
-
the turn, `view` reports the box around the turned viewport for culling, and `uprightRotation`
|
|
1960
|
-
keeps a label drawn into the world upright.
|
|
1961
|
-
- WML action vocabulary in `[event]` (item 250): `fire_event`, `store_unit`/`unstore_unit`/`recall`,
|
|
1962
|
-
`modify_unit`/`heal_unit`, `set_terrain`, `capture_village`, `clear_shroud`, and the scenario-level
|
|
1963
|
-
`[role]`/`[object]`/`[story]`, backed by `MwlWorld.villages`/`clearedShroud`/`roles`/`objects`/
|
|
1964
|
-
`story` (all saved). WML's scenario `[item]` is deliberately not added: the tag already means an
|
|
1965
|
-
inventory item definition.
|
|
1966
|
-
- `blendPixels`/`rotatePixels` in `ImageModifiers.ts`: `~BLEND` and `~ROTATE` moved from a
|
|
1967
|
-
runtime sprite-property/`ColorMatrixFilter` approximation to an exact, baked-once per-pixel
|
|
1968
|
-
operation in `applyTextureModifiers` (`~ROTATE` in particular now rotates the source pixels
|
|
1969
|
-
and expands the surface, which a sprite's own `rotation` cannot do - needed for terrain and
|
|
1970
|
-
anything else that must keep tiling after the rotation). `blendMatrix` stays available for a
|
|
1971
|
-
caller that explicitly wants the cheaper live approximation instead.
|
|
1972
|
-
- `PaletteRemapMode` (`'exact'` | `'nearest'`) on `remapPixels`/`recolorTexture`, defaulting to
|
|
1973
|
-
`'exact'`: a pixel is now repainted only on an exact match to a `from` colour unless
|
|
1974
|
-
`'nearest'` is asked for explicitly. The old always-nearest behaviour silently recoloured an
|
|
1975
|
-
entire image the first time `~RC`/`~PAL` met a short, specific palette instead of a full
|
|
1976
|
-
covering; `paletteRangeMapping`'s own gradient usage opts into `'nearest'` explicitly, since
|
|
1977
|
-
that is the one case it is correct for.
|
|
1978
|
-
- `ImageTextureProbe.resolveColor` and the exported `parseColorPairs`/`parsePaletteLists`: `~RC`
|
|
1979
|
-
and `~PAL` now accept a named colour (`~RC(magenta>red)`), not hex only, and `~PAL`'s two
|
|
1980
|
-
comma-separated colour lists parse correctly instead of only the first colour of each list
|
|
1981
|
-
(`parseImagePath`'s own comma split does not respect that list's internal boundary, which
|
|
1982
|
-
`parsePaletteLists` now reconstructs).
|
|
1983
|
-
- `~BLIT`/`~MASK` now hand `resolveTexture` the argument exactly as written, nested modifiers
|
|
1984
|
-
included (`~BLIT(unit.png~RC(magenta>red),0,0)` calls it with the full string, not a bare
|
|
1985
|
-
path with the modifier silently dropped).
|
|
1986
|
-
- `withTextureCanvas` is now exported from `two-d/render`, so a caller building its own
|
|
1987
|
-
texture-level modifier can reuse the same canvas bookkeeping `recolorTexture`/`~BLIT`/`~MASK`/
|
|
1988
|
-
`~BLEND`/`~ROTATE` all share instead of duplicating it.
|
|
1989
|
-
|
|
1990
|
-
- `mwl.parseMapFile`/`MwlMapFile` (item 284): a Wesnoth-shaped `.map` loader. The `key=value`
|
|
1991
|
-
header is split off and kept (keys not interpreted), and the comma-separated grid goes through
|
|
1992
|
-
the same `parseTerrain` an inline `[map] terrain=` uses.
|
|
1993
|
-
- `actors.craft` category-shaped ingredients (item 289): `Ingredient` now accepts `id` as a string
|
|
1994
|
-
or a list, a `category` matched against the item definition's new `InventoryItem.category`
|
|
1995
|
-
(kind-level, so it stays out of saves), or a `matches(item)` predicate. `craft` allocates against
|
|
1996
|
-
a working copy so two flexible ingredients cannot count one stack twice.
|
|
1997
|
-
- `two-d/render/SpriteAttachment.ts`: `SpriteAttachment` (item 291), ties a second sprite's
|
|
1998
|
-
position to a first one's - `follow(x, y)` applies an offset, an optional `duration` makes
|
|
1999
|
-
`update(dt)` report `done` once it elapses, so a permanent shadow and a temporary status icon
|
|
2000
|
-
are the same class with different options. Renderer-neutral like `Projectile`/`LightningArc`.
|
|
2001
|
-
|
|
2002
|
-
- `two-d/render/LightningArc.ts`: `LightningArc` (item 292), the position data for a jittered
|
|
2003
|
-
line between two points - a lightning bolt, a tether, a chain-lightning link - geometry only,
|
|
2004
|
-
drawn by the caller through `Shape2D`'s `Graphics`. `retarget` moves either endpoint for a
|
|
2005
|
-
tether following two moving units; an optional `flickerInterval` re-rolls the jitter on a
|
|
2006
|
-
timer instead of holding one fixed shape.
|
|
2007
|
-
- `assets.load`'s `optional`/`onMissing` options (item 287): paths a game can do without load
|
|
2008
|
-
separately from the required batch, so one missing file never aborts the rest; `texture`/`get`
|
|
2009
|
-
take a `fallback` value returned instead of a throw for a path that never loaded.
|
|
2010
|
-
|
|
2011
|
-
- `MultiTurnBeam` fronts, `blocker`, `onCell` and saved shape identity (item 278): a beam is now a
|
|
2012
|
-
sequence of per-turn fronts rather than one captured cell per turn, so a game-supplied
|
|
2013
|
-
`fronts(previous, turn)` expresses a cone, burst, fork or moving front. `BeamBlocker` replaces
|
|
2014
|
-
the implicit blocker flags with one policy, `BeamStep.cells` reports every reached cell, and a
|
|
2015
|
-
save carries the shape name so `fromJSON` refuses a mismatched shape; pre-fronts saves still load.
|
|
2016
|
-
- `two-d/render/PaletteRemap.ts`: `remapPixels`/`paletteRangeMapping`/`recolorTexture` (item
|
|
2017
|
-
256), a nearest-colour palette remap for team-colour-by-range - `paletteRangeMapping` places a
|
|
2018
|
-
reference palette's own lightest-to-darkest order along a `min -> mid -> max` gradient,
|
|
2019
|
-
`remapPixels` is the renderer-free pixel core, and `recolorTexture` (via the new shared
|
|
2020
|
-
`withTextureCanvas` helper) is the canvas-backed wrapper.
|
|
2021
|
-
- Eleven more `image~MOD` suffixes in `ImageModifiers.ts` (item 255): `~O`, `~R`/`~G`/`~B`,
|
|
2022
|
-
`~BLEND` and `~CHAN` join `~FL`/`~SCALE`/`~GS`/`~CS` as sprite-property/`ColorMatrixFilter`
|
|
2023
|
-
operations on `applyImageModifiers`; `~ROTATE` sets the sprite's own rotation. `~RC`, `~PAL`,
|
|
2024
|
-
`~BLIT` and `~MASK` needed real pixel access or a sibling texture, so they are the new
|
|
2025
|
-
`applyTextureModifiers`, built on 256's `withTextureCanvas`. `~GS` no longer replaces a filter
|
|
2026
|
-
already on the sprite (was clobbering, now appends).
|
|
2027
|
-
- `two-d/render/TerrainGraphics.ts`: `resolveTerrainGraphics`/`TerrainRule`/`matchTerrainRule`/
|
|
2028
|
-
`squareRotate`/`hexRotate` (item 257), a rule-driven `[terrain_graphics]`-style transition pass
|
|
2029
|
-
generalising `Autotile`'s fixed 47-shape blob table: arbitrary flag conditions at arbitrary
|
|
2030
|
-
offsets, multi-image placement (so a piece bigger than one cell is one rule's own data, not
|
|
2031
|
-
something `TileMap`'s one-sprite-per-cell grid has to hold), rotation and probability. Returns
|
|
2032
|
-
plain placement data; drawing it through a renderer is still open.
|
|
2033
|
-
- `markupToHtml` now renders colour and size as an inline style; `markupAccessibilityText` is a
|
|
2034
|
-
proper accessibility projection for markup (an image becomes a caller-described string instead
|
|
2035
|
-
of its raw path); `layoutMarkupLines` wraps already-parsed spans word by word, each word
|
|
2036
|
-
measured under its own span's style, so a bold or larger run wraps where its own wider glyphs
|
|
2037
|
-
actually land (item 258's remaining acceptance, in part - see ROADMAP for what is still open).
|
|
2038
|
-
|
|
2039
|
-
- `ParticleEmitter` spawn bounds (item 279): `ParticleSpawnArea` is an optional `spawn` on the
|
|
2040
|
-
emitter's options, a `rect` or `ellipse` in local space so a burst spreads across an extent
|
|
2041
|
-
instead of every particle starting at the emitter's single origin (a forge mouth, a flame
|
|
2042
|
-
column, rain across a room). A point emitter draws nothing extra, so the seeded sequence an
|
|
2043
|
-
existing replay recorded is unchanged.
|
|
2044
|
-
- `roguelike.TargetingController` (item 280): the input-facing half of targeting, renderer-free.
|
|
2045
|
-
A cursor moved by `move(dx, dy)` or a caller-resolved `moveTo(cell)`, range and line-of-sight
|
|
2046
|
-
validation with an optional `validate` hook, a `preview()` of the shape's cells and a
|
|
2047
|
-
`confirm()`/`cancel()` result carrying cells only, so damage, legality details and drawing stay
|
|
2048
|
-
with the game. Hex levels step by their own six neighbours and measure in hex distance.
|
|
2049
|
-
- `AudioListener`/`SoundSource`/`audioGain`/`audioPan`/`AudioFalloff` (item 271): positional
|
|
2050
|
-
audio, renderer-free. A listener the game moves and turns, a `Sound` placed at a world point,
|
|
2051
|
-
and the distance gain and stereo pan between them. `SoundSource.playFor(listener)` applies the
|
|
2052
|
-
gain through `Sound.play`, which now takes an optional gain argument.
|
|
2053
|
-
- `Input.onText`/`Input.onComposition`/`Input.textFromKey`/`Input.dispatchText`/
|
|
2054
|
-
`Input.dispatchComposition` (item 262): the character a key press produces, and the three
|
|
2055
|
-
phases of an input-method composition, so a free text field can be built. `onText` is a
|
|
2056
|
-
stack-mode signal a focused field can consume.
|
|
2057
|
-
- `MersenneTwister`/`MersenneTwisterState`/`RandomStreams` (item 266): MT19937 with the reference
|
|
2058
|
-
`mt_rng`'s `seed`/`discard`/`discardCount` bookkeeping (verified against the standard test
|
|
2059
|
-
vector) and named, independent streams derived from one base seed, so per-entity and per-usage
|
|
2060
|
-
draws never shift each other. C++'s `uniform_int_distribution` is implementation-defined, so the
|
|
2061
|
-
int mapping is MWG's own and documented as such.
|
|
2062
|
-
- `i18n.parsePo`/`PoOptions` (item 270): a gettext `.po` loader into the same `Catalog` surface
|
|
2063
|
-
as `parseFTL`, with `msgctxt`, `msgstr[N]` mapped onto the locale's CLDR categories,
|
|
2064
|
-
untranslated entries left out for base fallback, and gettext `domain`-prefixed keys.
|
|
2065
|
-
- `world.SideTurns`/`SideTurn`/`TimeOfDay`/`TimeArea`/`Alignment`/`alignmentBonus` (item 267): the
|
|
2066
|
-
reference's outer turn model, sides in order with a schedule that steps per round, and a per-hex
|
|
2067
|
-
`lawfulBonusAt` where a `TimeArea` overrides the global time of day.
|
|
2068
|
-
- `ui.TabbedList`/`ListTab`/`TabbedListOptions` (item 281): a renderer-free model for a tabbed,
|
|
2069
|
-
filtered, paged list with selection and a detail/close state, over caller-supplied rows and
|
|
2070
|
-
predicates. The page is derived from the selection, so the two cannot disagree.
|
|
2071
|
-
- `simulation.EventPresentation`/`EventPresentationOptions` (item 282): the documented recipe
|
|
2072
|
-
tying a `SimulationRuntime` to a `PresentationQueue` - command result, animation lock,
|
|
2073
|
-
scheduled secondary actor, cancellation, and save/load that resumes idle.
|
|
2074
|
-
- `MwlWorld.sideStatus` and per-side `[victory]`/`[defeat]` under `[side]` (item 283): a side's
|
|
2075
|
-
own condition is evaluated after the scenario-wide `[objectives]` ones, its result recorded by
|
|
2076
|
-
side id, and `[win]`/`[lose]` record the side they name too. `MwlCommand`'s `win`/`lose` gained an
|
|
2077
|
-
optional `side`.
|
|
2078
|
-
- `simulation.CampaignSave`/`CampaignSaveState`/`CampaignSaveParts` (item 249): one `SaveSystem`
|
|
2079
|
-
slot for a whole campaign, holding the campaign, world and simulation snapshots together, with
|
|
2080
|
-
the world payload left opaque.
|
|
2081
|
-
- `core.stateChecksum`/`core.SyncGuard` (item 272): a key-order-stable 32-bit checksum of JSON
|
|
2082
|
-
state and a guard comparing the checksums peers compute per tick, so a lockstep run can notice
|
|
2083
|
-
and locate a divergence.
|
|
2084
|
-
- `ai.personalScoreView`/`ai.sideScoreView`/`ai.scoreWith`, over `ScoreSubject`/`ScoreView`/
|
|
2085
|
-
`ScorePersonality` (items 274-276): the numbers a mind needs when a search is the wrong tool.
|
|
2086
|
-
The game supplies what anything is worth, the framework assembles the view (own, allies and
|
|
2087
|
-
enemies kept apart, with a `seen` count), and a personality is weights over the three, so a
|
|
2088
|
-
selfish scout and a loyal one are content rather than two AI implementations. A unit's sight and a
|
|
2089
|
-
whole side's read through the same two functions and differ only in the visibility set they are
|
|
2090
|
-
handed, and `board.FactionFog.sees(side)` is that set as a predicate: it reads the shroud as it is
|
|
2091
|
-
when called, not as it was when the predicate was made.
|
|
2092
|
-
- `Animation`/`AnimatedSprite` frame timing (item 254): a frame is now a texture or
|
|
2093
|
-
`{ texture, duration, offsetX, offsetY }`, so a frame carries its own time and its own place, as
|
|
2094
|
-
Wesnoth's `image=a.png:120,b.png:80` does, and `AnimationOptions.startTime` is signed the way
|
|
2095
|
-
Wesnoth writes it: positive holds the first frame, negative starts partway in (`start_time=-450`
|
|
2096
|
-
over frames of 100ms opens on the fifth, which is how a swing is lined up with its damage frame).
|
|
2097
|
-
`Animation.frameAt`/`frameIndexAt` are the rule, the sprite advances on its own elapsed time
|
|
2098
|
-
rather than a leftover timer, and a frame's offset is reported through `AnimatedSprite.frameOffset`
|
|
2099
|
-
for the caller to add where it already positions the sprite.
|
|
2100
|
-
- `FactionFog.share(factions)` (item 268): factions put on one map, what is lit now and the shroud
|
|
2101
|
-
they remember alike, which is what Wesnoth's `share_vision` means. Nothing shares until asked,
|
|
2102
|
-
growing a group widens it rather than replacing it, and a share declared after a `sync` still
|
|
2103
|
-
counts because the group is read when a cell is asked about. `sees(side)` follows it, so a side's
|
|
2104
|
-
score view reads the team's eyes.
|
|
2105
|
-
- `campaignChain` (item 247): a `[campaign]` pointed at `simulation.Campaign`. `first_scenario` opens
|
|
2106
|
-
it, each `[scenario]`'s `next_scenario` is where it goes when it is won, and the chain ends where a
|
|
2107
|
-
scenario has no next one. The order is content and the playing stays the game's, since the runner
|
|
2108
|
-
is a callback; a scenario that decides for itself keeps its decision, which is where a runtime
|
|
2109
|
-
`[endlevel]` will hook in. Malformed chains (no scenarios, one id twice, an unknown
|
|
2110
|
-
`first_scenario`) throw by name. The `[campaign]` schema now accepts `first_scenario`, and
|
|
2111
|
-
`contentCatalog` exposes each campaign's scenario links.
|
|
2112
|
-
- `[endlevel]` and carry-over (item 248): a scenario ends with `result=victory|defeat`, and what it
|
|
2113
|
-
hands on is `endLevelCarryover` - `bonus` plus a share of the side's gold (`carryover_percentage`,
|
|
2114
|
-
80% when unset, which is the reference's own default rather than an invented one), the units of
|
|
2115
|
-
that side still standing as the recall list, and `next_scenario` for where the campaign goes (the
|
|
2116
|
-
hook `campaignChain` already honours). `carryoverIntoScenario` is the other half of the rule: the
|
|
2117
|
-
carried share is added to what the next scenario declares when `carryover_add` asks for it, and is
|
|
2118
|
-
otherwise a floor under it. `MWL_DEFAULT_CARRYOVER_PERCENTAGE` names the default.
|
|
2119
|
-
- `[kill]` as a filter (item 251): naming a unit that is not there still throws, while a `[kill]`
|
|
2120
|
-
whose attributes are a filter over the world's units is a no-op when it matches nobody, as WML's
|
|
2121
|
-
own `[kill]` is. It reads the same attributes an event filter does, an empty filter matches every
|
|
2122
|
-
unit (there as here), and the schema entry is open on attributes so a filter can say what it
|
|
2123
|
-
means.
|
|
2124
|
-
- A scenario turn limit, as a native condition (item 253): `[game] turn_limit=N` makes the runtime
|
|
2125
|
-
set `time_over` as a world variable and fire the `time_over` event once the turn counter passes N.
|
|
2126
|
-
Content tests it like any variable and answers it like any event, `[endlevel]` included, because a
|
|
2127
|
-
limit is usually a defeat and sometimes the whole scenario.
|
|
2128
|
-
- An inline-markup contract, first half of item 258: `MarkupSpan` plus `parseMarkup`/`stripMarkup`/
|
|
2129
|
-
`markupToHtml`/`escapeHtml` in `src/two-d/ui/markup.ts`. Nested emphasis, named and hex colours, a
|
|
2130
|
-
size, a line break, an image span carrying a path, `$name` interpolation supplied by the caller,
|
|
2131
|
-
and the five entities as escapes. Unknown or malformed tags and unset variables stay literal
|
|
2132
|
-
rather than vanishing, and output text is escaped so no raw HTML can leak. What the item's
|
|
2133
|
-
acceptance still wants (backend equivalence, wrapping after styling, images through the asset
|
|
2134
|
-
resolver, an accessibility projection) is recorded on the item rather than implied here.
|
|
2135
|
-
- The `[side]` surface, and one key of it with behaviour (item 252): the Wesnoth keys `team_name`,
|
|
2136
|
-
`user_team_name`, `share_vision`, `village_gold`, `heal`, `fog`, `shroud`, `hidden` and `flag` are
|
|
2137
|
-
read onto `MwlWorld.sides` as written (`yes`/`no` as booleans), and `sideVisionGroups` turns
|
|
2138
|
-
`team_name` with `share_vision` into the groups `FactionFog.share` takes.
|
|
2139
|
-
- Hex projection options, first half of item 259: `hexToPixel`/`pixelToHex` take
|
|
2140
|
-
`HexShape`/`HexOrientation`/`HexOffset`, so a grid can be flat-top or pointy-top with either
|
|
2141
|
-
offset parity, and the default is the flat-top odd-q layout the module always had. The inverse is
|
|
2142
|
-
the nearest cell centre, which cannot disagree with the projection at a hex's edge.
|
|
2143
|
-
- `Halo` (item 260): the glow around a unit, an aura, a shrine's light. An `AnimatedSprite` that
|
|
2144
|
-
`follow(x, y)`s a target with its own offset applied once, additive by default, with z-order left
|
|
2145
|
-
to the caller. `[halo_frame]` needed nothing new after 254 gave frames their own timing.
|
|
2146
|
-
|
|
2147
|
-
### Fixed
|
|
2148
|
-
|
|
2149
|
-
- `FloatingTextStack` stacked the wrong way round: it moved the **newcomer** down by
|
|
2150
|
-
`height + 1`, where Java's `FloatingText.push()` anchors the newcomer on the target and lifts
|
|
2151
|
-
the lines already there to `below.top - height - 4`. A second pop-up on one target in one turn
|
|
2152
|
-
therefore landed *below* the target instead of above the first - found by a consumer measuring
|
|
2153
|
-
it, not by the tests, which asserted the offset's magnitude and never its direction.
|
|
2154
|
-
`floatingTextStackOffset` is replaced by `floatingTextStackLift` (the position the older line
|
|
2155
|
-
must take, rather than an offset the caller adds, so the sign cannot be got wrong quietly) and
|
|
2156
|
-
by `floatingTextStackMoves`, the whole policy: which lines move, newest first, where each one
|
|
2157
|
-
ends up, and what age each is forced to. The loop is arithmetic now, so it is checked as
|
|
2158
|
-
arithmetic rather than through a rendered label. `FLOATING_TEXT_STACK_GAP` names Java's 4px gap.
|
|
2159
|
-
- The lift survived exactly one frame. `FloatingText.update` wrote its own `y` from a base captured
|
|
2160
|
-
on the first frame, so a line the stack had just moved snapped back on the next one: measured, a
|
|
2161
|
-
line lifted to 166.6 was back at 194.4 beside the newcomer at 200, still overlapping it. The rise
|
|
2162
|
-
now moves the pop-up's inner layer and never its position, which belongs to the caller and to the
|
|
2163
|
-
stack; `baseY` is gone. A consumer repositioning a pop-up mid-flight no longer loses the position
|
|
2164
|
-
on the next frame either.
|
|
2165
|
-
- A pop-up scaled *after* `push` was measured before the scale, because a `FloatingText`'s `height`
|
|
2166
|
-
includes its own scale. A port rasterising at 21px and drawing at 7 therefore spaced lifted lines
|
|
2167
|
-
33.4 world pixels apart for lines 9.8 tall. `push` now takes a `scale`, applied before the pop-up
|
|
2168
|
-
is measured, so the entry records the size the line is actually drawn at.
|
|
2169
|
-
|
|
2170
|
-
### Changed
|
|
2171
|
-
|
|
2172
|
-
- `FloatingText.shortenLife(seconds)` becomes `FloatingText.ageAtLeast(seconds)`, which does what
|
|
2173
|
-
Java's rule says rather than something close: `above.timeLeft = Math.min(above.timeLeft,
|
|
2174
|
-
LIFESPAN - numBelow / 5f)` caps what is *left*, and a cap on what is left is a floor under the
|
|
2175
|
-
age. A line that has already lived past the floor keeps the age it has, where subtracting the
|
|
2176
|
-
floor shortened it a second time. `floatingTextAgeAtLeast` is that arithmetic as a pure function,
|
|
2177
|
-
so the difference is checked by a test; `floatingTextStackLifePenalty(linesBelow)` stays the
|
|
2178
|
-
floor itself, a fifth of a second per line below.
|
|
2179
|
-
- A stack keys on `key` alone, as Java's `stacks.get(key)` does. The old rule wanted the same key
|
|
2180
|
-
*and* the same origin, which this framework had invented. A caller that reused one key for two
|
|
2181
|
-
different targets now sees their lines stacked together, and has to give each target its own key.
|
|
2182
|
-
- One side identity in `MwlWorld` (item 277): `unit.side`, `MwlMessage.side`, `MwlMap.starts` keys
|
|
2183
|
-
and every `side`/`side_filter` attribute now hold the string `id` `[side]` declares, so a named
|
|
2184
|
-
side (`id=rebels`) works throughout. `MwlSideRef` is just that id. The `[side] id` and the other
|
|
2185
|
-
side-identifying schema attributes accept a string (numbers still validate), and the map
|
|
2186
|
-
`<side> <code>` keep marker accepts a name.
|
|
2187
|
-
|
|
2188
|
-
### Fixed
|
|
2189
|
-
|
|
2190
|
-
- `ui.Window` (item 290): `closed` is now a getter to guard a caller's reference after `close()`,
|
|
2191
|
-
`close()` is idempotent, input and layout on a closed window are no-ops rather than throws on
|
|
2192
|
-
freed Pixi internals, and `WindowStack.push` refuses a closed window with a named error.
|
|
2193
|
-
|
|
2194
|
-
## [0.7.6] - 2026-09-11
|
|
2195
|
-
|
|
2196
|
-
### Added
|
|
2197
|
-
|
|
2198
|
-
- `Blob.spread` returns the cells it just emptied, in reading order, so a game can turn the ground
|
|
2199
|
-
under a fire to embers at the moment the flames leave it instead of diffing `cellsAbove` between
|
|
2200
|
-
two steps to notice. Cells emptied before the step (a doused one) are not reported.
|
|
2201
|
-
|
|
2202
|
-
### Changed
|
|
2203
|
-
|
|
2204
|
-
- `pixi.js` moved from `dependencies` to an optional peer dependency, the treatment
|
|
2205
|
-
`@babylonjs/core` already had (item 175's 1.0 decision). The install line now names it:
|
|
2206
|
-
`npm install @datamoc/mw_games pixi.js vite`. A game that only uses the renderer-free modules
|
|
2207
|
-
never downloads it. Verified from an empty directory on all three documented paths: the
|
|
2208
|
-
registry install, the `npm pack` tarball installed by path, and the no-install
|
|
2209
|
-
`mw_games.global.js` script tag.
|
|
2210
|
-
|
|
2211
|
-
## [0.7.4] - 2026-09-11
|
|
2212
|
-
|
|
2213
|
-
### Added
|
|
2214
|
-
|
|
2215
|
-
- `FloatingTextStack` owns the pop-ups a game spawns over world points: one `push` per number, one
|
|
2216
|
-
`update(dt)` to drive them all, and pop-ups sharing a key and an origin stack apart instead of
|
|
2217
|
-
overprinting. `FloatingText` gained a `hold` option for the classic hold-then-fade curve, and its
|
|
2218
|
-
rise now moves an inner layer rather than the container itself - it used to overwrite the
|
|
2219
|
-
container's own `y`, so a pop-up positioned at a world point jumped to `y = 0` on its first
|
|
2220
|
-
update. The fade curve and the stacking rule are exported as pure functions, so both are tested
|
|
2221
|
-
without a DOM.
|
|
2222
|
-
- `ParticleEmitter` accepts a `frames` texture sequence, walked per particle across its own life -
|
|
2223
|
-
the four frames of a flame, the puff of smoke - in place of the single `texture`. The current
|
|
2224
|
-
frame is exposed as `Particle.frame` for the same reason the rest of the particle state is.
|
|
2225
|
-
- `Bar` recolours its fill at runtime with `setColor(color)` and takes a `background` colour for its
|
|
2226
|
-
track; both are readable back through `color`/`background`, and a runtime colour counts as
|
|
2227
|
-
explicit so a later theme change cannot throw it away. These were the two blockers for a consumer
|
|
2228
|
-
whose bars change colour with state (a health bar going red as it empties) and whose track is
|
|
2229
|
-
black rather than the theme's panel fill.
|
|
2230
|
-
|
|
2231
|
-
## [0.7.3] - 2026-09-11
|
|
2232
|
-
|
|
2233
|
-
### Added
|
|
2234
|
-
|
|
2235
|
-
- Hex-map parity for targeting, cones, area resolution, minimaps, markers, automap validation,
|
|
2236
|
-
and multi-turn beam traversal, with topology-specific tests.
|
|
2237
|
-
- The `multi-turn-beam` example demonstrates blockers, moving targets, per-turn damage, and
|
|
2238
|
-
deterministic multi-turn action state.
|
|
2239
|
-
|
|
2240
|
-
### Changed
|
|
2241
|
-
|
|
2242
|
-
- The public reference and API report document the new hex-aware map capabilities.
|
|
2243
|
-
|
|
2244
|
-
## [0.7.2] - 2026-09-11
|
|
2245
|
-
|
|
2246
|
-
### Added
|
|
2247
|
-
|
|
2248
|
-
- Renderer-free JavaScript and optional Lua AI modules, including bounded alpha-beta search for
|
|
2249
|
-
local actors and top-level controllers.
|
|
2250
|
-
- MWL typed tables, references, campaign metadata, deterministic artifact emission, and richer
|
|
2251
|
-
event, dialogue, expression, and persistence support.
|
|
2252
|
-
- Stable caller-chosen entity ids, typed 2D value exports, affix pool filtering, and shared
|
|
2253
|
-
CSV/MWL cell coercion.
|
|
2254
|
-
|
|
2255
|
-
### Changed
|
|
2256
|
-
|
|
2257
|
-
- The chess example now uses the shared MWG alpha-beta primitive.
|
|
2258
|
-
- The standalone bundle baseline, API report, documentation, and roadmap were updated.
|
|
2259
|
-
- Release checks now isolate npm audit and package-smoke caches from user-level npm settings.
|
|
2260
|
-
|
|
2261
|
-
## [0.7.1] - 2026-09-10
|
|
2262
|
-
|
|
2263
|
-
### Added
|
|
2264
|
-
|
|
2265
|
-
- MWL content-directory builds now generate game data, i18n, and asset manifests, with the
|
|
2266
|
-
battle example consuming generated MWL content.
|
|
2267
|
-
- `extract:html` extracts inline scripts, styles, data URLs, CSS data URLs, and `srcset`
|
|
2268
|
-
resources from a self-contained HTML file.
|
|
2269
|
-
|
|
2270
|
-
### Changed
|
|
2271
|
-
|
|
2272
|
-
- MWL generated-source diagnostics now use deterministic relative paths.
|
|
2273
|
-
|
|
2274
|
-
## [0.7.0] - 2026-09-10
|
|
2275
|
-
|
|
2276
|
-
### Added
|
|
2277
|
-
|
|
2278
|
-
- MWL build-time compilation with one command producing compiled data, i18n, and asset manifests.
|
|
2279
|
-
- Generic MWL item adapters for inventory, equipment slots, and stat modifiers.
|
|
2280
|
-
- Catalog validation for duplicate ids, slots, effects, and hook references, with source locations.
|
|
2281
|
-
- Game-provided numeric expressions and versioned MWL save migrations.
|
|
2282
|
-
- Wesnoth CFG asset fields including images, profiles, icons, and sounds.
|
|
2283
|
-
|
|
2284
|
-
## [0.6.0] - 2026-09-10
|
|
2285
|
-
|
|
2286
|
-
This is a pre-alpha, not an "early release" any more, and the project says so in README. The
|
|
2287
|
-
same note records the naming plan for future major versions: 1.0 takes a name beginning with A,
|
|
2288
|
-
2.0 one beginning with B, and so on, none of them chosen yet. Code-wise this release is the
|
|
2289
|
-
reduced-motion cluster from WebKit's "Responsive Design for Motion", done properly rather than
|
|
2290
|
-
as a single media query.
|
|
2291
|
-
|
|
2292
|
-
### Added
|
|
2293
|
-
- Reduced motion beyond the media feature (roadmap items 199-202): `MotionIntent` and
|
|
2294
|
-
`motionDuration` let a caller say whether a motion is decorative or meaningful, so a trigger
|
|
2295
|
-
can be replaced by a fade rather than deleted; `Tweener.tween` takes `{ intent, alternate }`;
|
|
2296
|
-
camera follow and `FloatingText`'s rise now respect the preference (and `AnimatedSprite`
|
|
2297
|
-
documents why it deliberately does not); `watchReducedMotion` reports a change while a game is
|
|
2298
|
-
running, so an in-flight tween, burst or fade stops instead of finishing; and the interface
|
|
2299
|
-
example gained a motion demo that `npm run motion:smoke` opens three ways (no preference,
|
|
2300
|
-
`prefers-reduced-motion: reduce` before load, and a flip mid-session) in a real browser.
|
|
2301
|
-
|
|
2302
|
-
## [0.5.5] - 2026-09-10
|
|
2303
|
-
|
|
2304
|
-
Accessibility reaches the framework floor: a reduced-motion switch the tween, particle, camera
|
|
2305
|
-
and screen-effect paths already consult, WCAG contrast helpers for a `theme` palette, and a
|
|
2306
|
-
screen-reader bridge `Window` and `MessageBox` announce through. The verification story catches
|
|
2307
|
-
up as well - a published-package `file://` smoke, a bundle-size budget, a coverage floor,
|
|
2308
|
-
cross-version save fixtures and a build of every example, all gated in CI. `Blob` moves to
|
|
2309
|
-
`core` (a breaking import change) with a per-cell `clear`, `assets.load` can rasterize a vector
|
|
2310
|
-
source at a chosen resolution, and a new benchmark settles the CSS/SVG-animation question in
|
|
2311
|
-
Pixi's favour.
|
|
2312
|
-
|
|
2313
|
-
### Added
|
|
2314
|
-
- `assets.load(paths, { resolution })` (roadmap item 198): rasterizes a vector source (SVG)
|
|
2315
|
-
at a multiple of its intrinsic size instead of only at intrinsic size, so a game that zooms
|
|
2316
|
-
into an icon asks for `2` or `3` rather than shipping a soft bitmap. Passing `onProgress`
|
|
2317
|
-
alone still works. The colour-transform example loads its gem SVG at 2x.
|
|
2318
|
-
- `npm run benchmark:animation`: measures CSS/SVG element animation against Pixi sprites (and
|
|
2319
|
-
both at once) at increasing counts, sampling rAF intervals in headless Chrome. On an RTX
|
|
2320
|
-
3070, 4000 composer-animated SVG elements fell to ~14 fps while 4000 Pixi sprites held 60.
|
|
2321
|
-
- Accessibility (roadmap item 192): `core.reducedMotion`/`setReducedMotion`/
|
|
2322
|
-
`prefersReducedMotion` (the OS `prefers-reduced-motion` preference with a per-game override,
|
|
2323
|
-
consulted by `Tweener`, `Camera`, `ScreenEffects` and `ParticleEmitter`),
|
|
2324
|
-
`ui.contrastRatio`/`meetsContrast`/`relativeLuminance` for WCAG-checking a palette, and
|
|
2325
|
-
`ui.screenReader`, a hidden `aria-live` mirror that `Window` (its title) and `MessageBox`
|
|
2326
|
-
(each page and its choices) already announce through.
|
|
2327
|
-
- `npm run package:smoke` (roadmap item 193): packs the tarball, installs it into a scratch
|
|
2328
|
-
directory outside the repo, builds the tutorial's own tiny game and opens both that page and
|
|
2329
|
-
the standalone `mw_games.global.js` from `file://` in headless Chrome.
|
|
2330
|
-
- `npm run size:check` / `size:update` (194): the global bundle and `dist` against the
|
|
2331
|
-
committed `tools/bundle-size.json`, failing past a 2% growth.
|
|
2332
|
-
- `npm run coverage:check` (195): the existing suite under Node's line/branch/function floors.
|
|
2333
|
-
- Cross-version save fixtures (196): committed `tests/fixtures/saves/` blobs for a floor,
|
|
2334
|
-
a `GameState` and a `Blob`, loaded by `tests/save-compat.test.ts`.
|
|
2335
|
-
- `npm run examples:build` (197): runs every `example:*:build` script, so a vite or
|
|
2336
|
-
`emit-page` regression in any example is caught, not just the benchmarked ones.
|
|
2337
|
-
- `npm run coverage` and `npm run visual:smoke:ui`. Coverage reuses the existing Node test
|
|
2338
|
-
suite through `--experimental-test-coverage`, so measuring it costs no dependency. The
|
|
2339
|
-
visual smoke builds the interface example, opens it from `file://` in headless Chrome, and
|
|
2340
|
-
fails when the page errors or the canvas paints nothing, attaching the screenshot as a
|
|
2341
|
-
GitHub artifact; CI runs it on every pull request.
|
|
2342
|
-
- `core.Blob` gained a per-cell `clear(x, y)` (roadmap item 191): it zeroes one cell's
|
|
2343
|
-
volume and leaves its neighbours alone, so a game can douse a single tile, seal a breach,
|
|
2344
|
-
or put out one patch of fire without rebuilding the field.
|
|
2345
|
-
- `npm run api:report` / `npm run api:check`, backed by the new committed `API_REPORT.md`:
|
|
2346
|
-
a generated index of every public export and its declaration, so API renames, removals
|
|
2347
|
-
and signature changes are visible in review instead of discovered by consumers.
|
|
2348
|
-
`tests/api-surface.test.ts` emits declarations with `tsc --emitDeclarationOnly` and fails
|
|
2349
|
-
when the committed report drifts; CI also runs `api:check` after the build.
|
|
2350
|
-
- `tests/barrel-collisions.test.ts`: a guard that fails when two `export *` sources in the
|
|
2351
|
-
same barrel export the same name, which TypeScript would otherwise resolve by silently
|
|
2352
|
-
exporting neither.
|
|
2353
|
-
- `@datamoc/mw_games/two-d/pixi-interop` is now a real published subpath, matching the
|
|
2354
|
-
escape hatch ADR-001 already documented.
|
|
2355
|
-
|
|
2356
|
-
### Changed
|
|
2357
|
-
- CI now runs the coverage floor, the bundle-size budget, `examples:build` and the
|
|
2358
|
-
published-package smoke alongside its existing check/test/build/api gates, so neither
|
|
2359
|
-
coverage, bundle growth, an unbuildable example nor a broken packed install can land
|
|
2360
|
-
unnoticed.
|
|
2361
|
-
- Formatting is now gated: Prettier over `src`, `tests`, `examples` and `tools`
|
|
2362
|
-
(`.prettierrc.json`, `npm run format`/`format:check`, run in CI). No ESLint rule set comes
|
|
2363
|
-
with it, and the reformat changes no behaviour (line wrapping, trailing commas and the
|
|
2364
|
-
like); `barrel-collisions.test.ts` now tolerates Prettier wrapping a long
|
|
2365
|
-
`export { ... } from './...'` across lines.
|
|
2366
|
-
- ROADMAP.md: five verification gaps are recorded as the open backlog at the tail (193, a
|
|
2367
|
-
published-package `file://` smoke; 194, a bundle-size budget; 195, a coverage floor; 196,
|
|
2368
|
-
cross-version save fixtures; 197, building every example in CI), each with the concrete
|
|
2369
|
-
number or path it should assert against. The 1.0 checklist's API line widens from
|
|
2370
|
-
`DEPRECATED` alone to a full stability-marker contract (`@experimental` plus `DEPRECATED`).
|
|
2371
|
-
- ROADMAP.md: item 192 records the accessibility gaps the list had never named (screen-reader
|
|
2372
|
-
text for `ui` widgets, `prefers-reduced-motion`, palette contrast) as one open backlog item
|
|
2373
|
-
at the tail; the roadmap-progress test now guards that open items sit after every shipped
|
|
2374
|
-
one rather than forbidding them, so a recorded idea needs no test edit. The 1.0 exit
|
|
2375
|
-
checklist now decides the published `dist` map files explicitly instead of leaving them to
|
|
2376
|
-
drift.
|
|
2377
|
-
- **Breaking: `Blob` moved from `mwg/roguelike` to `mwg/core`.** A grid of volumes is not a
|
|
2378
|
-
dungeon-crawl concern, so the field now lives in the renderer-free `core` module (still
|
|
2379
|
-
reachable at the top level from `mw_games`) and imports nothing. Import it from
|
|
2380
|
-
`@datamoc/mw_games/core` instead of `@datamoc/mw_games/roguelike`. `spread`'s predicate
|
|
2381
|
-
parameter is now named `open` rather than `passable`; positional callers are unaffected.
|
|
2382
|
-
- Documentation page is now the `REFERENCE.md` module guide (with a sidebar TOC), and
|
|
2383
|
-
the TypeDoc symbol dump lives under `documentation/api/` instead of being the front
|
|
2384
|
-
door.
|
|
2385
|
-
- ROADMAP.md: the last open item (175, the `pixi.js` dependency-shape question) is closed
|
|
2386
|
-
by decision - `pixi.js` stays a direct dependency for the 0.x line and moves to an
|
|
2387
|
-
optional peer dependency with 1.0. The stale priority prose is replaced with a current
|
|
2388
|
-
statement, and the new "Parked decisions" and "1.0 exit checklist" sections record what
|
|
2389
|
-
actually remains before 1.0.
|
|
2390
|
-
- ADR-001's known gap is narrowed: `Sprite2D` closed the constructible-sprite half; the
|
|
2391
|
-
remaining value-level exception is the one documented pixi-interop file.
|
|
2392
|
-
|
|
2393
|
-
## [0.5.4] - 2026-09-10
|
|
2394
|
-
|
|
2395
|
-
Inline sound markers now travel with translated dialogue strings and fire at their visible
|
|
2396
|
-
position during `MessageBox` reveals. The reference docs, webpage features, and string-editor
|
|
2397
|
-
example now document and demonstrate `{sound:path}` markers.
|
|
2398
|
-
|
|
2399
|
-
## [0.5.3] - 2026-09-10
|
|
2400
|
-
|
|
2401
|
-
Closes ROADMAP items 184-190, the string stack requested directly across one session:
|
|
2402
|
-
translation editing (CLI and web), sound cues, f-string specs, markdown, and progressive
|
|
2403
|
-
display.
|
|
2404
|
-
|
|
2405
|
-
### Added
|
|
2406
|
-
- `examples/string-editor` (roadmap item 190) - the string editor as a playable page:
|
|
2407
|
-
an English reference beside an editable French translation, rendered live through
|
|
2408
|
-
`RichLabel` with an adjustable `{HP_loose}` variable, placeholder-drift warnings, and
|
|
2409
|
-
a blip/hit/pickup cue per string that fires on the progressive reveal. Listed on the
|
|
2410
|
-
website's examples page with its own generated diagram.
|
|
2411
|
-
- `i18n:edit` cue preview (roadmap item 189) - `Ctrl+P` plays the current row's sound
|
|
2412
|
-
cue through the OS player (`afplay`, `aplay`/`paplay`/`ffplay`, Windows WAV via
|
|
2413
|
-
SoundPlayer; `MWG_SFX_PLAYER` names a replacement), falling through only when the
|
|
2414
|
-
command itself is missing. Plain `p` stays unbound so previews never start by accident.
|
|
2415
|
-
- Shared progressive display (roadmap item 188) - `ui.startReveal`/`advanceReveal`/
|
|
2416
|
-
`completeReveal`/`revealComplete` behind `Label.showProgressive`/`updateReveal` and
|
|
2417
|
-
`RichLabel`'s markdown-aware counterpart (markers never count or leak, via
|
|
2418
|
-
`ui.sliceSpans`); `MessageBox` now runs on the same primitive with its
|
|
2419
|
-
confirm-completes-then-advances rule unchanged.
|
|
2420
|
-
- `i18n:edit` placeholder and markdown rendering (roadmap item 187) - panes preview
|
|
2421
|
-
markdown as terminal bold/italic (`v` toggles raw source), flag placeholder drift
|
|
2422
|
-
with a `≠` marker and per-row detail, hint the needed tokens in the edit prompt, and
|
|
2423
|
-
report both in `--check` mode. Backed by `i18n.tokenizeMessage`/`diffPlaceholders`,
|
|
2424
|
-
the same grammar `t()` interpolates with, so the check cannot disagree with runtime.
|
|
2425
|
-
- `ui.RichLabel`/`parseMarkdown`/`stripMarkdown` (roadmap item 186) - basic inline
|
|
2426
|
-
markdown for UI text (`**bold**`, `*italic*`, combined `***both***`, backslash
|
|
2427
|
-
escapes) through Pixi `HTMLText`. The parser is pure and unit-tested; unmatched
|
|
2428
|
-
markers stay literal. Heavier than `Label`, so meant for descriptions and help
|
|
2429
|
-
bodies, not per-frame numbers or typewriter reveal.
|
|
2430
|
-
- `i18n.formatSpec` (roadmap item 185) - Python f-string-style value formatting for
|
|
2431
|
-
catalog placeholders (`{dmg:03d}`, `{hp:.1%}`, `{name:>12}`), with `!s`/`!r`/`!a`
|
|
2432
|
-
conversions and `=` debugging, wired into `t()`/`tRaw` and FTL parsing. Verified case
|
|
2433
|
-
by case against CPython output; an ill-fitting spec leaves its placeholder untouched.
|
|
2434
|
-
The one divergence nothing can close: JavaScript numbers carry no int/float
|
|
2435
|
-
distinction, so integer-valued floats take the integer path.
|
|
2436
|
-
- `i18n` semantic `audio` channel (roadmap item 184) - `format(message, 'audio')`
|
|
2437
|
-
resolves `<type>.audio` to a sound path a game plays through `mwg/audio`'s `Sound`,
|
|
2438
|
-
one more presentation of the same simulation event. Resolves raw via the new `tRaw`
|
|
2439
|
-
(no typographic spacing, no RTL wrapping), returns `''` when no cue is declared, and
|
|
2440
|
-
never falls back to a bare type holding a sentence. `validateMessageAudio` flags empty
|
|
2441
|
-
and non-string audio entries.
|
|
2442
|
-
- `tools/i18n-edit.mjs` (roadmap item 184) - a split-screen terminal translation editor:
|
|
2443
|
-
reference language left, translation right, either side any language (`x` swaps them),
|
|
2444
|
-
per-string cue editing (`s`, one cue per semantic family), JSON/FTL auto-detection,
|
|
2445
|
-
and a `--check` mode for CI. Pure session logic lives in `i18n/EditSession.ts`.
|
|
2446
|
-
|
|
2447
|
-
## [0.5.2] - 2026-09-09
|
|
2448
|
-
|
|
2449
|
-
Closes ROADMAP items 178-182, five ideas raised against a reference game whose `main.ts` had
|
|
2450
|
-
grown to roughly 7,800 lines. 178 and 181 turned out to describe the same mechanism and were
|
|
2451
|
-
built as one primitive rather than two.
|
|
2452
|
-
|
|
2453
|
-
### Added
|
|
2454
|
-
- `core.Registry` (roadmap item 180) - a named lookup registered once and read back by name,
|
|
2455
|
-
the dispatch primitive underneath a catalog of factories or handlers, in place of a
|
|
2456
|
-
hand-written `if`/`switch` cascade. No auto-discovery: a game still imports and registers
|
|
2457
|
-
each entry itself.
|
|
2458
|
-
- `core.SceneComponentHost`/`SceneComponent` (roadmap items 178, 181) - composes a scene out
|
|
2459
|
-
of named sections (map logic, encounter logic, UI wiring), each its own module with
|
|
2460
|
-
whichever `Scene` lifecycle hooks it needs, instead of one scene class accreting every
|
|
2461
|
-
responsibility. Composition, not a base class, so it works whether a scene extends `Scene`
|
|
2462
|
-
or `two-d.Scene2D`; uses `core.Registry` internally for its by-name lookup.
|
|
2463
|
-
- `rpg.questsFromRows`/`QuestStageRow` (roadmap item 179) - groups a flat table of stage rows
|
|
2464
|
-
(typically a `core.parseCSV` result, one row per stage sharing a `questId`) into
|
|
2465
|
-
`QuestDefinition`s a `QuestLog` can `define`, the same relational shape `core.parseCSV`
|
|
2466
|
-
already models elsewhere, in place of a hand-written `.ts` object literal nesting each
|
|
2467
|
-
quest's stage array.
|
|
2468
|
-
- `actors.toEntitySaveState`/`fromEntitySaveState`/`EntitySaveState` (roadmap item 182) - a
|
|
2469
|
-
`BuiltEntity`'s mutable state (base stat values, level/experience, the carried item) in the
|
|
2470
|
-
same "definitions supplied fresh on load" shape `StatBlock`/`Progression` already draw;
|
|
2471
|
-
`fromEntitySaveState` rebuilds via `buildEntity` from the same row and catalog, then
|
|
2472
|
-
overlays the saved state on top.
|
|
2473
|
-
|
|
2474
|
-
## [0.5.1] - 2026-09-09
|
|
2475
|
-
|
|
2476
|
-
Closes ROADMAP item 148 (the last item open before this pass) and corrects an overstated
|
|
2477
|
-
renderer-boundary claim found while auditing the roadmap for anything still open.
|
|
2478
|
-
|
|
2479
|
-
### Added
|
|
2480
|
-
- `board.HexSkirmish` (roadmap item 148) - `startingSkirmish`/`setSkirmishTerrain`/
|
|
2481
|
-
`canPlaceSkirmishUnit`/`addSkirmishUnit`/`skirmishMoves`/`moveSkirmishUnit`/
|
|
2482
|
-
`skirmishAttack`/`skirmishIncome`/`endSkirmishTurn`, a Wesnoth-style hex army-game rules
|
|
2483
|
-
layer distinct from `board.Tactics`: per-terrain movement cost and defence, adjacency-only
|
|
2484
|
-
attacks where a surviving defender always strikes back, capturable villages that grant
|
|
2485
|
-
income and heal their owner's units, no zone of control.
|
|
2486
|
-
- `two-d/render.Sprite2D` - a bare, untinted, MWG-named re-export of Pixi's `Sprite`,
|
|
2487
|
-
alongside the existing `Node2D`/`Shape2D`/`Text2D`. Closes half the gap ADR-001 and
|
|
2488
|
-
ROADMAP item 167 had overstated as fully closed (see Fixed below); prefer
|
|
2489
|
-
`render.TintedSprite` the moment a colour transform is needed.
|
|
2490
|
-
- `core.parseCSV` (roadmap item 176) - a header-row CSV string into an array of typed row
|
|
2491
|
-
objects, so a table shaped like `actors.AffixTable` can be authored as a spreadsheet
|
|
2492
|
-
instead of a hand-written `.ts` object literal. `columns` coerces named fields to
|
|
2493
|
-
`'number'`/`'boolean'`/`'list'`/`'map'`; an empty cell omits that field entirely, the same
|
|
2494
|
-
as an optional property never set. Takes a raw string with no opinion on how it was
|
|
2495
|
-
loaded, the same boundary `i18n.parseFTL` already draws.
|
|
2496
|
-
- `actors.buildEntity`/`buildEntities` (roadmap item 177) - one hero/monster file row
|
|
2497
|
-
(typically a `core.parseCSV` result) into a fully wired entity: a `StatBlock` of base
|
|
2498
|
-
stats (every non-reserved column), an optional `Progression` against a named growth
|
|
2499
|
-
curve, a starting item carrying a named starting affix, and a `core.ReactionTable`
|
|
2500
|
-
already holding a low-HP rule if the row names a threshold. Every named reference
|
|
2501
|
-
resolves through a game-supplied `EntityTemplateCatalog` - `mwg` never invents what a
|
|
2502
|
-
name means, the same boundary `AffixDef.id` already draws.
|
|
2503
|
-
|
|
2504
|
-
### Fixed
|
|
2505
|
-
- `ADR.md`'s ADR-001 and ROADMAP item 167 claimed the renderer boundary was fully closed
|
|
2506
|
-
("nothing left... not a gap"). Corrected (ROADMAP item 173): every *type* position across
|
|
2507
|
-
the public API genuinely no longer names a `pixi.js` type, but `two-d/pixi-interop.ts` is
|
|
2508
|
-
itself a literal re-export from `pixi.js`, and `package.json`'s `dependencies` still lists
|
|
2509
|
-
`pixi.js` directly - a real, still-open gap at the value level, tracked as ROADMAP item
|
|
2510
|
-
175 rather than rushed through as a breaking dependency-shape change to an
|
|
2511
|
-
already-published version.
|
|
2512
|
-
|
|
2513
|
-
## [0.5.0] - 2026-09-09
|
|
2514
|
-
|
|
2515
|
-
A declarative reactions primitive, closing the "branch cascade of `if HP < n`" gap named
|
|
2516
|
-
directly, plus a new website page collecting the framework's original, non-obvious
|
|
2517
|
-
mechanisms for a game-developer audience.
|
|
2518
|
-
|
|
2519
|
-
### Added
|
|
2520
|
-
- `core.ReactionTable`/`ReactionRule` (roadmap item 172) - named `when`/`action` rules
|
|
2521
|
-
checked against any state shape (a `StatBlock`'s values, or a plain object's own fields
|
|
2522
|
-
such as an item's durability), firing `action` the moment `when` turns true and staying
|
|
2523
|
-
quiet while it remains true - edge-triggered the same way `roguelike.BossPhases` tracks
|
|
2524
|
-
entered phases. A `once` rule retires after firing; the default re-fires on the next
|
|
2525
|
-
rising edge. Lives in `core`, not `actors`, so the same table watches a character or an
|
|
2526
|
-
inanimate object without either module depending on the other.
|
|
2527
|
-
- `webpage/features/index.html` - ten specific, original mwg mechanisms (declarative
|
|
2528
|
-
reactions, the per-sprite multiply-and-add colour transform, `Barrier`'s outermost-first
|
|
2529
|
-
layered absorption, `Advancement`'s unified points/branch/capstone track, `Affix`'s
|
|
2530
|
-
trigger-routed curse-derived enchantments, `TriggerTracker`'s turn-window streaks, i18n's
|
|
2531
|
-
bidi-isolate/typographic rules, `StatStages`'s bounded ladder as one modifier, `Scramble`'s
|
|
2532
|
-
honestly-scoped obfuscation, and the deliberate `Scheduler`/`TurnClock` split), linked from
|
|
2533
|
-
every hand-authored page's nav.
|
|
2534
|
-
|
|
2535
|
-
## [0.4.3] - 2026-09-08
|
|
2536
|
-
|
|
2537
|
-
A simplification pass across storage, selection, and text options, one pathfinding
|
|
2538
|
-
allocation fix, a new opt-in build tool, and an interactive architecture diagram on the
|
|
2539
|
-
website.
|
|
2540
|
-
|
|
2541
|
-
### Added
|
|
2542
|
-
- `tools/compress-dist.mjs` (`@datamoc/mw_games/tools/compress-dist`) - writes precompressed
|
|
2543
|
-
`.gz`/`.br` siblings (optionally `.xz` via a system `xz` binary) next to a build's text
|
|
2544
|
-
files, for a server that can negotiate `Content-Encoding`; the originals are untouched, so
|
|
2545
|
-
a `file://` page keeps working unchanged. Wired into `tools/emit-page.mjs`'s example build
|
|
2546
|
-
step (`--no-compress`/`MWG_NO_COMPRESS=1` to skip, `--xz` to also archive).
|
|
2547
|
-
- `webpage/design/architecture-explorer.html` - an interactive, pannable/searchable diagram
|
|
2548
|
-
of `mwg`'s real module dependency graph (which modules reach `core`, which reach a
|
|
2549
|
-
renderer), generated from `src/`'s own import graph rather than hand-drawn, linked from
|
|
2550
|
-
the design page's "Module boundaries" section.
|
|
2551
|
-
|
|
2552
|
-
### Changed
|
|
2553
|
-
- `core.StoredValue` - the read-with-fallback/write/remove trio `PlayerStats`, `RunHistory`
|
|
2554
|
-
and `NewsSeenTracker` each hand-rolled slightly differently now share one implementation.
|
|
2555
|
-
- `core.NewsClient` is rebuilt on the shared `HttpTransport` every other injectable HTTPS
|
|
2556
|
-
client here already used, rather than its own hand-rolled timeout/abort handling.
|
|
2557
|
-
- `two-d/ui.SelectionModel` - the highlight/select/confirm/wrap-at-both-ends contract
|
|
2558
|
-
`ListView` and `IconGrid` had begun to implement slightly differently now lives in one
|
|
2559
|
-
place; each widget keeps only what actually differs (1-D rows vs. 2-D cells).
|
|
2560
|
-
- `two-d/ui`'s `Label`/`BitmapLabel` share their text-option shape and RTL-aware default
|
|
2561
|
-
alignment through a new internal `themedText` helper instead of two copies.
|
|
2562
|
-
- `rpg`'s `FreeMover`/`GridMover` share their "play this animation if the sprite has it"
|
|
2563
|
-
guard; `actors`'s `applyStatusEffect`/`applyItemStatusEffect` share their clock-lease/
|
|
2564
|
-
cancel logic. Both were identical code living in two places.
|
|
2565
|
-
- `vite.lib.config.ts` and the examples' shared Vite config turn off `reportCompressedSize`:
|
|
2566
|
-
the estimate cost a full in-memory gzip of the bundle for a number `tools/compress-dist.mjs`
|
|
2567
|
-
reports for real now.
|
|
2568
|
-
- `roguelike.Level` gained `forEachNeighbor` (visits a cell's neighbours via callback instead
|
|
2569
|
-
of allocating an array), used by `Pathfinder`'s flood fills and `Placement.cellsNear` - the
|
|
2570
|
-
hottest per-cell allocation in map generation, now gone.
|
|
2571
|
-
|
|
2572
|
-
## [0.4.2] - 2026-09-08
|
|
2573
|
-
|
|
2574
|
-
A roadmap-management pass alongside three real capability gaps closed: deterministic dungeon
|
|
2575
|
-
content placement, i18n catalog content tooling, and 2D/3D asset loading unified where it
|
|
2576
|
-
correctly can be.
|
|
2577
|
-
|
|
2578
|
-
### Added
|
|
2579
|
-
- `tools/roadmap-progress.mjs`/`roadmapProgress.js` gained an item-management panel: search,
|
|
2580
|
-
"only open items", and local (never committed to `ROADMAP.md`) priority/status/assignee
|
|
2581
|
-
triage per item, with export/import.
|
|
2582
|
-
- `roguelike.candidateCells`/`cellsNear`/`selectDistinctCells` - deterministic content
|
|
2583
|
-
placement over a `Level`: terrain/occupancy/region filters, radius-based clustering, and
|
|
2584
|
-
bounded distinct-cell selection with a JSON-safe roll trace, composing for neighbouring
|
|
2585
|
-
items, scattered decorations, and single room/branch rewards.
|
|
2586
|
-
- `i18n.messageText`/`levenshteinDistance`/`findSimilarMessages` - near-duplicate catalog
|
|
2587
|
-
message detection by edit distance.
|
|
2588
|
-
- `i18n.catalogUsage`/`catalogCompleteness`/`pluralFormCoverage` - catalog statistics: used
|
|
2589
|
-
vs. unused keys against a caller-supplied reference list, translated-fraction completion,
|
|
2590
|
-
and CLDR plural-category coverage.
|
|
2591
|
-
- `i18n.mergeCatalogKeys` - drops a merged key from a catalog, keeping the surviving key's
|
|
2592
|
-
text; rewriting call sites stays the caller's own job.
|
|
2593
|
-
- `assets.loadBinary`/`getBinary`/`isBinaryLoaded`/`releaseBinary` (also its own
|
|
2594
|
-
`@datamoc/mw_games/assets/binary` entry point) - a renderer-free raw-byte cache, the
|
|
2595
|
-
direct fix for `three-d`'s `Vox.parseVox` needing a game to fetch bytes itself.
|
|
2596
|
-
- `3d/models`' `loadModelContainer3D`/`isModelContainerLoaded`/`releaseModelContainer` -
|
|
2597
|
-
loads a glTF/GLB source once, caching the Babylon `AssetContainer`; a game calls the
|
|
2598
|
-
container's own `instantiateModelsToScene()` for each independent, unaliased copy it
|
|
2599
|
-
wants placed, rather than importing (and re-fetching) the same model every time.
|
|
2600
|
-
|
|
2601
|
-
### Fixed
|
|
2602
|
-
- `two-d/ui`'s right-to-left mirroring was incomplete: `Bar`'s fill always grew from the
|
|
2603
|
-
left, `IconGrid` always laid its columns left-to-right and never swapped what the
|
|
2604
|
-
`'left'`/`'right'` actions meant, and `HelpScreen` always put its topic list on the left.
|
|
2605
|
-
All three now mirror under `theme().direction === 'rtl'`, matching `Window`/`ListView`/
|
|
2606
|
-
`Button`/`Label`, which already did.
|
|
2607
|
-
- `ROADMAP.md` had two items both numbered 161, a genuine duplicate; the misplaced one was
|
|
2608
|
-
renumbered and moved to the true end of the list before being implemented.
|
|
2609
|
-
- `tools/build-webpage-docs.mjs`'s nested `npm install` could fail when the caller's own
|
|
2610
|
-
global `~/.npmrc` set an `allow-scripts` value npm rejects for a project-scoped install;
|
|
2611
|
-
that env var is now explicitly cleared for the nested call.
|
|
2612
|
-
|
|
2613
|
-
## [0.4.1] - 2026-09-07
|
|
2614
|
-
|
|
2615
|
-
A study of `mwg-pixel-dungeon` (a reference game, not in this repo) recommended closing the
|
|
2616
|
-
PixiJS boundary the rest of the way, a formal simulation runtime, stable entity identity, and
|
|
2617
|
-
semantic messaging as framework primitives. All of it landed this release, plus the eight
|
|
2618
|
-
architecture decisions it proposed, recorded in the new `ADR.md`.
|
|
2619
|
-
|
|
2620
|
-
### Added
|
|
2621
|
-
- `core.EntityRegistry`/`EntityId` - assigns and looks up stable string ids for live objects,
|
|
2622
|
-
so events, saves, AI targets and buffs can name a creature or item without holding it.
|
|
2623
|
-
`idOf` is what a game passes as `Scheduler.toJSON`'s or `SimulationRuntime.snapshot`'s
|
|
2624
|
-
`actorId`.
|
|
2625
|
-
- `core.PresentationQueue` - plays a batch of simulation events one at a time, each waiting on
|
|
2626
|
-
its own `play()`-returned duration, freed of any renderer - the presentation-side
|
|
2627
|
-
counterpart to a `SimulationRuntime.dispatch()`/`runScenario()` result.
|
|
2628
|
-
- `simulation.SimulationRuntime`/`SimulationContext`/`SimulationOutcome`/
|
|
2629
|
-
`SimulationRuntimeRule`/`SimulationSnapshot` - a facade over one state + one
|
|
2630
|
-
`roguelike.Scheduler` + one `core.Generator` for the interactive half of a turn-based
|
|
2631
|
-
simulation: `dispatch` runs a single command, threading `random`/`scheduler` as context and
|
|
2632
|
-
charging any returned cost; `snapshot`/`restore` capture and rebuild the whole triple.
|
|
2633
|
-
Composes with the existing `advanceToInput`/`runScenario` rather than replacing them.
|
|
2634
|
-
`simulation` also re-exports `Scheduler`/`Actor`/`SchedulerSnapshot` from `roguelike`.
|
|
2635
|
-
- `roguelike.Scheduler` gained `postpone` (delaying an actor other than the current one) and
|
|
2636
|
-
`toJSON`/`restore` (a deterministic snapshot keyed by a caller-supplied actor id), making it
|
|
2637
|
-
the sole, serialisable authority on logical time.
|
|
2638
|
-
- `i18n.SemanticMessage`/`MessageChannel`/`MessageFormatter`/`createCatalogFormatter` - a
|
|
2639
|
-
typed `{ type, params }` communication intent rendered differently per channel (log/
|
|
2640
|
-
compact/accessibility/debug) from the same catalog, built on the existing `t()`/plural/
|
|
2641
|
-
Fluent machinery rather than a parallel implementation.
|
|
2642
|
-
- `i18n.formatNumber`/`formatDate`/`formatList` - locale-aware `Intl` formatting for a message
|
|
2643
|
-
that needs more than `{token}` substitution.
|
|
2644
|
-
- `i18n.diffCatalogKeys`/`validateCatalog` - catalog consistency checks: two catalogs' key
|
|
2645
|
-
sets compared, and one catalog's own empty messages/incomplete plural forms flagged.
|
|
2646
|
-
- `two-d.render.Container2D`/`Texture2D`/`Rect`/`TextureRegion`/`rectOf` - plain,
|
|
2647
|
-
renderer-free public types in place of `pixi.js`'s own `Container`/`Texture`/`Rectangle`;
|
|
2648
|
-
`Scene2D.stage` is now typed `Container2D`, `SpriteSheet.region` returns a `TextureRegion`.
|
|
2649
|
-
- `two-d.render.Node2D`/`Shape2D`/`Text2D`/`TiledSprite`/`Gradient` - bare, MWG-named
|
|
2650
|
-
re-exports of Pixi's `Container`/`Graphics`/`Text`/`TilingSprite`/`FillGradient`, so a game
|
|
2651
|
-
never has to name `pixi.js` for a plain layer, vector drawing, one-off text, a scrolling
|
|
2652
|
-
tile, or a gradient fill.
|
|
2653
|
-
- `two-d.pixi-interop` - the one sanctioned, explicit escape hatch for the rare Pixi-specific
|
|
2654
|
-
need the facade above does not cover.
|
|
2655
|
-
- `TintedSprite` (and everything built on it - `AnimatedSprite`, `TileMap`, `DialogueStage`)
|
|
2656
|
-
now registers its own colour-transform Pixi pipe automatically on import; a game no longer
|
|
2657
|
-
passes `{ extensions: [registerColorTransform] }` to `Game`.
|
|
2658
|
-
- `ADR.md` - the eight architecture decisions from the `mwg-pixel-dungeon` study, each
|
|
2659
|
-
recorded against the code and tests that enforce it.
|
|
2660
|
-
|
|
2661
|
-
### Fixed
|
|
2662
|
-
- `ButtonSkin.texture`, `ButtonOptions.icon`, `IconGridItem.icon`, `ListItem.icon`, and
|
|
2663
|
-
`Theme.panel` were still typed as raw `pixi.js` `Texture`/`Container` in public interfaces;
|
|
2664
|
-
all retyped to `Texture2D`/`Container2D` (the same underlying type, not a breaking change).
|
|
2665
|
-
|
|
2666
|
-
## [0.4.0] - 2026-09-06
|
|
2667
|
-
|
|
2668
|
-
**The reshaping release, and intended to be the last one.**
|
|
2669
|
-
|
|
2670
|
-
`mwg` grew fast, and grew by accretion: the renderer ended up inside `mwg/core`, an event
|
|
2671
|
-
interpreter ended up importing a widget library, the same idea got solved three or four
|
|
2672
|
-
different ways in different modules, and several names meant a different thing depending on
|
|
2673
|
-
which file you were reading. None of that was going to get cheaper to fix. A rename costs a
|
|
2674
|
-
line in this file today; after 1.0 it costs somebody else's build.
|
|
2675
|
-
|
|
2676
|
-
So this release spends the breakage budget deliberately, all at once, while the version
|
|
2677
|
-
number still says it is allowed:
|
|
2678
|
-
|
|
2679
|
-
- **The renderer is no longer part of the core.** `mwg/core` now holds the scene lifecycle,
|
|
2680
|
-
input, saves, RNG and signals, and pulls in no renderer at all. `Game` and the display half
|
|
2681
|
-
of `Scene` moved to the new `mwg/two-d`, which is where `render`, `ui` and `stage` now live
|
|
2682
|
-
as well. `mwg/3d` is its Babylon counterpart, and neither costs a game anything if it is
|
|
2683
|
-
not used.
|
|
2684
|
-
- **Game logic is renderer-free too.** `mwg/rpg` was the last module reaching a renderer by
|
|
2685
|
-
accident; its event interpreter now takes an injected dialogue presenter. So dungeon
|
|
2686
|
-
generation, map events, quests, stats, turn order, inventory and battles all run under a 2D
|
|
2687
|
-
game, a 3D game, or a headless test, unchanged. `tests/renderer-isolation.test.ts` walks the
|
|
2688
|
-
real import graph and enforces exactly which modules may reach PixiJS or Babylon.
|
|
2689
|
-
- **One idea, one spelling.** `advance(turns)` is turns and `update(dt)` is real seconds.
|
|
2690
|
-
`toJSON`/`fromJSON` is how a class saves. "Nothing to pick" is `null`, not `-1` or
|
|
2691
|
-
`undefined`. Two identical hook registries became one.
|
|
2692
|
-
- **The character sheet can be saved.** `Inventory`, `StatBlock`, `EquipmentSlots`,
|
|
2693
|
-
`Progression`, `SkillPoints` and `Charges` gained serialization, so a game stops hand-rolling
|
|
2694
|
-
the most important half of its own save file.
|
|
2695
|
-
|
|
2696
|
-
The hope, stated plainly: **1.0 should be this shape.** What remains before it is coverage and
|
|
2697
|
-
confidence, not another reshuffle. Additions rather than renames from here.
|
|
2698
|
-
|
|
2699
|
-
### Added
|
|
2700
|
-
- `two-d.ParticleEmitter` - a pooled, seeded particle emitter (sparks, dust, rain). The pool
|
|
2701
|
-
is allocated once at `max` and never grows, and every draw goes through `core.Random`, so a
|
|
2702
|
-
replayed run reproduces the same spray. Given no `texture` it runs the simulation and draws
|
|
2703
|
-
nothing, which is how it is tested without a DOM.
|
|
2704
|
-
- `two-d.ScreenEffects` - a full-screen colour wash: `fadeOut`/`fadeIn`/`flash`/`setTint`,
|
|
2705
|
-
driven by `update(dt)` returning true on the frame an effect completes.
|
|
2706
|
-
- `two-d.Tooltip` - a hover explanation over a themed `Window`, with a frame-driven delay and
|
|
2707
|
-
edge-aware placement that flips rather than running off screen.
|
|
2708
|
-
- `roguelike.RoomBuilder`/`hallBuilder`/`eligibleBuilders`/`pickBuilder`, and
|
|
2709
|
-
`DungeonOptions.builders` - composable room interiors: the generator places and joins rooms,
|
|
2710
|
-
a builder carves each one. A room no builder fits falls back to a plain hall.
|
|
2711
|
-
- `roguelike.generateDungeonGraph` - the same pipeline as `generateDungeon`, also returning the
|
|
2712
|
-
room graph, a rejected-placement retry count, and which builder carved each room.
|
|
2713
|
-
`DungeonOptions.hooks` fires `onRoomPlaced`/`onCorridorCarved` as the pipeline runs.
|
|
2714
|
-
- `roguelike.FeatureLayer` - a floor feature/event layer: named kinds with
|
|
2715
|
-
`inspect`/`interact`/`consequence`/`persistent` rules attached to generated cells.
|
|
2716
|
-
- `roguelike.rollRoster` - a variant-spawn/content-roll API: rare additions, per-entry
|
|
2717
|
-
alternative swaps, then a shuffle, with every roll traced (including an explicitly deferred
|
|
2718
|
-
one) for parity tests.
|
|
2719
|
-
- `roguelike.compareDungeonArtifacts`/`checkDeterminism` - a dungeon parity harness that tags
|
|
2720
|
-
every mismatch `'graph'` or `'paint'`.
|
|
2721
|
-
- **Save/load for the character sheet.** `Inventory`, `StatBlock`, `EquipmentSlots`,
|
|
2722
|
-
`Progression`, `SkillPoints` and `Charges` all gain `toJSON`/`fromJSON`. `Inventory` saves
|
|
2723
|
-
per-item instance state (level, wear, affix, `instanceId`) while taking kind-level fields
|
|
2724
|
-
from the game's own item table on load, so rebalancing reaches old saves. `StatBlock` saves
|
|
2725
|
-
base values and deliberately no modifiers, since whatever applied them reapplies them.
|
|
2726
|
-
`Charges` saves banked regeneration progress, so reloading cannot shorten a recharge.
|
|
2727
|
-
- `core.HookRegistry` - the named-event registry `battle.BattleHooks` and
|
|
2728
|
-
`roguelike.CombatHooks` are now both built on.
|
|
2729
|
-
- `two-d/ui.messageBoxPresenter` - wires `rpg.EventRunner`'s dialogue to a `MessageBox` in one
|
|
2730
|
-
argument.
|
|
2731
|
-
- `rpg.MovableSprite`, `rpg.AutomapTarget`, `rpg.DialoguePresenter` - the structural shapes
|
|
2732
|
-
that replaced concrete renderer types in `mwg/rpg`'s signatures.
|
|
2733
|
-
- `core.Input` gains touch input: `touchCode`/`bindTouch`/`pressTouch`/`releaseTouch` follow
|
|
2734
|
-
the same synthetic-code pattern `bindButton`/`pollGamepads` already use for a gamepad, so
|
|
2735
|
-
`isDown`/`justPressed`/`justReleased` work unmodified for a touch-driven action. `attachSwipe`
|
|
2736
|
-
resolves a one-finger drag into one of 8 directional action pulses by angle, or a `tap`
|
|
2737
|
-
action for a short drag. `core.PlayerInput` gains matching `bindTouch`/`pressTouch`/
|
|
2738
|
-
`releaseTouch` wrappers.
|
|
2739
|
-
- `ui.Button` gains `onPress`/`onRelease` signals (pointerdown, and pointerup/pointerupoutside),
|
|
2740
|
-
the hook a virtual on-screen d-pad button needs to feed `pressTouch`/`releaseTouch` for
|
|
2741
|
-
hold-to-repeat movement, independent of `onClick`.
|
|
2742
|
-
- `mwg/3d` gains `Collision3D.ts` (`buildHeightIndex`, `cellAt`, `heightAt`,
|
|
2743
|
-
`resolveCapsuleAgainstGrid`): horizontal collision against `createTileGrid3D`'s stepped
|
|
2744
|
-
grid, stopping a moving capsule/AABB at a raised column's edge instead of clipping through
|
|
2745
|
-
it. `Character3D` takes an optional third constructor argument, `collideXZ`, to plug this
|
|
2746
|
-
in; omitted, movement behaves exactly as before.
|
|
2747
|
-
- `assets.fetchWithByteProgress` reports real cumulative bytes transferred (and the known
|
|
2748
|
-
total, from `Content-Length`) for a real origin - a dev server, or a desktop host serving
|
|
2749
|
-
through a virtual origin rather than `file://`. `desktop/MwgDesktopHost` now serves the
|
|
2750
|
-
built game through `CoreWebView2.SetVirtualHostNameToFolderMapping` (a real `https://`
|
|
2751
|
-
origin) instead of a plain `file://` navigation, which is what makes this - and any other
|
|
2752
|
-
real network call - actually usable inside it.
|
|
2753
|
-
|
|
2754
|
-
### Changed
|
|
2755
|
-
|
|
2756
|
-
- **Breaking: `mwg/render`, `mwg/ui` and `mwg/stage` moved under `mwg/two-d`.** The Pixi half
|
|
2757
|
-
of the framework is now one module, symmetric with `mwg/3d`. Import from
|
|
2758
|
-
`@datamoc/mw_games/two-d` (or the granular `two-d/render`, `two-d/ui`, `two-d/stage`). No
|
|
2759
|
-
legacy aliases were kept.
|
|
2760
|
-
- **Breaking: `Game` moved from `mwg/core` to `mwg/two-d`, and `Scene` split.** `core.Scene` is
|
|
2761
|
-
now the renderer-free lifecycle (`create`/`update`/`resize`/`onSuspend`/`onResume`/`destroy`);
|
|
2762
|
-
`two-d.Scene2D` adds the Pixi container and is what a 2D game extends. `SceneStack` is generic
|
|
2763
|
-
over the scene type, so a Babylon game gets scene management, suspend/resume and minigame
|
|
2764
|
-
stacking. **`mwg/core` now pulls in no renderer at all**, and neither does `mwg/rpg`.
|
|
2765
|
-
- **Breaking: `rpg.EventRunner` takes `present: DialoguePresenter` instead of `windows`.** The
|
|
2766
|
-
event interpreter no longer builds a `MessageBox`; use
|
|
2767
|
-
`present: messageBoxPresenter(this.windows)` for the previous behaviour. `boxWidth`,
|
|
2768
|
-
`boxHeight` and `speed` moved onto the presenter.
|
|
2769
|
-
- **Breaking: `loadTiledMap` moved from `mwg/rpg` to `mwg/two-d/render`**, where the `TileMap`
|
|
2770
|
-
and `SpriteSheet` it builds already lived.
|
|
2771
|
-
- **Breaking: every "pick one" now returns `null`.** `Random.weighted` returned `-1` and
|
|
2772
|
-
`Random.element`/`Random.weightedKey` returned `undefined`; all three now match
|
|
2773
|
-
`rollEncounter`/`rollLoot`.
|
|
2774
|
-
- **Breaking: one meaning per name.** `advance(turns)` is turns or rounds and `update(dt)` is
|
|
2775
|
-
real seconds, so `EnvironmentClock.advance(seconds)` became `update(dt)`,
|
|
2776
|
-
`Barrier.decay(ticks)` and `AbilityCycle.tick()` became `advance(turns)`,
|
|
2777
|
-
`BossPhases.update(hpFraction)` became `check(hpFraction)`, and `QuestLog.advance` became
|
|
2778
|
-
`advanceStage`. `EnvironmentClock.snapshot`/`restore` and `SupportLedger.save`/`restore`
|
|
2779
|
-
became `toJSON`/`fromJSON`.
|
|
2780
|
-
- **Breaking: `GridMover`/`FreeMover` take a `MovableSprite`** rather than an `AnimatedSprite`,
|
|
2781
|
-
so a static sprite (or anything with `x`/`y`) works; the animation members are optional.
|
|
2782
|
-
- `mwg/assets` split into renderer-free path resolution (`assets/paths`, its own export
|
|
2783
|
-
subpath) and the Pixi-backed loader, which is what took Pixi out of `mwg/3d` and `mwg/audio`.
|
|
2784
|
-
- Per-module export subpaths now ship TypeScript types; previously only the package root did,
|
|
2785
|
-
so `@datamoc/mw_games/core` resolved to `any` under `moduleResolution: bundler`/`node16`.
|
|
2786
|
-
- `sideEffects` narrowed from a blanket `false` to the two `mwg/3d` files with real
|
|
2787
|
-
side-effect imports, so a bundler can no longer drop Babylon's glTF and thin-instance
|
|
2788
|
-
registrations.
|
|
2789
|
-
|
|
2790
|
-
### Fixed
|
|
2791
|
-
- `examples/three-d`'s hero now actually collides with the raised ridge its demo path crosses,
|
|
2792
|
-
rather than the path being hand-routed around it.
|
|
2793
|
-
|
|
2794
|
-
## [0.3.1] - 2026-09-05
|
|
2795
|
-
|
|
2796
|
-
### Added
|
|
2797
|
-
- `audio.Music.playTracks(paths, fadeDuration)` plays a playlist rather than one looping
|
|
2798
|
-
track: each track plays once, `HTMLAudioElement.onended` (when the backend exposes it)
|
|
2799
|
-
advances to the next, and the sequence cycles once it reaches the end. `play()`/`stop()`
|
|
2800
|
-
cancel an active playlist so a stale `onended` from a track already replaced cannot advance
|
|
2801
|
-
a newer one.
|
|
2802
|
-
|
|
2803
|
-
## [0.3.0] - 2026-09-05
|
|
2804
|
-
|
|
2805
|
-
### Added
|
|
2806
|
-
- `core.PlayerStats` (a lifetime total, folded per run - deliberately not derived from
|
|
2807
|
-
`RunHistory`, which can drop old entries), `ui.StatsScreen` (a `label: value` display
|
|
2808
|
-
recipe), and `core.TelemetryClient` (automatic structured events, off by default until a
|
|
2809
|
-
game calls `setConsent(true)`).
|
|
2810
|
-
- `tools/benchmark-browser.mjs` now records each run's fps/p95/memory to a per-page history
|
|
2811
|
-
file (`benchmark-results/`, gitignored) and fails on a regression against the best-seen
|
|
2812
|
-
prior run, not only its fixed gate. `npm run benchmark:tower-defense`/`benchmark:ui` cover
|
|
2813
|
-
those examples the same way `benchmark:browser`/`benchmark:3d` already did.
|
|
2814
|
-
`tools/benchmark-simulation.mjs` (`npm run benchmark:simulation`) measures headless
|
|
2815
|
-
`runScenario`/`advanceToInput` throughput, with the same history tracking.
|
|
2816
|
-
- `core.LockstepClient` and a reference server, `tools/multiplayer-server.mjs` (real-time
|
|
2817
|
-
multiplayer's one exception to "`mwg` ships no backend"): lockstep tick authority over a
|
|
2818
|
-
plain `WebSocket`, server-assigned identity, and a `?room=` matchmaking string. Run it with
|
|
2819
|
-
`npm run multiplayer:server`.
|
|
2820
|
-
- `core.SaveSyncClient.list()` returns every save-profile slot name an endpoint holds, so a
|
|
2821
|
-
player's multiple named profiles (`SaveSystem` already supports as many as a game creates)
|
|
2822
|
-
can each sync independently against one endpoint.
|
|
2823
|
-
- `desktop/MwgDesktopHost`, a minimal WebView2 (WinForms, net8.0-windows) reference host that
|
|
2824
|
-
loads a built example's own `index.html` via `file://` unmodified. `npm run desktop:build`/
|
|
2825
|
-
`desktop:run` mirror the existing `cap:*` scripts' naming and target the same `tower-defense`
|
|
2826
|
-
reference build. Verified with a real `dotnet build`/`dotnet run` and a screenshot of the
|
|
2827
|
-
running window showing the game actually rendered.
|
|
2828
|
-
- `assets.load` and `assets.AssetStream`'s `preload`/`preloadLikely` take an optional
|
|
2829
|
-
`onProgress` (asset-count fraction, not literal bytes), threaded through `examples/loading`'s
|
|
2830
|
-
own tasks into `LoadQueue.report`. Eviction under a tight budget was verified in a real
|
|
2831
|
-
browser across 300 preload/evict cycles: resident texture count stayed pinned to the budget
|
|
2832
|
-
throughout.
|
|
2833
|
-
- `render.StatusVisuals` maps active status-effect names to a tint on a sprite (priority by
|
|
2834
|
-
declaration order, an optional pulsing strength), bridging `actors.applyStatusEffect`'s
|
|
2835
|
-
game-side data to what a character looks like without either module importing the other.
|
|
2836
|
-
- `mwg/simulation` (`Simulation` on the standalone build): `advanceToInput` runs a
|
|
2837
|
-
scheduler's automatic actions up to a budget until an actor needs input, and
|
|
2838
|
-
`runScenario` applies a finite command sequence against caller-supplied rules. Both
|
|
2839
|
-
are headless, with no rendering or browser imports, and take random state explicitly
|
|
2840
|
-
for reproducibility.
|
|
2841
|
-
- Button accepts a per-instance nine-patch skin with state tints and caption styling, including captions created later with setText.
|
|
2842
|
-
- Label accepts stroke, resolution and roundPixels options. Existing defaults are unchanged. Textures remain owned by the caller.
|
|
2843
|
-
|
|
2844
|
-
### Changed
|
|
2845
|
-
- **Breaking:** `core.SaveSyncClient.upload`/`download` now take a `slot` name -
|
|
2846
|
-
`upload(payload)`/`download()` are `upload(slot, payload)`/`download(slot)` - so one
|
|
2847
|
-
endpoint can hold more than one player profile.
|
|
2848
|
-
|
|
2849
|
-
|
|
2850
|
-
## [0.2.1] - 2026-09-05
|
|
2851
|
-
|
|
2852
|
-
### Fixed
|
|
2853
|
-
- `Sound.play()`, `Music.play()` and `Synth.playTone()` discarded the `Promise` that
|
|
2854
|
-
`HTMLAudioElement.play()` returns with no rejection handler. Reusing a pooled `Sound`
|
|
2855
|
-
instance before its prior `play()` settled, or `Music`'s crossfade pausing the previous
|
|
2856
|
-
track while the incoming one was still loading, rejects that promise ("The fetching
|
|
2857
|
-
process for the media resource was aborted..."), which surfaced as an unhandled
|
|
2858
|
-
rejection instead of being silently absorbed, the correct handling for an interruption
|
|
2859
|
-
that is expected, not an error.
|
|
2860
|
-
- `Camera.update()` computed its deadzone size through the `view` getter, which also
|
|
2861
|
-
clamps to bounds and allocates a rectangle object - two needless allocations every
|
|
2862
|
-
frame for values the deadzone calculation never used.
|
|
2863
|
-
|
|
2864
|
-
## [0.2.0] - 2026-09-05
|
|
2865
|
-
|
|
2866
|
-
### Added
|
|
2867
|
-
|
|
2868
|
-
**Core**
|
|
2869
|
-
- `Tweener`/`Easing`, `UndoHistory`, `PlayerInput` (rebindable action-to-key mapping),
|
|
2870
|
-
`RunHistory` (per-run reports and rankings, no online component), `News` (`NewsClient`,
|
|
2871
|
-
`NewsSeenTracker`), `Sanitize` (`checkSize`, `checkNoControlCharacters`,
|
|
2872
|
-
`sanitizeInboundText`, `validateSchema` - a 10MB default size cap and no embedded control
|
|
2873
|
-
characters on any inbound save/news/sync data), `Scramble`, `SaveSync` (`SaveSyncClient`),
|
|
2874
|
-
`Save.exportSlot`/`importSlot`, `Loading` (`LoadQueue`), `Feedback` (`FeedbackClient`),
|
|
2875
|
-
`Input.onWheel` (wheel scroll as a first-class input signal alongside keys, not just a
|
|
2876
|
-
`ListView` feature - horizontal-scroll and zoom modifier keys resolve to a
|
|
2877
|
-
`WheelAction`/`WheelInput` the game interprets, distinct from the browser's own scroll/zoom).
|
|
2878
|
-
- `version`: `mwg`'s own version string, exported from `mwg/core` and kept in sync with
|
|
2879
|
-
`package.json` by a dedicated test.
|
|
2880
|
-
|
|
2881
|
-
**Render**
|
|
2882
|
-
- `Viewport`/`splitScreenHalves` (local split-screen multiplayer), `Camera.setViewport`
|
|
2883
|
-
screen offset, `ColorBlindness` (`createColorBlindnessFilter`, accessible colour modes),
|
|
2884
|
-
`Capabilities.inspectGraphicsCapabilities`/`detectWebGpu` (real WebGPU shader-compile
|
|
2885
|
-
probe, not just a `navigator.gpu` existence check), `Streaming.AssetStream`.
|
|
2886
|
-
|
|
2887
|
-
**UI**
|
|
2888
|
-
- `BitmapLabel`, `Toast`, `theme.highContrastTheme`, `LoadingScreen`, pointer and wheel
|
|
2889
|
-
support on `ListView`/`IconGrid`, `Bar` fill/background textures with pixel rounding.
|
|
2890
|
-
|
|
2891
|
-
**Audio**
|
|
2892
|
-
- `Synth` (`synthesizeTone`, `playTone`), `Midi` (`parseMidi`, `scheduleMidi`,
|
|
2893
|
-
`MidiPlayer`, `noteToFrequency`), `Captions` (`onCaption` - subtitles for accessibility).
|
|
2894
|
-
|
|
2895
|
-
**Actors / World / Board / RPG**
|
|
2896
|
-
- `Support` (`SupportLedger`), `ItemStatusEffect.applyItemStatusEffect` (temporary item
|
|
2897
|
-
status), `Environment` (`EnvironmentClock`), `FogOfWar.FactionFog`, `Collision`
|
|
2898
|
-
(`aabbOverlap`, `circleOverlap`, `circleAabbOverlap`, `resolveAabbAgainstTiles`).
|
|
2899
|
-
|
|
2900
|
-
**i18n / Stage**
|
|
2901
|
-
- `Fluent.parseFTL`, typographic apostrophes, `StageScript.history`/`showLast`/`skipSeen`,
|
|
2902
|
-
`MessageBox` `nvl` mode and `autoAdvance`.
|
|
2903
|
-
|
|
2904
|
-
**3D, mobile and desktop**
|
|
2905
|
-
- `Character3D.playAnimation`/`stopAnimation`/`currentAnimation`,
|
|
2906
|
-
`Heightmap.createHeightmapTerrain3D`, an Ionic Capacitor integration for native
|
|
2907
|
-
iOS/Android packaging, and a WebView2 desktop host reference under `desktop/`.
|
|
2908
|
-
|
|
2909
|
-
**Examples**
|
|
2910
|
-
- `examples/loading` (`LoadQueue`/`LoadingScreen`/`AssetStream` end to end, including a
|
|
2911
|
-
deliberately-failing-once task exercising retry), `examples/three-d`,
|
|
2912
|
-
`examples/tower-defense`.
|
|
2913
|
-
|
|
2914
|
-
### Changed
|
|
2915
|
-
- `graphics-capabilities`'s `wgsl` capability now defaults to `false` unless a real
|
|
2916
|
-
WebGPU shader-compile probe supplies it, instead of asserting true from
|
|
2917
|
-
`navigator.gpu`'s mere existence.
|
|
2918
|
-
- `tools/find-chrome.mjs` extracted from the byte-identical `findChrome()` duplicated in
|
|
2919
|
-
`benchmark-browser.mjs` and `graphics-capabilities.mjs`.
|
|
2920
|
-
|
|
2921
|
-
## [0.1.2] - 2026-09-03
|
|
2922
|
-
|
|
2923
|
-
### Added
|
|
2924
|
-
- `Session`: counts how many times a game has launched, persisted across page loads (the
|
|
2925
|
-
same `SaveStorage` abstraction `SaveSystem` uses) - the signal a native wrapper needs to
|
|
2926
|
-
decide whether to ask for a store rating. `mwg` counts; it never prompts, and bundles no
|
|
2927
|
-
store/ads/IAP SDK of any kind.
|
|
2928
|
-
|
|
2929
|
-
### Changed
|
|
2930
|
-
- **Breaking:** `Game` no longer registers `mwg/render`'s colour-transform batcher
|
|
2931
|
-
automatically. `mwg/core` imported from `mwg/render` to do this, meaning a game that
|
|
2932
|
-
only imported `mwg/core` still compiled in the whole render module. `GameOptions` gained
|
|
2933
|
-
`extensions`, a list of Pixi-extension registration functions the caller supplies
|
|
2934
|
-
instead: a game using `TintedSprite` (directly, or via `TileMap`/`DialogueStage`/
|
|
2935
|
-
`AnimatedSprite`) now passes `{ extensions: [registerColorTransform] }` explicitly.
|
|
2936
|
-
`mwg/core` now imports from no other module.
|
|
2937
|
-
|
|
2938
|
-
## [0.1.1] - 2026-09-03
|
|
2939
|
-
|
|
2940
|
-
First tagged release. Everything below shipped on `main` before this tag existed; nothing
|
|
2941
|
-
in it is new as of the tag, only now given a version number to refer to.
|
|
2942
|
-
|
|
2943
|
-
### Added
|
|
2944
|
-
|
|
2945
|
-
**Core**
|
|
2946
|
-
- `Game` (owns the Pixi `Application`, the frame loop, current `Scene`), `Scene`, `Signal`
|
|
2947
|
-
(typed event emitter, stack-mode listener order), seeded `Random` (save/restorable state,
|
|
2948
|
-
`withSeed` for scoped determinism), keyboard `Input` with rebinding.
|
|
2949
|
-
- `Achievements`: named milestones unlocked by counters crossing a target - unlocking is
|
|
2950
|
-
derived, never stored; the increment that earns one reports it, `drainNew()` queues
|
|
2951
|
-
announcements, and loaded counts announce nothing.
|
|
2952
|
-
- `Game.step(dt)`, to drive a frame by hand - needed because Chrome throttles
|
|
2953
|
-
`requestAnimationFrame` in a background tab.
|
|
2954
|
-
- `SaveSystem`: named, versioned save slots over `localStorage`, with an in-memory fallback.
|
|
2955
|
-
- `Recorder`/`Player`: action recording and replay for testing - every `Input.onAction`
|
|
2956
|
-
stamped against the `Game.onFrame` count, re-dispatched at the same counts while the loop
|
|
2957
|
-
is driven by hand with `Game.step(dt)`; `serializeReplay`/`deserializeReplay` round-trip
|
|
2958
|
-
the log with validation.
|
|
2959
|
-
- `Collection`: named record collections over `localStorage` (quest logs, bestiaries,
|
|
2960
|
-
achievements) - `all`/`get`/`put`/`remove`/`where`/`clear` reading storage directly, so
|
|
2961
|
-
there is no cached copy to go stale; `SaveSystem`'s memory fallback is now shared.
|
|
2962
|
-
- `SceneStack` with `Game.pushScene`/`popScene`: a scene suspends underneath another and
|
|
2963
|
-
resumes with a result via `Scene.onSuspend`/`onResume` - only the top scene updates, all
|
|
2964
|
-
render, so overlays and opaque scenes both work.
|
|
2965
|
-
- `Logger`: categories and severity over bare `console.log` - four levels, a filter, and a
|
|
2966
|
-
sink tests capture instead of the console.
|
|
2967
|
-
- `Hex`: cube-coordinate hex grid math (`hexNeighbors`, `hexDistance`, `hexLine`, `hexRange`,
|
|
2968
|
-
`hexToPixel`/`pixelToHex`), orientation-agnostic and shared by `roguelike` and `render`.
|
|
2969
|
-
|
|
2970
|
-
**Render**
|
|
2971
|
-
- `Camera`, `TileMap` (chunked and culled against the camera; `square`, `hex`, `isometric`, and
|
|
2972
|
-
`staggered` projections, all culled through one shape-agnostic bounding-box method), `SpriteSheet`, `AnimatedSprite`,
|
|
2973
|
-
`TintedSprite`, and `ColorTransformBatcher` - a per-sprite multiply-and-add colour transform
|
|
2974
|
-
in the batch shader, which Pixi's built-in tint cannot do.
|
|
2975
|
-
- `LayeredSprite`, for characters built from swappable parts (skin, hair, garment).
|
|
2976
|
-
- `ActorAnimator`: the idle/move/action animation-state convention `AnimatedSprite` and
|
|
2977
|
-
`GridMover` never had on their own, with the one rule that makes them coherent - an action
|
|
2978
|
-
interrupts idle/move, but is not itself interruptible while it plays.
|
|
2979
|
-
- `Projectile`: tweens a sprite's position in a straight line, the render-side half of aiming
|
|
2980
|
-
a thrown item or a wand bolt.
|
|
2981
|
-
- `blobIndex`/`autotileFrames`/`BLOB_SHAPES`: the classic 256-combination-to-47-shape blob-tile
|
|
2982
|
-
reduction for auto-tiling a terrain edge or corner from many small pieces.
|
|
2983
|
-
- Verified: SVG textures load correctly through the compiled `data:` URI path; the render path
|
|
2984
|
-
holds 60fps at 4000 tinted sprites and over a 160,000-cell synthetic map, with no silent
|
|
2985
|
-
fallback off WebGL.
|
|
2986
|
-
- `TileMap` reads one sheet per tileset (`tileFrame` packs naming the sheet; plain indices
|
|
2987
|
-
still read as sheet 0), and cells carry an elevation: `setCellHeight` lifts the top tile
|
|
2988
|
-
by `heightStep` per level, growing two shaded side faces per level on the diamond
|
|
2989
|
-
projections, with `tileCenter` riding along so occupants stand on top.
|
|
2990
|
-
|
|
2991
|
-
**Assets**
|
|
2992
|
-
- `load`/`texture`/`get`/`resolve`, synchronous after one `load()` call per scene.
|
|
2993
|
-
- `tools/compile-resources.mjs`: turns every asset into a `data:` URI script, so a compiled
|
|
2994
|
-
build never needs `fetch`/XHR (both blocked from `file://`).
|
|
2995
|
-
|
|
2996
|
-
**UI**
|
|
2997
|
-
- `Window`, `WindowStack` (keyboard focus to the top window only), `ListView`, `MessageBox`,
|
|
2998
|
-
`Label`, `NinePatch`, `VerticalLabel` (for vertical writing systems), `theme`.
|
|
2999
|
-
- `IconGrid`: a multi-column icon grid alongside `ListView`, for SPD-sized item counts. Tap-
|
|
3000
|
-
then-tap reordering and a frame-driven long-press-to-quickslot timer, both plain methods a
|
|
3001
|
-
test can drive without simulating pointer events.
|
|
3002
|
-
|
|
3003
|
-
**i18n**
|
|
3004
|
-
- Message tables, `Intl.PluralRules`-backed plurals, `{token}` interpolation, and
|
|
3005
|
-
`direction()` (ltr/rtl), which `ui`'s `Theme.direction` reads from a game's own glue code.
|
|
3006
|
-
|
|
3007
|
-
**Actors**
|
|
3008
|
-
- `StatBlock` (base + derived stats through a fixed add→multiply→set modifier order),
|
|
3009
|
-
`EquipmentSlots` (ties an item's modifiers to a stat block on equip/unequip),
|
|
3010
|
-
`Progression`/`powerCurve` (levels and experience over a replaceable growth curve),
|
|
3011
|
-
`Inventory` (stacking, weight, containers), `skillCheck`.
|
|
3012
|
-
- `SkillPoints`: a per-stat spendable ledger over a `StatBlock`, with a rising cost-per-rank
|
|
3013
|
-
callback and an optional cap - deliberately not a wrapper around `Progression`, just bridged
|
|
3014
|
-
to it by the points a level-up grants.
|
|
3015
|
-
- `craft(inventory, recipe)`: consumes every ingredient and adds the result atomically - an
|
|
3016
|
-
ingredient shortfall or a result that doesn't fit rolls back everything already removed.
|
|
3017
|
-
- `applyStatusEffect`: a temporary buff/debuff - applies `StatBlock` modifiers and registers
|
|
3018
|
-
their removal against any clock shaped like `TurnClock`'s `add`/`remove`, returning a handle
|
|
3019
|
-
whose `cancel()` removes them early (a cure, a remove-curse scroll).
|
|
3020
|
-
- `identify`/`enchant`/`damageItem`/`repairItem`: item-depth functions over a plain
|
|
3021
|
-
`InventoryItem`, which gained `level`, `durability` and `maxDurability` fields - durability
|
|
3022
|
-
is opt-in per item, a no-op without `maxDurability` set.
|
|
3023
|
-
- `Charges`: a resource that regenerates on its own as turns pass (a wand's limited charges),
|
|
3024
|
-
distinct from a `StatBlock` stat spent per use and restored only by an explicit event.
|
|
3025
|
-
- `rollLoot`: a weighted drop table, the same shape as `world.rollEncounter` - roll whether
|
|
3026
|
-
anything drops, then weight-pick which.
|
|
3027
|
-
- `buy`/`sell`: a shop transaction between two `Inventory`s paid from a `StatBlock` currency
|
|
3028
|
-
stat, all-or-nothing like `craft()` - a full stock/buyer-capacity rollback on failure.
|
|
3029
|
-
- `Advancement`: tiered specialization (level-gated point tiers, one permanent branch choice,
|
|
3030
|
-
one capstone) with a point ledger - never the spend rule, which stays game-side.
|
|
3031
|
-
- `rollAffix`/`applyAffix`/`removeAffix`/`affixOf`: named item affixes carrying only trigger,
|
|
3032
|
-
weight and curse flag; `InventoryItem` gained an optional `affix` field.
|
|
3033
|
-
- `scaledModifiers`: `{stat, op, base, perLevel}` templates resolved to plain `Modifier`s at
|
|
3034
|
-
a given item level.
|
|
3035
|
-
- `Appearances`: per-run seeded shuffling of which look each unidentified kind wears, with
|
|
3036
|
-
`toJSON`/`fromJSON`.
|
|
3037
|
-
- `canAfford`/`spend`: a spendable per-use resource (mana, stamina) over a `StatBlock`
|
|
3038
|
-
pool - one cost or several, all-or-nothing `craft()`-shaped, with a negative cost
|
|
3039
|
-
refused as an authoring error rather than a refund.
|
|
3040
|
-
|
|
3041
|
-
**Roguelike**
|
|
3042
|
-
- `FieldOfView` (visible/explored/remembered), `Pathfinder` (A*, a Dijkstra distance map,
|
|
3043
|
-
`autoExplore`), `Scheduler` (energy-cost turn order), `generateDungeon` (seeded, with an
|
|
3044
|
-
optional `kinds` list for a game's own terrain ids alongside wall/floor).
|
|
3045
|
-
- `decideMonsterAI`: a wander/hunt/flee behaviour loop over a monster's own `FieldOfView`
|
|
3046
|
-
(not the player's), built entirely from already-shipped primitives.
|
|
3047
|
-
- `Secrets`: discoverable/hidden tile state (secret doors, undiscovered traps). A concealed
|
|
3048
|
-
cell is disguised straight in `Level`'s own terrain, so `FieldOfView`/`Pathfinder` need no
|
|
3049
|
-
changes to support it.
|
|
3050
|
-
- `chebyshevDistance`/`traceLine`/`hasLineOfSight`/`canTarget`/`resolveArea`: targeting via a
|
|
3051
|
-
Bresenham line trace (a different, cheaper question than `FieldOfView`'s shadowcast), with
|
|
3052
|
-
`single`/`line`/`burst` area resolution.
|
|
3053
|
-
- `decideMonsterAI` gained a `disposition` option (`hostile`/`neutral`/`peaceful`, defaulting
|
|
3054
|
-
to `hostile`, unchanged) and a `provoked` flag - a peaceful/neutral monster always wanders
|
|
3055
|
-
until either overrides it back to hunting.
|
|
3056
|
-
- `Doors`: open/closed/locked door state, `Secrets`' own shape reused - the state is just
|
|
3057
|
-
terrain, swapped between a door's own open/closed kinds; locking is a separate flag that
|
|
3058
|
-
keeps a door closed and unopenable until `unlock` is called.
|
|
3059
|
-
- `BossPhases`/`AbilityCycle`: HP-fraction thresholds reporting newly entered phases in
|
|
3060
|
-
order, plus named ability cooldowns with `tick`/`ready`/`use` - both JSON round-trippable.
|
|
3061
|
-
- `Blob`: per-cell volumes diffused into passable neighbours and decayed per step, with
|
|
3062
|
-
`cellsAbove` for the game to apply its own effects on.
|
|
3063
|
-
- `Level`, `Secrets` and `Doors` gained `toJSON`/`fromJSON` - the game's own `kinds` table
|
|
3064
|
-
(or live level) is supplied fresh on load, `QuestLog`'s own convention.
|
|
3065
|
-
- `Elevation`: a discrete height per cell, in the `Secrets`/`Doors` sidecar shape.
|
|
3066
|
-
`FieldOfView.update` takes it for asymmetric cliff sight (a cell blocks exactly when
|
|
3067
|
-
above viewer and target alike), and `Pathfinder` takes it with a climb limit (ascent
|
|
3068
|
-
capped, descent free).
|
|
3069
|
-
|
|
3070
|
-
**World**
|
|
3071
|
-
- `World` (many maps, each created once and kept alive, with an explicit non-persistent mode
|
|
3072
|
-
for SPD-shaped floors that rebuild fresh every visit), `Overworld`, `TurnClock`,
|
|
3073
|
-
`rollEncounter`.
|
|
3074
|
-
|
|
3075
|
-
**RPG**
|
|
3076
|
-
- `loadTiledMap` (orthogonal, single embedded tileset, uncompressed CSV layers; isometric and
|
|
3077
|
-
staggered orientations too, each mapped to the matching `TileMap` shape), `GameState`
|
|
3078
|
-
(switches/variables), `MapEvent`/`activePage` (last matching page wins), `EventRunner`,
|
|
3079
|
-
`GridMover` (tweened tile movement, a walk cycle, and `turnTo` for facing without moving).
|
|
3080
|
-
- `QuestLog`: staged quest/mission definitions (`canStart`/`start`/`advance`/`status`), with
|
|
3081
|
-
`toJSON`/`fromJSON` for `SaveSystem`.
|
|
3082
|
-
- `loadTiledMap` reads any number of tilesets - embedded or external (fetching an external
|
|
3083
|
-
`.tsx`/JSON stays the caller's asset loading) - resolving each gid by Tiled's own
|
|
3084
|
-
greatest-firstgid-at-or-below rule.
|
|
3085
|
-
- `automap`: Tiled-style automapping rules - `input` patterns matched anywhere (`EMPTY`
|
|
3086
|
-
constrains nothing), one `output` variant written per match (`EMPTY` leaves the cell
|
|
3087
|
-
alone), rules applied in order with each rule's matches collected before any write.
|
|
3088
|
-
|
|
3089
|
-
**Stage**
|
|
3090
|
-
- `DialogueStage` (backdrop, characters standing in front of it, expressions, speaker focus)
|
|
3091
|
-
and `StageScript`, a small command interpreter run as one awaited call.
|
|
3092
|
-
- `StageScript.runStory`: a story as a graph of named passages - `{goto}` commands and
|
|
3093
|
-
`StageChoice` jumps between them, falling off a passage ending the story.
|
|
3094
|
-
- `importTwee`: Twine's Twee notation (plain text, no DOM needed) into a `StoryScript`:
|
|
3095
|
-
text lines become `say`, `[[links]]` in all three forms become one closing `ask`, and
|
|
3096
|
-
dangling links, doubled passages and setter links are refused rather than half-read.
|
|
3097
|
-
|
|
3098
|
-
**Battle**
|
|
3099
|
-
- `Creature` (wraps `actors.StatBlock`/`Progression`), `TypeMatrix`, `Party`, `battleOrder`,
|
|
3100
|
-
`checkEvolution` (last-match-wins, so a multi-stage chain reaches its final form).
|
|
3101
|
-
- `StatStages`: a bounded, symmetric stage ladder over a `StatBlock` stat (Swords Dance's own
|
|
3102
|
-
shape) - replaces rather than stacks a stat's current modifier, and `resetAll()` clears
|
|
3103
|
-
every stage in one call for the switch-out rule.
|
|
3104
|
-
- `chooseMove`/`chooseSwitch`: battle AI built on `TypeMatrix.multiplierFor` - a move scored
|
|
3105
|
-
by type effectiveness (or a custom `score`), and a switch suggested only when the bench has
|
|
3106
|
-
a genuinely better defensive matchup than staying in.
|
|
3107
|
-
- `BattleHooks`: a battle-scoped event/hook system for passive abilities and held items,
|
|
3108
|
-
keyed by a plain event-name string a game's own battle loop defines; `offSource` removes
|
|
3109
|
-
every hook tied to one source (an ability leaving the field on faint).
|
|
3110
|
-
- `Field`: named, optionally-timed battle-wide conditions (weather, terrain, a screen) a game
|
|
3111
|
-
reads directly (`field.has('rain')`) - distinct from any one creature's own `StatBlock`.
|
|
3112
|
-
|
|
3113
|
-
**Board**
|
|
3114
|
-
- `mwg/board`: a generic `BoardGrid` (owned pieces on a cell grid, move/capture) plus four
|
|
3115
|
-
traditional games built on it - chess (`startingChess`/`legalMoves`/`applyMove`, FEN
|
|
3116
|
-
parsing, check/mate/stalemate/draw detection, and a material-evaluation alpha-beta
|
|
3117
|
-
`chooseMove`/`search` engine), checkers (forced captures, multi-jump chains, king
|
|
3118
|
-
promotion), go (placement, capture-by-surrounding, ko, area scoring after two passes),
|
|
3119
|
-
and backgammon (points, bar/off, dice, hitting a blot).
|
|
3120
|
-
- `startingTactics`/`tacticalMoves`/`tacticalAttack`/`setTacticalOverwatch`: a small
|
|
3121
|
-
grid-tactics layer (move/shoot/overwatch, one action budget per unit per turn) for an
|
|
3122
|
-
XCOM-shaped turn.
|
|
3123
|
-
- `createDeck`/`shuffleDeck`/`deal`: a standard 52-card deck (with optional jokers), shuffled
|
|
3124
|
-
and dealt into equal hands; `trickWinner` resolves one trick - highest trump, or highest of
|
|
3125
|
-
the lead suit with no trump played - leaving bidding and stakes to the game.
|
|
3126
|
-
- `dealSolitaire`/`drawSolitaire`/`moveSolitaireTableau`/`moveSolitaireToFoundation`/
|
|
3127
|
-
`solitaireWon`: a seeded Klondike deal and its four moves - stock/waste draw with
|
|
3128
|
-
waste-recycling, alternating-colour descending tableau moves, ace-up same-suit foundation
|
|
3129
|
-
moves, and the all-four-full win check.
|
|
3130
|
-
- `rollDice`/`rollExpression`: `NdM` and `NdM±K` dice notation over `Random`. `DiceCup`: a
|
|
3131
|
-
kept-die reroll cup (`keep`/`reRoll`/`clearKept`). `scoreDice`: all thirteen standard
|
|
3132
|
-
Yahtzee-shaped categories over a five-die hand.
|
|
3133
|
-
|
|
3134
|
-
**Roguelike**
|
|
3135
|
-
- `CombatHooks`: named-event listeners for a grid actor's combat lifecycle
|
|
3136
|
-
(`beforeAttack`/`beforeDamage`/`afterDamage`/`onKill`, or any game-defined event string),
|
|
3137
|
-
optionally tagged by source for bulk removal; `modifyDamage` runs the `beforeDamage` seam
|
|
3138
|
-
and clamps/reports whether the hit was fully prevented. HP, formulas and when each event
|
|
3139
|
-
fires stay game-side.
|
|
3140
|
-
|
|
3141
|
-
**Audio**
|
|
3142
|
-
- `Sound` (pooled, round-robin) and `Music` (crossfade via `update(dt)`), both taking an
|
|
3143
|
-
injectable `create()` in place of `new Audio()` for testing.
|
|
3144
|
-
|
|
3145
|
-
**Examples**
|
|
3146
|
-
- `colour-transform`, `interface`, `dialogue`, `village` (an NPC with switch-selected
|
|
3147
|
-
conversation pages and an autorun cutscene), `battle`, `dungeon` - an SPD-shaped
|
|
3148
|
-
mockup wiring together most of the above: generated floors, three-state fog of war,
|
|
3149
|
-
bump-to-attack, wander/hunt/flee monsters, secret doors and hidden traps, a thrown flask
|
|
3150
|
-
of oil, a dense icon-grid inventory, autosave-on-descend with permadeath - and `chess`, a
|
|
3151
|
-
playable board against `mwg/board`'s search engine, moved by click-to-select-then-move or
|
|
3152
|
-
a held/repeating arrow-key cursor.
|
|
3153
|
-
|
|
3154
|
-
**Project**
|
|
3155
|
-
- A project website with a live colour-transform demo, the capability-spec table, and the
|
|
3156
|
-
roadmap, deployed to GitHub Pages.
|
|
3157
|
-
- TypeDoc-generated API documentation, built through an isolated toolchain (TypeDoc needs
|
|
3158
|
-
TypeScript's classic compiler API, which TS7 no longer exposes through its main package).
|
|
3159
|
-
|
|
3160
|
-
### Changed
|
|
3161
|
-
- `generateDungeon` gained an optional `kinds` list, so a game can add its own terrain ids
|
|
3162
|
-
(a trap kind, say) alongside the generator's wall/floor without forking it.
|
|
3163
|
-
- `Targeting`'s `AreaShape` gained `cone`, and `coneCells`/`chainTargets`/`knockbackPath`
|
|
3164
|
-
cover sprays, arcs and shoves alongside the existing `single`/`line`/`burst` resolution.
|
|
3165
|
-
- `EquipmentSlots` gained an optional `locked` predicate - a locked slot reports `isLocked()`
|
|
3166
|
-
and refuses both `unequip` and swaps; without it every slot behaves exactly as before.
|
|
3167
|
-
- `examples/dungeon`'s inventory screen is an `IconGrid` now, not a `ListView`.
|
|
3168
|
-
- `TurnClock`'s `TimedEffect` gained an optional `onExpire` callback, fired once right before
|
|
3169
|
-
an effect whose duration has run out is removed - what `applyStatusEffect` needed to tie a
|
|
3170
|
-
status effect's expiry to removing the `StatBlock` modifiers it applied.
|
|
3171
|
-
- `Game`'s scenes run as a stack: `switchScene` replaces everything, `pushScene`/`popScene`
|
|
3172
|
-
suspend and resume; only the top scene updates, all render, and resize reaches the whole
|
|
3173
|
-
stack.
|
|
3174
|
-
- `Pathfinder`'s search loops check the step (both ends on the map, climb within limit)
|
|
3175
|
-
rather than the destination cell alone.
|
|
3176
|
-
|
|
3177
|
-
### Fixed
|
|
3178
|
-
- `checkEvolution` was first-match-wins; a multi-stage evolution chain could get stuck on an
|
|
3179
|
-
earlier form instead of reaching its final one. Now last-match-wins, matching
|
|
3180
|
-
`Event.activePage`'s own convention.
|
|
3181
|
-
- `GridMover` never updated `facing` on a *blocked* move, so approaching an NPC from certain
|
|
3182
|
-
angles left a player unable to turn to face it. Added `turnTo`.
|
|
3183
|
-
- A vault's floor and treasure (behind a secret door) were rendering through the "solid" wall
|
|
3184
|
-
before the door was ever found, because the vault cell was carved eagerly instead of
|
|
3185
|
-
staying genuinely undiscovered rock until the door opened.
|
|
3186
|
-
- Sprites looked blurry under `pixelArt: true` on a hidpi display, even though nearest-neighbour
|
|
3187
|
-
texture sampling was already on. The browser does a second, separate resize compositing the
|
|
3188
|
-
canvas element onto the page (its backing buffer is rarely the same size as its CSS display
|
|
3189
|
-
size), and that step defaults to smoothing regardless of anything Pixi does. Fixed by adding
|
|
3190
|
-
a `.mwg-pixel-art { image-rendering: pixelated }` class to the canvas - a class survives
|
|
3191
|
-
`autoDensity`/`resizeTo` rewriting the canvas's `style` attribute wholesale, where an inline
|
|
3192
|
-
style did not.
|
|
3193
|
-
- Off-map neighbours could alias real cells through `Level.index` (which does not
|
|
3194
|
-
bounds-check), writing distances into the wrong cell once a search looked at the
|
|
3195
|
-
step's origin rather than only its destination. Steps now refuse either end off
|
|
3196
|
-
the map before any index is touched.
|