xrxs/README.md

109 lines
7.6 KiB
Markdown
Raw Permalink Normal View History

2021-07-01 07:45:48 +00:00
# xrxs
`xrxs` is an experimental game server using the Plan 9 protocol `9p`.
2021-10-16 06:40:33 +00:00
The client is a specialized [uxn](https://wiki.xxiivv.com/site/uxn.html) ROM that can load other ROMs over the network via the `9p` service.
2021-07-01 07:45:48 +00:00
## design
This is the working structure of the 9p filesystem:
2021-10-17 23:44:27 +00:00
* `/ctl`: Read/write control file for inputing system commands. Reading the file shows the status of the last input command: 1 for success, 0 for failure; `logout` is a special case, and the status code will be -1 if it was succesful. the following are valid command syntax:
* `login PW`: Authenticate with `xrxs` -- password is hashed against realm password hash.
* `logout`: Gracefully remove yourself from the users table.
* `load CART`: Load a cartridge.
* `chunk TYPE N`: Load data of type TYPE and chunk number N.
* `create REALM`: Create a new realm (start a new game) -- must have a cartridge loaded
* `protect PW`: Protect the curent realm with a password if you are the master.
* `transfer USER`: Transfer ownership of the realm to another user.
* `delete REALM`: Delete the realm off the server if you are the master and it is empty.
* `enter REALM`: Join an existing realm.
* `leave`: Leave the current realm.
* `unload`: Unload the cartridge.
2021-07-01 07:45:48 +00:00
* `/users`: Read-only; Self and others in the realm are readable from here, one per line. It contains only yourself before joining a realm. Your username on your machine is used as your username in `xrxs` -- if your name is taken, you will get an error on attaching.
2021-07-19 21:42:46 +00:00
* `/carts`: Available game/app cartridges for this server, read only; Carts are listed per line upon reading the file. It is backed by files on the server in a directory structure like `carts/CART_NAME/{CART_NAME.rom, data/, realms/}`.
2021-07-01 07:45:48 +00:00
* `/slot`: After loading the cartridge, its ROM is read from here; Read-only.
* `/data/`: Any supporting data that comes with the cartridge will be found here; They are in three parts: `sprite`, `audio`, and `text`. While `uxn` has the ability to seek through a file up to 4GB in size, it can be beneficial to separate game assets into discrete files. The `chunk` command should be used to page different files into the service when needed. The files on the server should be like `TYPEN` where `TYPE` is one of `sprite`, `audio`, and `text`, and `N` is any sequence of characters (canonically a nonnegative integer). When first loading the cartridge, `N == 0`. Issuing the command `chunk TYPE XXX` will attempt to load data from file `carts/CART_NAME/data/TYPEXXX` into the correct data file. If `TYPE` is not one of `sprite`, `audio`, or `text`, or the file `TYPEXXX` doesn't exist in the data directory, the `chunk` command does nothing.
2021-07-01 07:45:48 +00:00
2021-07-19 21:42:46 +00:00
* `/realms`: Open/saved realms, read-only. Realms and their associated universe are backed by real files on the server so that they can be preserved across service instantiations, in a directory structure like: `carts/CART_NAME/realms/REALM_NAME/{realm, universe}`. Realms can either be solo, open, or protected; Open or protected realms can have limited member numbers. Depending on the cartridge, these settings can be user-managed or managed by the cartridge itself. Realms are listed per line upon reading the file like: `REALM_NAME 1 4 1`. First would obviously be the name of the realm. The first number is number of members, second is member limit, third is 1 if protected, 0 if not. `0 1 1` represents a protected solo realm that is empty (saved game with password). `0 1 0` represents an unprotected solo realm that is empty (saved game with no password).
2021-07-01 07:45:48 +00:00
* `/universe`: Write here to update serverside state for this cart/realm; Read from here to get the complete current state. This is backed by a key-value-pair list on the server.
* `/scope`: Write here to tell the server the names of the `Atom`s (key/value pair of a `Universe`) you're interested in (one per line), and read from here to retrieve their values (one per line). In many cases this will be preferrable to fetching the entire `Universe`.
2021-07-01 07:45:48 +00:00
* `/random`: Read-only, get a random number from 0 to 99.
* `/grandom`: Read-only, get a random number from 0 to 99 -- These are doled out on a per-realm basis, and the number stays the same until everyone in the realm has had a chance to read it. If you've already read it this round or aren't in a realm, it will be empty.
* `/version`: Read-only, outputs the version of the `xrxs` server.
2021-08-04 05:31:32 +00:00
### realm format
Each realm directory on the server should have the following files:
* `realm`: Basic data for the realm, file should contain only the maximum number of members, the master's name, and the password hash, if any (otherwise 0), separated by spaces.
* `universe`: The actual game state for the realm as key value pairs, one per line, like `KEY = VALUE`; limit 15 characters for keys, 63 for values.
The realm should be synchronized to disc when realm membership, limit, or password change. Fenagling some periodic autosave should be possible...
## configuration
`config.h` in the source contains the following configuration macros:
* `MAX_USERS`: the maximum number of simultaneous users able to attach to the `xrxs` service
* `DATA_DIR`: the path to the root of the cartridge and realm storage; can be absolute or relative to the `xrxs` executable, but must have the trailing `/`
2021-08-04 05:31:32 +00:00
## build/run
2021-07-01 07:45:48 +00:00
2021-08-04 05:31:32 +00:00
2021-10-16 06:40:33 +00:00
### server
The `xrxs` server is built/tested in a Linux environment with `plan9port` and the C standard library as the only dependencies. With minimal modifications it will probably run just as well on Plan9, *BSD, WSL, and MacOS.
Running `./build.sh` from the `server` directory should build the `xrxs` executable.
2021-08-04 05:31:32 +00:00
You can run a local server (for testing, split-screen games, or single-player games) with:
2021-08-05 05:20:16 +00:00
2021-08-04 05:31:32 +00:00
```
./xrxs -m /path/to/mountpoint
```
or expose a service on the network (uses `9pserve` to support multiple users and gracefully handle disconnects) with:
2021-08-05 05:20:16 +00:00
2021-08-04 05:31:32 +00:00
```
./xrxs-srv.sh start
```
Add the `-d` option to the above command to enable 9p debugging output. The default port is `5460` but can be changed by setting the `XRXS_PORT` environment variable.
2021-08-04 05:31:32 +00:00
Similarly, you can stop the service with:
2021-08-05 05:20:16 +00:00
2021-08-04 05:31:32 +00:00
```
./xrxs-srv.sh stop
```
2021-07-01 07:49:00 +00:00
The executable itself supports the following options, one of which is required (no options prints the help text):
* `-m MOUNTPOINT`: mount the 9p filesystem locally at MOUNTPOINT
* `-s SOCKET`: serve the 9p filesystem over a socket named SOCKET
* `-v`: print the version information
* `-h | --help`: show the help text
2021-10-16 06:40:33 +00:00
### client
There are two versions of the client ROM. One is the normal `xrxs` client, and one is a standalone client for use as a generic `uxn` bootloader. The latter reads a ROM list out of a file called `index`, and appends the `.rom` extension to your selection and loads a file so named. Note that while the `9p` filesystem will be located under the parent directory of `./n`, the standalone bootloader assumes a flat filesystem.
You can run `./build.sh` with no options to build the normal `xrxs` client, or with any of the following options:
2021-10-16 06:48:07 +00:00
* `-r`: build the normal client and run it for local testing (don't mount the remote `9p` filesystem)
* `-l`: build the standalone bootloader
* `-lr`: build the standalone bootloader and run it
When the client ROM has been built, run `./uxn-xrxs.sh` to mount the `9p` service and run the client. As with the server, the default port is `5460` but can be overridden with the `XRXS_PORT` environment variable. The default server address is `127.0.0.1` but can be similarly changed by setting the `XRXS_ADDR` environment variable.
The scripts assume you have `uxnasm` and `uxnemu` in your `PATH`. `9pfuse` is used to mount the service, but other implementations could possibly be used.