chiark / gitweb /
Shape library documentation editing
[otter.git] / README.md
1 OTTER - ONLINE TABLE TOP ENVIRONMENT RENDERER
2 =============================================
3
4 Otter is an online "table simulator" intended to be suitable for board
5 games and similar.
6
7 It is accessed from a web browser running JavaScript.  The server runs
8 on a convenationl Unix host.  Currently, joining a game requires a
9 unix shell account on the server.
10
11 I expect it to be used with a concurrent voice chat.
12
13 The game server does not currently have a built-in text chat system.
14 The game organiser can use the game server to distribute (and update)
15 voice chat and info links.
16
17 Right now Otter is in an alpha state.
18
19
20 JOINING A GAME
21 ==============
22
23 In the simplest case:
24 ```
25   otter join-game unix:<user>::<game-name>
26 ```
27 e.g.
28 ```
29   otter join-game unix:ijackson::test
30 ```
31
32 See `otter --help` for further options, including setting your nick.
33
34 Currently when a new player joins a game (with the `otter` command),
35 all the other players must reload the page.
36
37
38 CREATING A GAME
39 ===============
40
41 ```
42 otter reset --reset-table local-users :test demo
43                          /^^^^^^^^^^^  ^^^\ ^^^^'~ game spec
44                          `table spec       game name
45 ```
46
47 Here `local-users` refers to the file `local-users.table.spec` in the
48 Otter specs directory (`/volatile/Otter/specs` on chiark).  The table
49 spec file handles access control (and some other global properties)
50 This particular file says that all local shell account users may join
51 the game.
52
53 `:test` is the game name.  It starts with a colon, which means
54 implicitly `unix:<whoami>::test`.  Other people have to name the game
55 with the full name, with all three colons in it.
56
57 `demo` refers to the file `demo.game.spec`.  The "game spec" says what
58 shape table is and what pieces there are.  This is a simple demo game.
59 There is also `penultima` which is a work-in-progress set of pieces
60 suitable for fairy chess etc.
61
62 See `otter --help` for some more options.
63
64 Currently, resetting a game (or otherwise adding or removing pieces)
65 will mean all the players will get errors until they reload the page.
66
67
68 MAKING YOUR OWN GAME
69 ====================
70
71 If you want to use existing piece shapes that Otter already knows
72 about, you can do this by providing a `<something>.game.toml` file.
73 The format of these files is a TOML document representing a GameSpec
74 as found in `src/spec.rs` in the Otter source code.
75
76 todo: use rustdoc to provide this somewhere.
77
78
79 ADDING SHAPES
80 =============
81
82 Otter uses SVGs.  The sources for the SVGs are all in the otter source
83 tree, in the `library/` directory.
84
85 Each shape is listed in one of the `library/*.toml` files, in a
86 `files` entry.  Unfortunately the syntax and semantics of this file
87 are not yet properly documented.
88
89 You can preview the shapes, including any changes you make, without a
90 whole game server, by running `make -j8 shapelib`, and looking at
91 `templates/shapelib.html`.  (See BUILDING AND TESTING for information
92 about how to install the tools you will need.)
93
94 Some of these SVGs were scraped from Wikimedia.  The scraper machinery
95 can perhaps be adapted to scrape SVGs from elsewhere.
96
97 You can also add your own SVGs in the library/edited/ directory.
98 If you do that, please make sure to include the actual source code.
99 If you copied or adapted an SVG from somewhere, provide details.
100
101 Contributions should be via git branch, eg a merge request on Salsa:
102 [https://salsa.debian.org/iwj/otter](https://salsa.debian.org/iwj/otter)
103
104 NB that shapes must come with a licence compatible with CC-BY-SA 4.0.
105 See `LICENCE` for more information about copyright status.
106
107
108 BUILDING AND TESTING
109 ====================
110
111 You will need at 6000 megabytes of disk space, or more, and a good
112 internet connection.  Your computer will be compiling a lot of code.
113
114 These instructions have been tested on Debian buster.
115
116
117 Setup
118 -----
119
120 1. 
121 ```
122      sudo apt install build-essential cpio git curl     \
123                       pkg-config libssl-dev             \
124                       node-typescript inkscape
125 ```
126
127 2. Install Rust.  This is most easily done with rustup:
128
129 ```
130      curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
131 ```
132
133    and then follow the instructions about your `PATH`.  If this rune
134    alarms you, see below about Rust privsep.
135
136 3. Switch your Rust install to use Rust Nightly and add the WASM
137    target:
138
139 ```
140      rustup default nightly
141      rustup target add wasm32-unknown-unknown
142 ```
143
144    Unfortunately, it is possible that the Rust nightly you find when
145    you run this is missing some pieces.  The following is known to
146    work (with otter from the time of writing):
147 ```
148      rustup default nightly-2020-11-09
149 ```
150
151
152 ** If you just want to edit and preview the shape libraries
153    (ie the piece shapes) you can stop here **
154
155
156 4. Install some build tools:
157
158 ```
159      cargo install usvg
160      cargo install bundle-sources
161 ```
162
163    This will put them in `~/.cargo/bin`, which you presumably have on
164    your PATH (or the above `rustup` and `cargo` runes wouldn't work).
165
166 5. Install the version of wasm-pack with the option I need (upstream
167    haven't reviewed my merge request):
168
169 ```
170      git clone https://github.com/ijackson/wasm-pack.git -b cargo-opts
171      cd wasm-pack
172      cargo install
173 ```
174
175   NB that wasm-pack will itself download and install more stuff when
176   it is run by the Otter Makefile.
177
178
179 Build
180 -----
181
182 ```
183      git clone https://salsa.debian.org/iwj/otter
184      cd otter
185      make -j8 all bundled-sources
186 ```
187
188 Or if you just want to edit the piece libraries:
189
190 ```
191     make -j8 shapelib
192 ```
193 And then open ./templates/shapelib.html in your browser
194
195
196 Ad-hoc tests
197 ------------
198
199 In one shell:
200
201 ```
202      target/debug/daemon-otter server-test.toml
203 ```
204
205 The server does not daemonise, and the default config there makes it
206 quite verbose.  So, in another shell:
207
208 ```
209     target/debug/otter                                               \
210         --account server: --config server-test.toml --spec-dir=specs \
211         reset --reset-table test server::test demo
212
213     target/debug/otter                                               \
214         --account server: --config server-test.toml --spec-dir=specs \
215         join-game server::test
216 ```
217
218 The URL printed can then be visited in a local browser.
219
220
221 Resetting/restoring things after tests, updating server, etc.
222 -------------------------------------------------------------
223
224 After the server is updated, you can just `^C` and restart it.  Games
225 are constantly saved (although there is an up-to-1s lag on the most
226 frequently udpated game state).
227
228 If you want to clear out the server state, delete the files `[ag]-*`
229 and `accounts`.  NB that you should do this with the server not
230 running, because the server has most of that information in memory and
231 will like to write it out again.
232
233 If you update Typescript (JS code) you will need to rerun `make` to
234 rebuild the JS output.
235
236 Apart from that, if you update JS or WASM code or Tera templates, you
237 do not need to restart the server - it will pick up changes
238 automatically.
239
240 When testing, you do not need to `make bundled-sources` more than
241 once, at the beginning.  So don't, because it's slow.  But you
242 definitely should run it for every update if you make a deployment for
243 other people to use.  Otherwise you might be running a privately
244 modified server without offering your users its source code.  See
245 LICENCE.
246
247 If you Do Something to the output from cargo, you should `rm stamp/*`,
248 since the `Makefile` won't notice, otherwise, that, the relevant cargo
249 rune(s) need to be re-run.  Needlessly deleting all the stamp files
250 wastes only a handful of seconds (on my stupidly fast laptop).
251
252
253 Navigating the otter source code
254 --------------------------------
255
256 * `src/`
257
258   The main Rust source code.  This is mixture of code used only or
259   mainly by the server and code used by the `otter` command line
260   utility; these aren't split up in a wholly principled way.  In Rust
261   terms this is a "library crate".
262
263 * `src/bin/*.rs`
264
265   Support executables, including in particular the command line
266   utility `otter` which is used to set up and join games.
267
268 * `daemon/`
269
270   The Otter server.  This is a simple binary crare.  Much
271   functionality belonging primarily, or only, to the server, is in
272   `src/`, simply because it was easier not to disentangle it.
273   Anything that needs Rocket (the web framework) is in `daemon/`.
274
275 * `zcoord/`
276
277   Code shared by the host and the WebAssembly.  Notably, the Z
278   coordinate handling, but also a a few other minor functions needed
279   by both client and server.  To avoid duplicating them are written
280   once in Rust and compiled twice - once for the host and once for
281   WebAssembly for use in the client.  This crate is kept minimal to
282   keeep the WebAssembly binary small.
283
284 * `wasm/`
285
286   WebAssembly/Rust bindings for the items in `zcoord/`.  Produces the
287   single wasm file for use by the JavaScript, and corresponding
288   Typescript annotations etc.
289
290 * `templates/script.ts`
291
292   The main Typescript (typed Javascript) code.  Otter's web
293   compatibility target is the earliest browser versions that properly
294   support WebAssembly.
295
296 * `templates/session.tera`, `macros.tera`, etc.
297
298   Tera templates generating the main HTML screen.  These templates are
299   filled in from structs in the Rust source code.  The main files are
300   `session.tera` (portrait), `landscape.tera`, and `macros.tera`
301   (common), and their rendering uses an instance of
302   `SessionRenderContext` from `src/session.rs`.
303
304 * `nwtemplates/`
305
306   "Non-web templataes".  Tera templates for things other than web
307   pages.  Currently this includes the server's outgoing emails.  These
308   have to be in a separate directory because Rocket likes to load
309   everything applicable it finds in its own `templates/` directory.
310   These are used via `src/nwtemplates.rs`.
311
312 * `wdriver.rs`, `wdriver/`
313
314   WebDriver-based end-to-end tests.  Each `wdt-*.rs` is one test
315   utility.  `wdriver.rs` (in the top level to evade Cargo's
316   dur-brained search rules) is the library for these, and contains
317   most of the heavy lifting.
318
319   These are not standard Rust `#[test]` tests because they need to
320   reinvoke themselves via `bwrap` for test isolation reasons, and
321   because their dependencies are extensive and not properly capturable
322   in Cargo.  They are run by `make check`.
323
324 * `library/`: The shape libraries.
325
326   The program `./media-scraper` (which is not run by the `Makefile`)
327   reads `library/*.toml` for instructions and generates `files.make`
328   fragments.  These fragments arrange to run `./usvg-processor` which
329   launders SVGs through `usvg`.  `usvg-processor`.
330
331   The shape libraries have a different, more relaxed, copyright
332   licence.
333
334
335 Automatic in-browser tests
336 --------------------------
337
338 * `apt install firefox`
339
340 * `https://github.com/mozilla/geckodriver/releases/tag/v0.28.0`
341   download appropriate tarball, put "geckodriver" on PATH
342
343 `make check` runs all the tests; `make wdt` runs only those tests.  You can run
344 an individual test with a rune like this:
345
346 ```
347   OTTER_WDT_LOG=otter_webdriver_tests=trace CARGO_MANIFEST_DIR=~ian/Rustup/Game/server time target/debug/wdt-simple --geckodriver-args=
348 ```
349
350 (This rune has some example logging options in it, for you to change
351 if you like. You can omit the `CARGO_MANIFEST_DIR` for an in-tree
352 non-privsep build.)  After a test has run, you can find screenshots,
353 etc. in `tmp/wdt-simple` or whatever.  You can restart the same game
354 server setup as the test used, with the state left by the test, with a
355 rune like this:
356
357 ```
358   target/debug/daemon-otter tmp/wdt-simple/server-config.toml
359 ```
360 and then play with it at this url:
361 ```
362   http://localhost:8000/?kmqAKPwK4TfReFjMor8MJhdRPBcwIBpe
363 ```
364
365
366 Rust, cargo, curl|bash-ware; privsep
367 ------------------------------------
368
369 If you follow the above instructions you will have downloaded and
370 executed - and, therefore, trusted:
371
372  * Various Debian packages - safe
373  * Rustup (the Rust downloader/installer) - this is pretty safe
374  * Rust itself - again, pretty safe
375  * Otter itself - well, I wrote this; up to you.
376  * My branch of wasm-pack - I haven't audited what I started with.
377  * 300 transitive dependencies of otter (from crates.io)
378  * 50 transitive dependencies of bundle-sources
379  * the transitive dependencies of resvg
380  * god knows how many transitive dependencies of wasm-pack
381  * a geckodriver binary directly from mozilla
382  * whatever wasm-pack downloads at runtime (mostly(?) via cargo)
383
384 You will have trusted the integrity of the following:
385
386  * The Debian archive (via its apt keyring) (very good)
387  * Rustup's and Rust's TLS keyholders (good, I think)
388  * The HTTP TLS cabal (sigh)
389  * github (pretty good in practice)
390  * whatever mozilla do to make binaries, in particular geckodriver
391  * crates.io (extremely poor traceability)
392  * the project management of hundreds of random crates.io libraries
393
394 If this makes you uncomfortable, as it should, you may wish to
395 consider running everything in a separate shell account, or a VM or
396 container of some kind.
397
398 (I have a not-properly-released tool called "nailing-cargo" which
399 makes it possible to do most things in my main account but run the
400 Rust stuff in a separate less-privileged account.  There is support
401 for this in the Makefile.  But if you want to run *everything* in the
402 lesser account, you don't need to bother with that.)
403
404
405 Dependencies - apologia
406 -----------------------
407
408  * Rust Nightly
409
410    This is needed almost solely because Rocket needs it.  Rocket is
411    the web framework I am using.  The next version of Rocket (0.5.x),
412    which is in development, will not need Nightly, but it will also be
413    a serious compatibility break.  The existing Rocket (0.4.x) will
414    almost certainly never be ported to Stable Rust.  When Rocket 0.5.x
415    is out, porting Otter to it will go on my list - but it won't be
416    trivial.  Sorry.
417
418  * The many dependencies of Otter
419
420    These are partly because Rocket is a large piece of software with
421    much functionality.  But also because I favoured my own programming
422    convenience and in some cases was experimenting with different
423    approaches.  In practice, it seems to me that once I'm using Rocket
424    and WASM utilities and resvg and so on, there is not that much to
425    be gained by trying to prune the dependencies of the otter package
426    itself.
427
428  * wasm-pack
429
430    This is a wrapper program for various utilities for manipulating
431    WebAssembly files, and their Typescript and Javascript glue, etc.
432    It likes to run cargo and do god knows what.  I'm not sure it's
433    buying me much over whatever things it runs, so ideally it would be
434    best to replace this with calls to the underlying utilities and
435    libraries.  But there are some wrinkles, for example, some version
436    coupling requirements that wasm-pack takes care of.  And to be
437    honest, I'm not sure precisely what it does and understanding that
438    would be a necessary first step to reproducing it in the Makefile.
439
440  * bundle-rust-sources
441
442    This is mine, but it needs to be properly released.
443
444  * geckodriver (for the automated in-browser tests)
445
446    This is done with a protocol called "WebDriver" which is a
447    cross-browser way to puppet a browser.  There is a thing called
448    "geckodriver" which converts that to a firefox-specific protocol
449    for the same purpose, called "Marionette".  (In practice all this
450    seems to have lots of bugs and misfeatures.)
451
452    AFAICT the usual approach for using geckodriver to have it *bind to
453    a fixed TCP port accessible to all local programs*.  My wrapper
454    tooling arranges to run this in an ephemeral $HOME and a private
455    network namespace.
456
457    AFAICT the only practical way to get geckodriver is to download the
458    binary.  I got mine here:
459      https://github.com/mozilla/geckodriver/releases/tag/v0.28.0 You
460    You just dump the binary on your PATH.
461
462
463 Final weirdness
464 ---------------
465
466  * For running on chiark I build with the Rust target
467    `x86_64-unknown-linux-musl` which on my system is configured to
468    produce a completely statically linked bionary.  I have this in my
469    `~/.cargo/config` (in the lesser privsep account):
470
471 ```
472 [target.x86_64-unknown-linux-musl]
473 rustflags = ["-C", "target-feature=+crt-static"]
474 # ^ from https://stackoverflow.com/questions/31770604/how-to-generate-statically-linked-executables
475 ```