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