sci2-ts 0.0.0-stage → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +72 -0
- package/LICENSE +21 -0
- package/README.md +113 -2
- package/apps/viewer/editor.html +43 -0
- package/apps/viewer/explore.html +27 -0
- package/apps/viewer/index.html +26 -0
- package/apps/viewer/package.json +27 -0
- package/apps/viewer/play.html +26 -0
- package/apps/viewer/plugin.d.ts +18 -0
- package/apps/viewer/plugin.js +75 -0
- package/apps/viewer/plugin.ts +84 -0
- package/apps/viewer/src/adlib.d.ts +20 -0
- package/apps/viewer/src/adlib.js +55 -0
- package/apps/viewer/src/adlib.ts +62 -0
- package/apps/viewer/src/app.d.ts +5 -0
- package/apps/viewer/src/app.js +5 -0
- package/apps/viewer/src/app.ts +5 -0
- package/apps/viewer/src/asset-index.d.ts +22 -0
- package/apps/viewer/src/asset-index.js +74 -0
- package/apps/viewer/src/asset-index.ts +90 -0
- package/apps/viewer/src/audio.d.ts +28 -0
- package/apps/viewer/src/audio.js +102 -0
- package/apps/viewer/src/audio.ts +110 -0
- package/apps/viewer/src/editor-handles.d.ts +63 -0
- package/apps/viewer/src/editor-handles.js +332 -0
- package/apps/viewer/src/editor-handles.ts +368 -0
- package/apps/viewer/src/editor-languages.d.ts +23 -0
- package/apps/viewer/src/editor-languages.js +157 -0
- package/apps/viewer/src/editor-languages.ts +135 -0
- package/apps/viewer/src/editor.css +213 -0
- package/apps/viewer/src/editor.d.ts +1 -0
- package/apps/viewer/src/editor.js +393 -0
- package/apps/viewer/src/editor.ts +412 -0
- package/apps/viewer/src/explore/classes.d.ts +7 -0
- package/apps/viewer/src/explore/classes.js +63 -0
- package/apps/viewer/src/explore/classes.ts +61 -0
- package/apps/viewer/src/explore/context.d.ts +33 -0
- package/apps/viewer/src/explore/context.js +96 -0
- package/apps/viewer/src/explore/context.ts +124 -0
- package/apps/viewer/src/explore/explore.css +93 -0
- package/apps/viewer/src/explore/explore.d.ts +1 -0
- package/apps/viewer/src/explore/explore.js +102 -0
- package/apps/viewer/src/explore/explore.ts +104 -0
- package/apps/viewer/src/explore/inspect.d.ts +5 -0
- package/apps/viewer/src/explore/inspect.js +208 -0
- package/apps/viewer/src/explore/inspect.ts +279 -0
- package/apps/viewer/src/explore/live.d.ts +22 -0
- package/apps/viewer/src/explore/live.js +318 -0
- package/apps/viewer/src/explore/live.ts +365 -0
- package/apps/viewer/src/explore/map.d.ts +11 -0
- package/apps/viewer/src/explore/map.js +182 -0
- package/apps/viewer/src/explore/map.ts +193 -0
- package/apps/viewer/src/files.d.ts +21 -0
- package/apps/viewer/src/files.js +69 -0
- package/apps/viewer/src/files.ts +72 -0
- package/apps/viewer/src/game-profile.d.ts +19 -0
- package/apps/viewer/src/game-profile.js +4 -0
- package/apps/viewer/src/game-profile.ts +26 -0
- package/apps/viewer/src/main.d.ts +1 -0
- package/apps/viewer/src/main.js +473 -0
- package/apps/viewer/src/main.ts +527 -0
- package/apps/viewer/src/music.d.ts +14 -0
- package/apps/viewer/src/music.js +32 -0
- package/apps/viewer/src/music.ts +34 -0
- package/apps/viewer/src/opl-worklet.d.ts +1 -0
- package/apps/viewer/src/opl-worklet.js +47 -0
- package/apps/viewer/src/opl-worklet.ts +55 -0
- package/apps/viewer/src/overlay.d.ts +31 -0
- package/apps/viewer/src/overlay.js +103 -0
- package/apps/viewer/src/overlay.ts +123 -0
- package/apps/viewer/src/play.css +14 -0
- package/apps/viewer/src/play.d.ts +1 -0
- package/apps/viewer/src/play.js +179 -0
- package/apps/viewer/src/play.ts +177 -0
- package/apps/viewer/src/saves.d.ts +10 -0
- package/apps/viewer/src/saves.js +50 -0
- package/apps/viewer/src/saves.ts +51 -0
- package/apps/viewer/src/session.d.ts +91 -0
- package/apps/viewer/src/session.js +301 -0
- package/apps/viewer/src/session.ts +321 -0
- package/apps/viewer/src/sound-preview.d.ts +7 -0
- package/apps/viewer/src/sound-preview.js +214 -0
- package/apps/viewer/src/sound-preview.ts +228 -0
- package/apps/viewer/src/style.css +64 -0
- package/apps/viewer/vite.config.ts +25 -0
- package/bin/sci-ts.mjs +9 -0
- package/lib/994.sc +49 -0
- package/lib/995.sc +53 -0
- package/lib/996.sc +299 -0
- package/lib/997.sc +198 -0
- package/lib/998.sc +338 -0
- package/lib/999.sc +189 -0
- package/lib/resources.d.ts +2 -0
- package/lib/resources.js +84 -0
- package/lib/resources.ts +88 -0
- package/lib/system.sh +62 -0
- package/package.json +75 -4
- package/packages/content/room.schema.json +267 -0
- package/packages/content/src/index.d.ts +3 -0
- package/packages/content/src/index.js +3 -0
- package/packages/content/src/index.ts +3 -0
- package/packages/content/src/room.d.ts +111 -0
- package/packages/content/src/room.js +886 -0
- package/packages/content/src/room.ts +1011 -0
- package/packages/content/src/target.d.ts +80 -0
- package/packages/content/src/target.js +1 -0
- package/packages/content/src/target.ts +60 -0
- package/packages/content/src/yarn.d.ts +90 -0
- package/packages/content/src/yarn.js +214 -0
- package/packages/content/src/yarn.ts +261 -0
- package/packages/sci/src/analysis/game.d.ts +90 -0
- package/packages/sci/src/analysis/game.js +221 -0
- package/packages/sci/src/analysis/game.ts +305 -0
- package/packages/sci/src/analysis/runtime.d.ts +58 -0
- package/packages/sci/src/analysis/runtime.js +133 -0
- package/packages/sci/src/analysis/runtime.ts +163 -0
- package/packages/sci/src/audio/adlib.d.ts +73 -0
- package/packages/sci/src/audio/adlib.js +280 -0
- package/packages/sci/src/audio/adlib.ts +329 -0
- package/packages/sci/src/audio/index.d.ts +43 -0
- package/packages/sci/src/audio/index.js +99 -0
- package/packages/sci/src/audio/index.ts +122 -0
- package/packages/sci/src/audio/midi.d.ts +92 -0
- package/packages/sci/src/audio/midi.js +242 -0
- package/packages/sci/src/audio/midi.ts +262 -0
- package/packages/sci/src/audio/opl2.d.ts +74 -0
- package/packages/sci/src/audio/opl2.js +283 -0
- package/packages/sci/src/audio/opl2.ts +283 -0
- package/packages/sci/src/audio/sol.d.ts +32 -0
- package/packages/sci/src/audio/sol.js +81 -0
- package/packages/sci/src/audio/sol.ts +100 -0
- package/packages/sci/src/audio/write.d.ts +35 -0
- package/packages/sci/src/audio/write.js +91 -0
- package/packages/sci/src/audio/write.ts +108 -0
- package/packages/sci/src/gfx/cel.d.ts +36 -0
- package/packages/sci/src/gfx/cel.js +82 -0
- package/packages/sci/src/gfx/cel.ts +110 -0
- package/packages/sci/src/gfx/palette.d.ts +24 -0
- package/packages/sci/src/gfx/palette.js +49 -0
- package/packages/sci/src/gfx/palette.ts +56 -0
- package/packages/sci/src/gfx/pic-file.d.ts +46 -0
- package/packages/sci/src/gfx/pic-file.js +114 -0
- package/packages/sci/src/gfx/pic-file.ts +155 -0
- package/packages/sci/src/gfx/pic.d.ts +27 -0
- package/packages/sci/src/gfx/pic.js +34 -0
- package/packages/sci/src/gfx/pic.ts +53 -0
- package/packages/sci/src/gfx/quantize.d.ts +42 -0
- package/packages/sci/src/gfx/quantize.js +199 -0
- package/packages/sci/src/gfx/quantize.ts +218 -0
- package/packages/sci/src/gfx/view-file.d.ts +62 -0
- package/packages/sci/src/gfx/view-file.js +182 -0
- package/packages/sci/src/gfx/view-file.ts +233 -0
- package/packages/sci/src/gfx/view.d.ts +28 -0
- package/packages/sci/src/gfx/view.js +45 -0
- package/packages/sci/src/gfx/view.ts +62 -0
- package/packages/sci/src/index.d.ts +38 -0
- package/packages/sci/src/index.js +38 -0
- package/packages/sci/src/index.ts +38 -0
- package/packages/sci/src/motion/pathfinding.d.ts +40 -0
- package/packages/sci/src/motion/pathfinding.js +140 -0
- package/packages/sci/src/motion/pathfinding.ts +147 -0
- package/packages/sci/src/resource/archive.d.ts +16 -0
- package/packages/sci/src/resource/archive.js +51 -0
- package/packages/sci/src/resource/archive.ts +56 -0
- package/packages/sci/src/resource/lzs.d.ts +12 -0
- package/packages/sci/src/resource/lzs.js +64 -0
- package/packages/sci/src/resource/lzs.ts +66 -0
- package/packages/sci/src/resource/manager.d.ts +45 -0
- package/packages/sci/src/resource/manager.js +158 -0
- package/packages/sci/src/resource/manager.ts +184 -0
- package/packages/sci/src/resource/map.d.ts +18 -0
- package/packages/sci/src/resource/map.js +34 -0
- package/packages/sci/src/resource/map.ts +44 -0
- package/packages/sci/src/resource/types.d.ts +37 -0
- package/packages/sci/src/resource/types.js +45 -0
- package/packages/sci/src/resource/types.ts +57 -0
- package/packages/sci/src/script/assembly.d.ts +67 -0
- package/packages/sci/src/script/assembly.js +748 -0
- package/packages/sci/src/script/assembly.ts +714 -0
- package/packages/sci/src/script/compiler.d.ts +75 -0
- package/packages/sci/src/script/compiler.js +993 -0
- package/packages/sci/src/script/compiler.ts +1040 -0
- package/packages/sci/src/script/disasm.d.ts +81 -0
- package/packages/sci/src/script/disasm.js +318 -0
- package/packages/sci/src/script/disasm.ts +323 -0
- package/packages/sci/src/script/kernel-names.d.ts +6 -0
- package/packages/sci/src/script/kernel-names.js +165 -0
- package/packages/sci/src/script/kernel-names.ts +165 -0
- package/packages/sci/src/script/opcodes.d.ts +22 -0
- package/packages/sci/src/script/opcodes.js +45 -0
- package/packages/sci/src/script/opcodes.ts +72 -0
- package/packages/sci/src/script/script.d.ts +56 -0
- package/packages/sci/src/script/script.js +63 -0
- package/packages/sci/src/script/script.ts +111 -0
- package/packages/sci/src/script/sexpr.d.ts +45 -0
- package/packages/sci/src/script/sexpr.js +151 -0
- package/packages/sci/src/script/sexpr.ts +139 -0
- package/packages/sci/src/script/vocab.d.ts +15 -0
- package/packages/sci/src/script/vocab.js +44 -0
- package/packages/sci/src/script/vocab.ts +48 -0
- package/packages/sci/src/script/world.d.ts +25 -0
- package/packages/sci/src/script/world.js +65 -0
- package/packages/sci/src/script/world.ts +70 -0
- package/packages/sci/src/text/font.d.ts +37 -0
- package/packages/sci/src/text/font.js +103 -0
- package/packages/sci/src/text/font.ts +125 -0
- package/packages/sci/src/text/message.d.ts +69 -0
- package/packages/sci/src/text/message.js +171 -0
- package/packages/sci/src/text/message.ts +205 -0
- package/packages/sci/src/vm/kernels/arrays.d.ts +19 -0
- package/packages/sci/src/vm/kernels/arrays.js +182 -0
- package/packages/sci/src/vm/kernels/arrays.ts +164 -0
- package/packages/sci/src/vm/kernels/audio.d.ts +70 -0
- package/packages/sci/src/vm/kernels/audio.js +347 -0
- package/packages/sci/src/vm/kernels/audio.ts +349 -0
- package/packages/sci/src/vm/kernels/core.d.ts +5 -0
- package/packages/sci/src/vm/kernels/core.js +87 -0
- package/packages/sci/src/vm/kernels/core.ts +91 -0
- package/packages/sci/src/vm/kernels/graphics.d.ts +141 -0
- package/packages/sci/src/vm/kernels/graphics.js +467 -0
- package/packages/sci/src/vm/kernels/graphics.ts +502 -0
- package/packages/sci/src/vm/kernels/index.d.ts +8 -0
- package/packages/sci/src/vm/kernels/index.js +29 -0
- package/packages/sci/src/vm/kernels/index.ts +32 -0
- package/packages/sci/src/vm/kernels/lists.d.ts +6 -0
- package/packages/sci/src/vm/kernels/lists.js +127 -0
- package/packages/sci/src/vm/kernels/lists.ts +111 -0
- package/packages/sci/src/vm/kernels/motion.d.ts +7 -0
- package/packages/sci/src/vm/kernels/motion.js +204 -0
- package/packages/sci/src/vm/kernels/motion.ts +194 -0
- package/packages/sci/src/vm/kernels/palette.d.ts +82 -0
- package/packages/sci/src/vm/kernels/palette.js +292 -0
- package/packages/sci/src/vm/kernels/palette.ts +303 -0
- package/packages/sci/src/vm/kernels/saves.d.ts +45 -0
- package/packages/sci/src/vm/kernels/saves.js +123 -0
- package/packages/sci/src/vm/kernels/saves.ts +149 -0
- package/packages/sci/src/vm/kernels/system.d.ts +62 -0
- package/packages/sci/src/vm/kernels/system.js +110 -0
- package/packages/sci/src/vm/kernels/system.ts +128 -0
- package/packages/sci/src/vm/kernels/text.d.ts +13 -0
- package/packages/sci/src/vm/kernels/text.js +338 -0
- package/packages/sci/src/vm/kernels/text.ts +328 -0
- package/packages/sci/src/vm/memory.d.ts +138 -0
- package/packages/sci/src/vm/memory.js +168 -0
- package/packages/sci/src/vm/memory.ts +266 -0
- package/packages/sci/src/vm/replace.d.ts +11 -0
- package/packages/sci/src/vm/replace.js +14 -0
- package/packages/sci/src/vm/replace.ts +16 -0
- package/packages/sci/src/vm/savegame.d.ts +89 -0
- package/packages/sci/src/vm/savegame.js +161 -0
- package/packages/sci/src/vm/savegame.ts +188 -0
- package/packages/sci/src/vm/value.d.ts +17 -0
- package/packages/sci/src/vm/value.js +12 -0
- package/packages/sci/src/vm/value.ts +25 -0
- package/packages/sci/src/vm/vm.d.ts +155 -0
- package/packages/sci/src/vm/vm.js +1053 -0
- package/packages/sci/src/vm/vm.ts +914 -0
- package/tools/adlib-render.d.ts +1 -0
- package/tools/adlib-render.js +49 -0
- package/tools/adlib-render.ts +42 -0
- package/tools/analyze.d.ts +1 -0
- package/tools/analyze.js +25 -0
- package/tools/analyze.ts +25 -0
- package/tools/art/build.d.ts +34 -0
- package/tools/art/build.js +175 -0
- package/tools/art/build.ts +153 -0
- package/tools/art.d.ts +1 -0
- package/tools/art.js +31 -0
- package/tools/art.ts +29 -0
- package/tools/asm.d.ts +1 -0
- package/tools/asm.js +61 -0
- package/tools/asm.ts +55 -0
- package/tools/cli.d.ts +1 -0
- package/tools/cli.js +99 -0
- package/tools/cli.ts +100 -0
- package/tools/editor-server.d.ts +29 -0
- package/tools/editor-server.js +162 -0
- package/tools/editor-server.ts +176 -0
- package/tools/explore.d.ts +1 -0
- package/tools/explore.js +305 -0
- package/tools/explore.ts +250 -0
- package/tools/game/audio.d.ts +19 -0
- package/tools/game/audio.js +143 -0
- package/tools/game/audio.ts +130 -0
- package/tools/game/build.d.ts +46 -0
- package/tools/game/build.js +259 -0
- package/tools/game/build.ts +283 -0
- package/tools/game/defaults.d.ts +26 -0
- package/tools/game/defaults.js +82 -0
- package/tools/game/defaults.ts +83 -0
- package/tools/game/font.d.ts +3 -0
- package/tools/game/font.js +124 -0
- package/tools/game/font.ts +126 -0
- package/tools/game/kit.d.ts +7 -0
- package/tools/game/kit.js +7 -0
- package/tools/game/kit.ts +10 -0
- package/tools/game/new.d.ts +8 -0
- package/tools/game/new.js +39 -0
- package/tools/game/new.ts +38 -0
- package/tools/game/target.d.ts +7 -0
- package/tools/game/target.js +41 -0
- package/tools/game/target.ts +42 -0
- package/tools/game/template/resources.ts.tmpl +43 -0
- package/tools/game/template/rooms/1.room.yaml +9 -0
- package/tools/game/template/rooms/1.yarn +17 -0
- package/tools/game/template/scripts/0.sc +24 -0
- package/tools/game.d.ts +1 -0
- package/tools/game.js +77 -0
- package/tools/game.ts +70 -0
- package/tools/mod-build.d.ts +28 -0
- package/tools/mod-build.js +173 -0
- package/tools/mod-build.ts +179 -0
- package/tools/mod-target.d.ts +16 -0
- package/tools/mod-target.js +26 -0
- package/tools/mod-target.ts +32 -0
- package/tools/mod.d.ts +1 -0
- package/tools/mod.js +47 -0
- package/tools/mod.ts +45 -0
- package/tools/msg.d.ts +1 -0
- package/tools/msg.js +40 -0
- package/tools/msg.ts +36 -0
- package/tools/node-files.d.ts +3 -0
- package/tools/node-files.js +34 -0
- package/tools/node-files.ts +33 -0
- package/tools/patches.d.ts +3 -0
- package/tools/patches.js +13 -0
- package/tools/patches.ts +13 -0
- package/tools/pic-build.d.ts +9 -0
- package/tools/pic-build.js +26 -0
- package/tools/pic-build.ts +27 -0
- package/tools/pic.d.ts +1 -0
- package/tools/pic.js +64 -0
- package/tools/pic.ts +61 -0
- package/tools/play.d.ts +1 -0
- package/tools/play.js +54 -0
- package/tools/play.ts +54 -0
- package/tools/png.d.ts +16 -0
- package/tools/png.js +124 -0
- package/tools/png.ts +123 -0
- package/tools/res.d.ts +1 -0
- package/tools/res.js +48 -0
- package/tools/res.ts +50 -0
- package/tools/scenario.d.ts +1 -0
- package/tools/scenario.js +74 -0
- package/tools/scenario.ts +80 -0
- package/tools/site/build.d.ts +8 -0
- package/tools/site/build.js +110 -0
- package/tools/site/build.ts +116 -0
- package/tools/site/markdown.d.ts +11 -0
- package/tools/site/markdown.js +88 -0
- package/tools/site/markdown.ts +84 -0
- package/tools/view-build.d.ts +34 -0
- package/tools/view-build.js +47 -0
- package/tools/view-build.ts +71 -0
- package/tools/view.d.ts +1 -0
- package/tools/view.js +54 -0
- package/tools/view.ts +52 -0
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import type { Font, Glyph } from "../../packages/sci/src/index.ts";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* sci-ts's own pixel font: 7 pixels from the top of a capital to the baseline, 2 below for
|
|
5
|
+
* descenders, a line height of 10. Drawn here as rows of `#` (ink) and `.`; a glyph is 7 rows
|
|
6
|
+
* (sitting on the baseline) or 9 (with a descender). Each glyph gets one column of space after
|
|
7
|
+
* it. Characters 0-31 and 127 are empty.
|
|
8
|
+
*/
|
|
9
|
+
const ROWS = 9;
|
|
10
|
+
const LINE_HEIGHT = 10;
|
|
11
|
+
|
|
12
|
+
const GLYPHS: Record<string, string> = {
|
|
13
|
+
" ": "... ... ... ... ... ... ...",
|
|
14
|
+
"!": "# # # # # . #",
|
|
15
|
+
'"': "#.# #.# ... ... ... ... ...",
|
|
16
|
+
"#": "..... .#.#. ##### .#.#. ##### .#.#. .....",
|
|
17
|
+
"$": "..#.. .#### #.#.. .###. ..#.# ####. ..#..",
|
|
18
|
+
"%": "##..# ##.#. ..#.. .#... #..## #..## .....",
|
|
19
|
+
"&": ".#.. #.#. .#.. #.#. #..# #.#. .#.#",
|
|
20
|
+
"'": "# # . . . . .",
|
|
21
|
+
"(": ".# #. #. #. #. #. .#",
|
|
22
|
+
")": "#. .# .# .# .# .# #.",
|
|
23
|
+
"*": "... #.# .#. #.# ... ... ...",
|
|
24
|
+
"+": "... ... .#. ### .#. ... ...",
|
|
25
|
+
",": ".. .. .. .. .. .# .# #. ..",
|
|
26
|
+
"-": "... ... ... ### ... ... ...",
|
|
27
|
+
".": ". . . . . . #",
|
|
28
|
+
"/": "...# ...# ..#. ..#. .#.. #... #...",
|
|
29
|
+
"0": ".##. #..# #.## ##.# #..# #..# .##.",
|
|
30
|
+
"1": ".#. ##. .#. .#. .#. .#. ###",
|
|
31
|
+
"2": ".##. #..# ...# ..#. .#.. #... ####",
|
|
32
|
+
"3": "###. ...# ...# .##. ...# ...# ###.",
|
|
33
|
+
"4": "#..# #..# #..# #### ...# ...# ...#",
|
|
34
|
+
"5": "#### #... ###. ...# ...# #..# .##.",
|
|
35
|
+
"6": ".##. #... #... ###. #..# #..# .##.",
|
|
36
|
+
"7": "#### ...# ..#. ..#. .#.. .#.. .#..",
|
|
37
|
+
"8": ".##. #..# #..# .##. #..# #..# .##.",
|
|
38
|
+
"9": ".##. #..# #..# .### ...# ...# .##.",
|
|
39
|
+
":": ". . # . . # .",
|
|
40
|
+
";": ".. .. .# .. .. .# .# #. ..",
|
|
41
|
+
"<": "... ..# .#. #.. .#. ..# ...",
|
|
42
|
+
"=": ".... .... #### .... #### .... ....",
|
|
43
|
+
">": "... #.. .#. ..# .#. #.. ...",
|
|
44
|
+
"?": ".##. #..# ...# ..#. .#.. .... .#..",
|
|
45
|
+
"@": ".###. #...# #.### #.#.# #.### #.... .###.",
|
|
46
|
+
"A": ".##. #..# #..# #### #..# #..# #..#",
|
|
47
|
+
"B": "###. #..# #..# ###. #..# #..# ###.",
|
|
48
|
+
"C": ".##. #..# #... #... #... #..# .##.",
|
|
49
|
+
"D": "###. #..# #..# #..# #..# #..# ###.",
|
|
50
|
+
"E": "#### #... #... ###. #... #... ####",
|
|
51
|
+
"F": "#### #... #... ###. #... #... #...",
|
|
52
|
+
"G": ".##. #..# #... #.## #..# #..# .###",
|
|
53
|
+
"H": "#..# #..# #..# #### #..# #..# #..#",
|
|
54
|
+
"I": "### .#. .#. .#. .#. .#. ###",
|
|
55
|
+
"J": "..## ...# ...# ...# ...# #..# .##.",
|
|
56
|
+
"K": "#..# #.#. ##.. ##.. #.#. #..# #..#",
|
|
57
|
+
"L": "#... #... #... #... #... #... ####",
|
|
58
|
+
"M": "#...# ##.## #.#.# #.#.# #...# #...# #...#",
|
|
59
|
+
"N": "#..# ##.# ##.# #.## #.## #..# #..#",
|
|
60
|
+
"O": ".##. #..# #..# #..# #..# #..# .##.",
|
|
61
|
+
"P": "###. #..# #..# ###. #... #... #...",
|
|
62
|
+
"Q": ".##. #..# #..# #..# #..# #.#. .#.#",
|
|
63
|
+
"R": "###. #..# #..# ###. #.#. #..# #..#",
|
|
64
|
+
"S": ".##. #..# #... .##. ...# #..# .##.",
|
|
65
|
+
"T": "##### ..#.. ..#.. ..#.. ..#.. ..#.. ..#..",
|
|
66
|
+
"U": "#..# #..# #..# #..# #..# #..# .##.",
|
|
67
|
+
"V": "#...# #...# #...# .#.#. .#.#. ..#.. ..#..",
|
|
68
|
+
"W": "#...# #...# #...# #.#.# #.#.# ##.## #...#",
|
|
69
|
+
"X": "#..# #..# .##. .##. .##. #..# #..#",
|
|
70
|
+
"Y": "#...# #...# .#.#. ..#.. ..#.. ..#.. ..#..",
|
|
71
|
+
"Z": "#### ...# ..#. .#.. #... #... ####",
|
|
72
|
+
"[": "## #. #. #. #. #. ##",
|
|
73
|
+
"\\": "#... #... .#.. .#.. ..#. ...# ...#",
|
|
74
|
+
"]": "## .# .# .# .# .# ##",
|
|
75
|
+
"^": ".#. #.# ... ... ... ... ...",
|
|
76
|
+
_: ".... .... .... .... .... .... .... .... ####",
|
|
77
|
+
"`": "#. .# .. .. .. .. ..",
|
|
78
|
+
a: ".... .... .##. ...# .### #..# .###",
|
|
79
|
+
b: "#... #... ###. #..# #..# #..# ###.",
|
|
80
|
+
c: "... ... .## #.. #.. #.. .##",
|
|
81
|
+
d: "...# ...# .### #..# #..# #..# .###",
|
|
82
|
+
e: ".... .... .##. #..# #### #... .##.",
|
|
83
|
+
f: ".## #.. ### #.. #.. #.. #..",
|
|
84
|
+
g: ".... .... .### #..# #..# #..# .### ...# .##.",
|
|
85
|
+
h: "#... #... ###. #..# #..# #..# #..#",
|
|
86
|
+
i: "# . # # # # #",
|
|
87
|
+
j: ".# .. .# .# .# .# .# .# #.",
|
|
88
|
+
k: "#... #... #..# #.#. ##.. #.#. #..#",
|
|
89
|
+
l: "#. #. #. #. #. #. .#",
|
|
90
|
+
m: "..... ..... ####. #.#.# #.#.# #.#.# #.#.#",
|
|
91
|
+
n: ".... .... ###. #..# #..# #..# #..#",
|
|
92
|
+
o: ".... .... .##. #..# #..# #..# .##.",
|
|
93
|
+
p: ".... .... ###. #..# #..# #..# ###. #... #...",
|
|
94
|
+
q: ".... .... .### #..# #..# #..# .### ...# ...#",
|
|
95
|
+
r: "... ... #.# ##. #.. #.. #..",
|
|
96
|
+
s: ".... .... .### #... .##. ...# ###.",
|
|
97
|
+
t: ".#. .#. ### .#. .#. .#. ..#",
|
|
98
|
+
u: ".... .... #..# #..# #..# #..# .###",
|
|
99
|
+
v: "..... ..... #...# #...# .#.#. .#.#. ..#..",
|
|
100
|
+
w: "..... ..... #...# #...# #.#.# #.#.# .#.#.",
|
|
101
|
+
x: "..... ..... #...# .#.#. ..#.. .#.#. #...#",
|
|
102
|
+
y: ".... .... #..# #..# #..# #..# .### ...# .##.",
|
|
103
|
+
z: ".... .... #### ...# ..#. .#.. ####",
|
|
104
|
+
"{": ".## .#. .#. #.. .#. .#. .##",
|
|
105
|
+
"|": "# # # # # # # # #",
|
|
106
|
+
"}": "##. .#. .#. ..# .#. .#. ##.",
|
|
107
|
+
"~": ".... .... .#.# #.#. .... .... ....",
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
function glyph(char: string, art: string): Glyph {
|
|
111
|
+
const rows = art.split(" ");
|
|
112
|
+
if (rows.length !== 7 && rows.length !== 9) throw new Error(`glyph ${JSON.stringify(char)}: ${rows.length} rows`);
|
|
113
|
+
const inked = rows[0]!.length;
|
|
114
|
+
if (rows.some((r) => r.length !== inked)) throw new Error(`glyph ${JSON.stringify(char)}: rows of different widths`);
|
|
115
|
+
const width = inked + 1;
|
|
116
|
+
const pixels = new Uint8Array(width * ROWS);
|
|
117
|
+
rows.forEach((row, y) => [...row].forEach((c, x) => (pixels[y * width + x] = c === "#" ? 1 : 0)));
|
|
118
|
+
return { width, height: ROWS, pixels };
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/** The font, as a Font (write it with writeFont). */
|
|
122
|
+
export function pixelFont(): Font {
|
|
123
|
+
const glyphs: Glyph[] = Array.from({ length: 128 }, () => ({ width: 0, height: 0, pixels: new Uint8Array(0) }));
|
|
124
|
+
for (const [char, art] of Object.entries(GLYPHS)) glyphs[char.charCodeAt(0)] = glyph(char, art);
|
|
125
|
+
return { height: LINE_HEIGHT, glyphs };
|
|
126
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What a game's resources.ts imports to make art and music in code: the engine's writers
|
|
3
|
+
* and types, and the default palette's colours.
|
|
4
|
+
*/
|
|
5
|
+
export { ResourceType, SoundDevice, writeFont, writeHunkPalette, writePic, writeSound, writeView, type Cel, type Font, type HunkPaletteFile, type MidiEvent, type PicFile, type ResourceData, type SoundSpec, type ViewFile, } from "../../packages/sci/src/index.ts";
|
|
6
|
+
export { BASE_PALETTE, CURSOR_VIEW, Colour, DEFAULT_FONT, basePalette, cube } from "./defaults.ts";
|
|
7
|
+
export { pixelFont } from "./font.ts";
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What a game's resources.ts imports to make art and music in code: the engine's writers
|
|
3
|
+
* and types, and the default palette's colours.
|
|
4
|
+
*/
|
|
5
|
+
export { ResourceType, SoundDevice, writeFont, writeHunkPalette, writePic, writeSound, writeView, } from "../../packages/sci/src/index.js";
|
|
6
|
+
export { BASE_PALETTE, CURSOR_VIEW, Colour, DEFAULT_FONT, basePalette, cube } from "./defaults.js";
|
|
7
|
+
export { pixelFont } from "./font.js";
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What a game's resources.ts imports to make art and music in code: the engine's writers
|
|
3
|
+
* and types, and the default palette's colours.
|
|
4
|
+
*/
|
|
5
|
+
export {
|
|
6
|
+
ResourceType, SoundDevice, writeFont, writeHunkPalette, writePic, writeSound, writeView,
|
|
7
|
+
type Cel, type Font, type HunkPaletteFile, type MidiEvent, type PicFile, type ResourceData, type SoundSpec, type ViewFile,
|
|
8
|
+
} from "../../packages/sci/src/index.ts";
|
|
9
|
+
export { BASE_PALETTE, CURSOR_VIEW, Colour, DEFAULT_FONT, basePalette, cube } from "./defaults.ts";
|
|
10
|
+
export { pixelFont } from "./font.ts";
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A new game in `target` (a folder that doesn't exist yet), from the template. NAME becomes
|
|
3
|
+
* the folder's name and Name the same in capitals (the game's class). KIT and SCHEMA become
|
|
4
|
+
* the art kit and the room schema: by path for a game inside this repository, through the
|
|
5
|
+
* sci2-ts package for one outside it. `.tmpl` files lose the suffix (they aren't type
|
|
6
|
+
* checked where they stand). `refs` overrides that choice. Returns the game's folder.
|
|
7
|
+
*/
|
|
8
|
+
export declare function newGame(target: string, refs?: "path" | "package"): string;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { existsSync, mkdirSync, readFileSync, readdirSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { basename, join, relative, resolve } from "node:path";
|
|
3
|
+
import { GameBuildError } from "./build.js";
|
|
4
|
+
/** Where `sci-ts new` copies from: a room in YAML and Yarn, the game, placeholder art. */
|
|
5
|
+
const TEMPLATE = join(import.meta.dirname, "template");
|
|
6
|
+
const ROOT = resolve(import.meta.dirname, "../..");
|
|
7
|
+
/**
|
|
8
|
+
* A new game in `target` (a folder that doesn't exist yet), from the template. NAME becomes
|
|
9
|
+
* the folder's name and Name the same in capitals (the game's class). KIT and SCHEMA become
|
|
10
|
+
* the art kit and the room schema: by path for a game inside this repository, through the
|
|
11
|
+
* sci2-ts package for one outside it. `.tmpl` files lose the suffix (they aren't type
|
|
12
|
+
* checked where they stand). `refs` overrides that choice. Returns the game's folder.
|
|
13
|
+
*/
|
|
14
|
+
export function newGame(target, refs) {
|
|
15
|
+
const name = basename(resolve(target));
|
|
16
|
+
if (!/^[a-z][a-z0-9-]*$/.test(name))
|
|
17
|
+
throw new GameBuildError(`${name}: a game's name is lower-case letters, digits and dashes, starting with a letter`);
|
|
18
|
+
if (existsSync(target) && readdirSync(target).some((f) => f === "scripts" || f === "rooms"))
|
|
19
|
+
throw new GameBuildError(`${target} is already there`);
|
|
20
|
+
const inside = refs ? refs === "path" : !relative(ROOT, resolve(target)).startsWith("..");
|
|
21
|
+
const slash = (p) => p.replaceAll("\\", "/");
|
|
22
|
+
const kit = inside ? slash(relative(resolve(target), join(ROOT, "tools/game/kit.ts"))) : "sci2-ts/kit";
|
|
23
|
+
const schema = inside
|
|
24
|
+
? slash(relative(join(resolve(target), "rooms"), join(ROOT, "packages/content/room.schema.json")))
|
|
25
|
+
: "../node_modules/sci2-ts/packages/content/room.schema.json";
|
|
26
|
+
const Name = name.replace(/(^|-)([a-z])/g, (_, __, c) => c.toUpperCase());
|
|
27
|
+
const fill = (text) => text.replaceAll('"KIT"', JSON.stringify(kit)).replaceAll("SCHEMA", schema).replaceAll("NAME", name).replaceAll("Name", Name);
|
|
28
|
+
const copy = (from, to) => {
|
|
29
|
+
mkdirSync(to, { recursive: true });
|
|
30
|
+
for (const entry of readdirSync(from, { withFileTypes: true })) {
|
|
31
|
+
if (entry.isDirectory())
|
|
32
|
+
copy(join(from, entry.name), join(to, entry.name));
|
|
33
|
+
else
|
|
34
|
+
writeFileSync(join(to, entry.name.replace(/\.tmpl$/, "")), fill(readFileSync(join(from, entry.name), "utf8")));
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
copy(TEMPLATE, target);
|
|
38
|
+
return target;
|
|
39
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { existsSync, mkdirSync, readFileSync, readdirSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { basename, join, relative, resolve } from "node:path";
|
|
3
|
+
import { GameBuildError } from "./build.ts";
|
|
4
|
+
|
|
5
|
+
/** Where `sci-ts new` copies from: a room in YAML and Yarn, the game, placeholder art. */
|
|
6
|
+
const TEMPLATE = join(import.meta.dirname, "template");
|
|
7
|
+
const ROOT = resolve(import.meta.dirname, "../..");
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* A new game in `target` (a folder that doesn't exist yet), from the template. NAME becomes
|
|
11
|
+
* the folder's name and Name the same in capitals (the game's class). KIT and SCHEMA become
|
|
12
|
+
* the art kit and the room schema: by path for a game inside this repository, through the
|
|
13
|
+
* sci2-ts package for one outside it. `.tmpl` files lose the suffix (they aren't type
|
|
14
|
+
* checked where they stand). `refs` overrides that choice. Returns the game's folder.
|
|
15
|
+
*/
|
|
16
|
+
export function newGame(target: string, refs?: "path" | "package"): string {
|
|
17
|
+
const name = basename(resolve(target));
|
|
18
|
+
if (!/^[a-z][a-z0-9-]*$/.test(name)) throw new GameBuildError(`${name}: a game's name is lower-case letters, digits and dashes, starting with a letter`);
|
|
19
|
+
if (existsSync(target) && readdirSync(target).some((f) => f === "scripts" || f === "rooms")) throw new GameBuildError(`${target} is already there`);
|
|
20
|
+
const inside = refs ? refs === "path" : !relative(ROOT, resolve(target)).startsWith("..");
|
|
21
|
+
const slash = (p: string) => p.replaceAll("\\", "/");
|
|
22
|
+
const kit = inside ? slash(relative(resolve(target), join(ROOT, "tools/game/kit.ts"))) : "sci2-ts/kit";
|
|
23
|
+
const schema = inside
|
|
24
|
+
? slash(relative(join(resolve(target), "rooms"), join(ROOT, "packages/content/room.schema.json")))
|
|
25
|
+
: "../node_modules/sci2-ts/packages/content/room.schema.json";
|
|
26
|
+
const Name = name.replace(/(^|-)([a-z])/g, (_, __, c: string) => c.toUpperCase());
|
|
27
|
+
const fill = (text: string) =>
|
|
28
|
+
text.replaceAll('"KIT"', JSON.stringify(kit)).replaceAll("SCHEMA", schema).replaceAll("NAME", name).replaceAll("Name", Name);
|
|
29
|
+
const copy = (from: string, to: string) => {
|
|
30
|
+
mkdirSync(to, { recursive: true });
|
|
31
|
+
for (const entry of readdirSync(from, { withFileTypes: true })) {
|
|
32
|
+
if (entry.isDirectory()) copy(join(from, entry.name), join(to, entry.name));
|
|
33
|
+
else writeFileSync(join(to, entry.name.replace(/\.tmpl$/, "")), fill(readFileSync(join(from, entry.name), "utf8")));
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
copy(TEMPLATE, target);
|
|
37
|
+
return target;
|
|
38
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { Target } from "../../packages/content/src/index.ts";
|
|
2
|
+
/**
|
|
3
|
+
* The class library (lib/) as a compile target for rooms written as YAML and Yarn
|
|
4
|
+
* (packages/content). Global numbers depend on the game's script 0, so the target is made
|
|
5
|
+
* for each build from the compiled globals' names.
|
|
6
|
+
*/
|
|
7
|
+
export declare function libraryTarget(globals: readonly string[]): Target;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The class library (lib/) as a compile target for rooms written as YAML and Yarn
|
|
3
|
+
* (packages/content). Global numbers depend on the game's script 0, so the target is made
|
|
4
|
+
* for each build from the compiled globals' names.
|
|
5
|
+
*/
|
|
6
|
+
export function libraryTarget(globals) {
|
|
7
|
+
const g = (name) => {
|
|
8
|
+
const n = globals.indexOf(name);
|
|
9
|
+
if (n < 0)
|
|
10
|
+
throw new Error(`the library's global ${name} isn't there: is script 0 compiled with the library?`);
|
|
11
|
+
return n;
|
|
12
|
+
};
|
|
13
|
+
return {
|
|
14
|
+
roomClass: "Room",
|
|
15
|
+
roomDefaults: {},
|
|
16
|
+
globals: {
|
|
17
|
+
ego: g("ego"),
|
|
18
|
+
game: g("game"),
|
|
19
|
+
curRoom: g("curRoom"),
|
|
20
|
+
messager: g("messager"),
|
|
21
|
+
narratorObject: g("narrator"),
|
|
22
|
+
music: g("music"),
|
|
23
|
+
sound: g("sfx"),
|
|
24
|
+
},
|
|
25
|
+
// As in lib/system.sh.
|
|
26
|
+
narrator: 99,
|
|
27
|
+
heroTalker: 98,
|
|
28
|
+
firstRoomTalker: 200,
|
|
29
|
+
voice: { class: "Talker", props: {} },
|
|
30
|
+
// Portraits stand at the top left, the text beside them.
|
|
31
|
+
portrait: { class: "PortraitTalker", props: {}, at: [36, 70], frameSignal: 0, partSignal: 0 },
|
|
32
|
+
teller: { class: "Teller", props: {}, verb: 2 },
|
|
33
|
+
forwardCycle: "Forward",
|
|
34
|
+
// room.enter lines: a verb the player can't use.
|
|
35
|
+
narrationVerb: 0,
|
|
36
|
+
verbs: { look: 1, talk: 2, walk: 3, do: 4 },
|
|
37
|
+
messageVersion: 4321,
|
|
38
|
+
// SetFlag, ClearFlag and IsFlag: script 999's exports 0, 1 and 2.
|
|
39
|
+
flags: { script: 999, set: 0, clear: 1, test: 2, first: 0, last: 1023 },
|
|
40
|
+
};
|
|
41
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import type { Target } from "../../packages/content/src/index.ts";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* The class library (lib/) as a compile target for rooms written as YAML and Yarn
|
|
5
|
+
* (packages/content). Global numbers depend on the game's script 0, so the target is made
|
|
6
|
+
* for each build from the compiled globals' names.
|
|
7
|
+
*/
|
|
8
|
+
export function libraryTarget(globals: readonly string[]): Target {
|
|
9
|
+
const g = (name: string) => {
|
|
10
|
+
const n = globals.indexOf(name);
|
|
11
|
+
if (n < 0) throw new Error(`the library's global ${name} isn't there: is script 0 compiled with the library?`);
|
|
12
|
+
return n;
|
|
13
|
+
};
|
|
14
|
+
return {
|
|
15
|
+
roomClass: "Room",
|
|
16
|
+
roomDefaults: {},
|
|
17
|
+
globals: {
|
|
18
|
+
ego: g("ego"),
|
|
19
|
+
game: g("game"),
|
|
20
|
+
curRoom: g("curRoom"),
|
|
21
|
+
messager: g("messager"),
|
|
22
|
+
narratorObject: g("narrator"),
|
|
23
|
+
music: g("music"),
|
|
24
|
+
sound: g("sfx"),
|
|
25
|
+
},
|
|
26
|
+
// As in lib/system.sh.
|
|
27
|
+
narrator: 99,
|
|
28
|
+
heroTalker: 98,
|
|
29
|
+
firstRoomTalker: 200,
|
|
30
|
+
voice: { class: "Talker", props: {} },
|
|
31
|
+
// Portraits stand at the top left, the text beside them.
|
|
32
|
+
portrait: { class: "PortraitTalker", props: {}, at: [36, 70], frameSignal: 0, partSignal: 0 },
|
|
33
|
+
teller: { class: "Teller", props: {}, verb: 2 },
|
|
34
|
+
forwardCycle: "Forward",
|
|
35
|
+
// room.enter lines: a verb the player can't use.
|
|
36
|
+
narrationVerb: 0,
|
|
37
|
+
verbs: { look: 1, talk: 2, walk: 3, do: 4 },
|
|
38
|
+
messageVersion: 4321,
|
|
39
|
+
// SetFlag, ClearFlag and IsFlag: script 999's exports 0, 1 and 2.
|
|
40
|
+
flags: { script: 999, set: 0, clear: 1, test: 2, first: 0, last: 1023 },
|
|
41
|
+
};
|
|
42
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { Colour, ResourceType, basePalette, cube, writePic, writeView, type ResourceData, type ViewFile } from "KIT";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Placeholder art, drawn here: the room (picture 100) and the hero (view 200: loop 0 east,
|
|
5
|
+
* 1 west, 2 south, 3 north). Replace it with your own: draw it here, or see the docs.
|
|
6
|
+
*/
|
|
7
|
+
export default function resources(): ResourceData[] {
|
|
8
|
+
return [
|
|
9
|
+
{ type: ResourceType.Pic, number: 100, data: writePic(room()) },
|
|
10
|
+
{ type: ResourceType.View, number: 200, data: writeView(hero()) },
|
|
11
|
+
];
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const W = 320, H = 200;
|
|
15
|
+
|
|
16
|
+
function room() {
|
|
17
|
+
const pixels = new Uint8Array(W * H);
|
|
18
|
+
for (let y = 0; y < H; y++) pixels.fill(y < 150 ? cube(204, 204, 153) : cube(153, 102, 51), y * W, (y + 1) * W);
|
|
19
|
+
// A window.
|
|
20
|
+
for (let y = 40; y <= 100; y++) for (let x = 130; x <= 190; x++) pixels[y * W + x] = x === 130 || x === 190 || y === 40 || y === 100 || x === 160 || y === 70 ? cube(102, 51, 0) : cube(153, 204, 255);
|
|
21
|
+
return {
|
|
22
|
+
resolution: [W, H] as [number, number],
|
|
23
|
+
cels: [{ width: W, height: H, displaceX: 0, displaceY: 0, skipColor: Colour.Transparent, pixels, priority: 0, x: 0, y: 0, unknown16: 0 }],
|
|
24
|
+
palette: basePalette(),
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/** A figure 9 pixels wide; its legs move in cels 1 and 3. */
|
|
29
|
+
function hero(): ViewFile {
|
|
30
|
+
const colours: Record<string, number> = { H: cube(51, 51, 51), S: cube(255, 204, 153), C: cube(51, 102, 153), L: cube(51, 51, 51) };
|
|
31
|
+
const body = ["..HHHHH..", "..SSSSS..", "..SSSSS..", "...SSS...", "..CCCCC..", ".CCCCCCC.", ".CCCCCCC.", ".SCCCCCS.", "..CCCCC.."];
|
|
32
|
+
const legs = [["..LL.LL..", "..LL.LL..", "..LL.LL.."], [".LL...LL.", ".LL...LL.", "LL.....LL"], ["..LL.LL..", "..LL.LL..", "..LL.LL.."], ["...LLL...", "...LLL...", "...LLL..."]];
|
|
33
|
+
const cels = legs.map((l) => {
|
|
34
|
+
const rows = [...body, ...l];
|
|
35
|
+
const pixels = Uint8Array.from(rows.join(""), (c) => colours[c] ?? Colour.Transparent);
|
|
36
|
+
return { width: 9, height: rows.length, displaceX: 0, displaceY: 0, skipColor: Colour.Transparent, pixels };
|
|
37
|
+
});
|
|
38
|
+
return {
|
|
39
|
+
flags: 1,
|
|
40
|
+
loops: [{ link: -1, mirror: false, cels }, { link: 0, mirror: true, cels: [] }, { link: -1, mirror: false, cels }, { link: -1, mirror: false, cels }],
|
|
41
|
+
palette: undefined,
|
|
42
|
+
};
|
|
43
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# yaml-language-server: $schema=SCHEMA
|
|
2
|
+
# The first room. What's here and where you can walk; what's said is in 1.yarn.
|
|
3
|
+
room: 1
|
|
4
|
+
picture: 100
|
|
5
|
+
hero:
|
|
6
|
+
at: [60, 170]
|
|
7
|
+
walkable: [[0, 150], [319, 150], [319, 189], [0, 189]]
|
|
8
|
+
features:
|
|
9
|
+
window: { rect: [130, 40, 190, 100] }
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
title: room.enter
|
|
2
|
+
---
|
|
3
|
+
<<if not $started>>
|
|
4
|
+
You're here. Right-click for the next verb; click to use it.
|
|
5
|
+
<<set $started to true>>
|
|
6
|
+
<<endif>>
|
|
7
|
+
===
|
|
8
|
+
|
|
9
|
+
title: room.look
|
|
10
|
+
---
|
|
11
|
+
An empty room, waiting for a story.
|
|
12
|
+
===
|
|
13
|
+
|
|
14
|
+
title: window.look
|
|
15
|
+
---
|
|
16
|
+
Nothing out there yet.
|
|
17
|
+
===
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
;;; NAME: the game. It sets up, names the hero, and goes to the first room.
|
|
2
|
+
(script 0)
|
|
3
|
+
(include "system.sh")
|
|
4
|
+
|
|
5
|
+
(public NAME 0)
|
|
6
|
+
|
|
7
|
+
(class NameGame of Game
|
|
8
|
+
(method (init)
|
|
9
|
+
(super init:)
|
|
10
|
+
(= ego hero)
|
|
11
|
+
(= heroTalker heroVoice)
|
|
12
|
+
(self newRoom: 1)))
|
|
13
|
+
|
|
14
|
+
(instance NAME of NameGame)
|
|
15
|
+
|
|
16
|
+
(instance hero of Ego
|
|
17
|
+
(properties
|
|
18
|
+
view 200
|
|
19
|
+
xStep 2 yStep 1
|
|
20
|
+
cycleSpeed 8))
|
|
21
|
+
|
|
22
|
+
;; Who says the hero's lines (Hero: in Yarn).
|
|
23
|
+
(instance heroVoice of Talker
|
|
24
|
+
(properties name "You"))
|
package/tools/game.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/tools/game.js
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Games built from their own sources (see tools/game/build.ts):
|
|
3
|
+
*
|
|
4
|
+
* pnpm game build games/<name> [out dir] RESOURCE.MAP + RESOURCE.000, by default in
|
|
5
|
+
* out/games/<name>, and in src/ the assembly
|
|
6
|
+
* compiled from each .sc script
|
|
7
|
+
* pnpm game new <name> a new game in games/<name>, from tools/game/template:
|
|
8
|
+
* a room in YAML and Yarn, a hero, placeholder art
|
|
9
|
+
* pnpm game site games/<name> [out dir] a static site: the docs as pages and the game
|
|
10
|
+
* in the player (out/site by default; see
|
|
11
|
+
* tools/site/build.ts)
|
|
12
|
+
*
|
|
13
|
+
* Play one in the browser with SCI_GAME=out/games/<name> pnpm viewer (then /play.html), or
|
|
14
|
+
* headless with SCI_GAME=out/games/<name> pnpm play.
|
|
15
|
+
*/
|
|
16
|
+
import { mkdirSync, writeFileSync } from "node:fs";
|
|
17
|
+
import { basename, join, relative } from "node:path";
|
|
18
|
+
import { writeResourceArchive } from "../packages/sci/src/index.js";
|
|
19
|
+
import { GameBuildError, buildGame } from "./game/build.js";
|
|
20
|
+
import { newGame } from "./game/new.js";
|
|
21
|
+
import { buildSite } from "./site/build.js";
|
|
22
|
+
const [command, dir, outArg] = process.argv.slice(2);
|
|
23
|
+
if ((command !== "build" && command !== "site" && command !== "new") || !dir) {
|
|
24
|
+
console.error("usage: pnpm game build|site games/<name> [out dir], or pnpm game new <name>");
|
|
25
|
+
process.exit(2);
|
|
26
|
+
}
|
|
27
|
+
if (command === "new") {
|
|
28
|
+
try {
|
|
29
|
+
const target = newGame(join("games", basename(dir)));
|
|
30
|
+
console.log(`${target}: a room (rooms/1.room.yaml, 1.yarn), the game (scripts/0.sc) and placeholder art (resources.ts)`);
|
|
31
|
+
console.log(` pnpm game build ${target}, then SCI_GAME=out/${target} pnpm viewer`);
|
|
32
|
+
}
|
|
33
|
+
catch (e) {
|
|
34
|
+
console.error(e.message);
|
|
35
|
+
process.exit(1);
|
|
36
|
+
}
|
|
37
|
+
process.exit(0);
|
|
38
|
+
}
|
|
39
|
+
if (command === "site") {
|
|
40
|
+
const out = outArg ?? "out/site";
|
|
41
|
+
try {
|
|
42
|
+
const site = await buildSite(dir, out);
|
|
43
|
+
console.log(`${out}: ${site.pages} pages, ${site.game} in play/play.html${site.soundFont ? "" : " (no SoundFont in assets/soundfonts: music is silent)"}`);
|
|
44
|
+
}
|
|
45
|
+
catch (e) {
|
|
46
|
+
if (!(e instanceof GameBuildError))
|
|
47
|
+
throw e;
|
|
48
|
+
console.error(e.message);
|
|
49
|
+
process.exit(1);
|
|
50
|
+
}
|
|
51
|
+
process.exit(0);
|
|
52
|
+
}
|
|
53
|
+
try {
|
|
54
|
+
const game = await buildGame(dir);
|
|
55
|
+
const out = outArg ?? join("out/games", basename(dir));
|
|
56
|
+
const { map, volume } = writeResourceArchive(game.resources);
|
|
57
|
+
mkdirSync(out, { recursive: true });
|
|
58
|
+
writeFileSync(join(out, "RESOURCE.MAP"), map);
|
|
59
|
+
writeFileSync(join(out, "RESOURCE.000"), volume);
|
|
60
|
+
for (const [name, data] of Object.entries(game.files))
|
|
61
|
+
writeFileSync(join(out, name), data);
|
|
62
|
+
// What the compiler made of the .sc scripts, to read when something doesn't work.
|
|
63
|
+
if (game.generated.size) {
|
|
64
|
+
mkdirSync(join(out, "src"), { recursive: true });
|
|
65
|
+
for (const [n, text] of game.generated)
|
|
66
|
+
writeFileSync(join(out, "src", `${n}.sca`), text);
|
|
67
|
+
}
|
|
68
|
+
for (const w of game.warnings)
|
|
69
|
+
console.warn(`warning: ${w}`);
|
|
70
|
+
console.log(`${relative(process.cwd(), out) || "."}: ${game.resources.length} resources, ${game.selectors.length} selectors, ${game.classes.size} classes`);
|
|
71
|
+
}
|
|
72
|
+
catch (e) {
|
|
73
|
+
if (!(e instanceof GameBuildError))
|
|
74
|
+
throw e;
|
|
75
|
+
console.error(e.message);
|
|
76
|
+
process.exit(1);
|
|
77
|
+
}
|
package/tools/game.ts
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Games built from their own sources (see tools/game/build.ts):
|
|
3
|
+
*
|
|
4
|
+
* pnpm game build games/<name> [out dir] RESOURCE.MAP + RESOURCE.000, by default in
|
|
5
|
+
* out/games/<name>, and in src/ the assembly
|
|
6
|
+
* compiled from each .sc script
|
|
7
|
+
* pnpm game new <name> a new game in games/<name>, from tools/game/template:
|
|
8
|
+
* a room in YAML and Yarn, a hero, placeholder art
|
|
9
|
+
* pnpm game site games/<name> [out dir] a static site: the docs as pages and the game
|
|
10
|
+
* in the player (out/site by default; see
|
|
11
|
+
* tools/site/build.ts)
|
|
12
|
+
*
|
|
13
|
+
* Play one in the browser with SCI_GAME=out/games/<name> pnpm viewer (then /play.html), or
|
|
14
|
+
* headless with SCI_GAME=out/games/<name> pnpm play.
|
|
15
|
+
*/
|
|
16
|
+
import { mkdirSync, writeFileSync } from "node:fs";
|
|
17
|
+
import { basename, join, relative } from "node:path";
|
|
18
|
+
import { writeResourceArchive } from "../packages/sci/src/index.ts";
|
|
19
|
+
import { GameBuildError, buildGame } from "./game/build.ts";
|
|
20
|
+
import { newGame } from "./game/new.ts";
|
|
21
|
+
import { buildSite } from "./site/build.ts";
|
|
22
|
+
|
|
23
|
+
const [command, dir, outArg] = process.argv.slice(2);
|
|
24
|
+
if ((command !== "build" && command !== "site" && command !== "new") || !dir) {
|
|
25
|
+
console.error("usage: pnpm game build|site games/<name> [out dir], or pnpm game new <name>");
|
|
26
|
+
process.exit(2);
|
|
27
|
+
}
|
|
28
|
+
if (command === "new") {
|
|
29
|
+
try {
|
|
30
|
+
const target = newGame(join("games", basename(dir)));
|
|
31
|
+
console.log(`${target}: a room (rooms/1.room.yaml, 1.yarn), the game (scripts/0.sc) and placeholder art (resources.ts)`);
|
|
32
|
+
console.log(` pnpm game build ${target}, then SCI_GAME=out/${target} pnpm viewer`);
|
|
33
|
+
} catch (e) {
|
|
34
|
+
console.error((e as Error).message);
|
|
35
|
+
process.exit(1);
|
|
36
|
+
}
|
|
37
|
+
process.exit(0);
|
|
38
|
+
}
|
|
39
|
+
if (command === "site") {
|
|
40
|
+
const out = outArg ?? "out/site";
|
|
41
|
+
try {
|
|
42
|
+
const site = await buildSite(dir, out);
|
|
43
|
+
console.log(`${out}: ${site.pages} pages, ${site.game} in play/play.html${site.soundFont ? "" : " (no SoundFont in assets/soundfonts: music is silent)"}`);
|
|
44
|
+
} catch (e) {
|
|
45
|
+
if (!(e instanceof GameBuildError)) throw e;
|
|
46
|
+
console.error(e.message);
|
|
47
|
+
process.exit(1);
|
|
48
|
+
}
|
|
49
|
+
process.exit(0);
|
|
50
|
+
}
|
|
51
|
+
try {
|
|
52
|
+
const game = await buildGame(dir);
|
|
53
|
+
const out = outArg ?? join("out/games", basename(dir));
|
|
54
|
+
const { map, volume } = writeResourceArchive(game.resources);
|
|
55
|
+
mkdirSync(out, { recursive: true });
|
|
56
|
+
writeFileSync(join(out, "RESOURCE.MAP"), map);
|
|
57
|
+
writeFileSync(join(out, "RESOURCE.000"), volume);
|
|
58
|
+
for (const [name, data] of Object.entries(game.files)) writeFileSync(join(out, name), data);
|
|
59
|
+
// What the compiler made of the .sc scripts, to read when something doesn't work.
|
|
60
|
+
if (game.generated.size) {
|
|
61
|
+
mkdirSync(join(out, "src"), { recursive: true });
|
|
62
|
+
for (const [n, text] of game.generated) writeFileSync(join(out, "src", `${n}.sca`), text);
|
|
63
|
+
}
|
|
64
|
+
for (const w of game.warnings) console.warn(`warning: ${w}`);
|
|
65
|
+
console.log(`${relative(process.cwd(), out) || "."}: ${game.resources.length} resources, ${game.selectors.length} selectors, ${game.classes.size} classes`);
|
|
66
|
+
} catch (e) {
|
|
67
|
+
if (!(e instanceof GameBuildError)) throw e;
|
|
68
|
+
console.error(e.message);
|
|
69
|
+
process.exit(1);
|
|
70
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { type ModTarget } from "./mod-target.ts";
|
|
2
|
+
import { ResourceType, type AsmContext, type ResourceManager, type ScriptWorld } from "../packages/sci/src/index.ts";
|
|
3
|
+
export interface BuiltResource {
|
|
4
|
+
type: ResourceType;
|
|
5
|
+
number: number;
|
|
6
|
+
data: Uint8Array;
|
|
7
|
+
}
|
|
8
|
+
/** Message file text with each record annotated: verb name, and the room objects using the noun. */
|
|
9
|
+
export declare function dumpMessages(rm: ResourceManager, world: ScriptWorld, n: number): Promise<string>;
|
|
10
|
+
/**
|
|
11
|
+
* Builds a mod directory: <n>.sca / <n>.msg are whole new files (a new room);
|
|
12
|
+
* <n>.sca.diff / <n>.msg.diff change the game's own, applied to fresh dumps with `patch`;
|
|
13
|
+
* <n>.png (+ <n>.layer-<priority>.png) is a room picture; *.view.json is a view;
|
|
14
|
+
* <n>.room.yaml (+ <n>.yarn) is a room described as data, compiled to <n>.sca and <n>.msg
|
|
15
|
+
* (@sci-ts/content). `generated` receives that compiled text, for reading. Their Yarn
|
|
16
|
+
* variables are flags numbered in the mod's flags.yaml (see modFlags). Rooms are compiled for
|
|
17
|
+
* the game named in the mod's mod.yaml (see tools/mod-target.ts).
|
|
18
|
+
*/
|
|
19
|
+
export declare function buildMod(modDir: string, rm: ResourceManager, world: ScriptWorld, ctx: AsmContext, generated?: (file: string, text: string) => void): Promise<BuiltResource[]>;
|
|
20
|
+
/**
|
|
21
|
+
* A mod's flags.yaml: Yarn variable -> flag number. Saved games store flags by number, so
|
|
22
|
+
* a name keeps its number once given: new names get the next free one (the build adds them
|
|
23
|
+
* to the file; commit it with the mod). `$game<n>` is the game's own flag n.
|
|
24
|
+
*/
|
|
25
|
+
export declare function modFlags(modDir: string, target: ModTarget): {
|
|
26
|
+
number: (name: string) => number;
|
|
27
|
+
save: () => void;
|
|
28
|
+
};
|