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