---
menu:
  after:
    name: Developer docs
    weight: 5
title: Developer docs
---
# Contributing to Blastmud

## Get the source

* [Main Blastmud game](https://git.blastmud.org/blasthavers/blastmud) - includes the listener that accepts connections, and the gameserver.
* [This website (including WebSocket play interface)](https://git.blastmud.org/blasthavers/blastmud-site)
* [Android app](https://git.blastmud.org/blasthavers/blastmud-android)

## Making changes

Make changes and test them locally (see dev env setup). If everything works correctly,
submit a PR.

Feel free to discuss in an issue first before starting work - we can tell you if we
think your idea is a good idea.

PRs are reviewed, and if we think it is appropriate for the game, it will be merged to main
by a member of the core (Wizards) team. Merged PRs are tested, and if tests pass, they are
automatically deployed. You can watch the status of the deployment over at
[https://concourse.blastmud.org/].

Note that changes to the gameserver can be made without disconnecting all users,
due to the design of the game. Changing the listener is a larger affair because
it involves disconnecting all users. Confining your changes to the gameserver part
of the code will mean we need to do less coordination to deploy it.

If you propose a change to us, you agree that unless you explicitly state otherwise,
you grant everyone a licence to use it under the same licence terms (as documented in
the LICENSE file) as the other code in the repository you are contributing to.

## Rules to increase the chances your change will be accepted

* The game must stay within [the guidelines](https://www.legislation.gov.au/Details/F2023L01424) to be rated as PG in Australia, rather than M, MA15+, R18+ or Refused Classification (i.e. illegal to distribute in Australia). No content that would make it RC can be accepted - this includes any content about any form of sexual violence, characters under 18 years of age (due to the interaction with the nature of this game), detailed instruction or promotion in crime or violence, incest or hard fetishes, or incentivised drug use (including any kind of buff from anything that could be construed as drugs). No PRs or other content of the kind described under this point may be submitted to any Blastmud resource (i.e. this restriction does not apply solely to PRs for the main branch). To avoid a higher classification, it is also necessary that violence remains mild and infrequent (taking the game as a whole), and that there is nothing more than infrequent discreet references to sexual activity (and not related to incentives / rewards).
* Your change shouldn't compromise security or privacy. It shouldn't create a risk that users can execute arbitrary code, access confidential information, misuse resources, or deny service to users. It should respect the privacy of users and not use personally-linked information for any purpose not mentioned in the privacy policy. It should not leak secrets such as deployment keys or the actual IP addresses of the systems on which Blastmud is deployed (other than the public proxy).
* Your change should be appropriate to the theme of the game.
* Your change should be safe to roll-back if it doesn't work correctly (if this is genuinely not possible, please discuss it with us).
* Your game should ensure the game remains balanced and fair both for players who primarily want to engage in PvE play, and those who want to engage in PvP with other willing participants.

## Setting up a blastmud development environment

* Check it out locally with git. `git clone https://git.blastmud.org/blasthavers/blastmud.git`.
* Ensure you have Rust installed. Visit [https://rustup.rs/](https://rustup.rs/) for help getting started.
* Run `cargo test && cargo build` to test and install the code.
* Setup postgresql. See [the Postgres docs](https://www.postgresql.org/docs/current/tutorial-install.html) for help. Create a postgresql database (in these instructions, I assume you call it blast) and user (called `blast` in these instructions as well) for Blastmud.
* Run `psql -d template1 &lt;schema/schema.sql` as a user with access to create databases.
* Install migra - `pip3 install migra`.
* Diff the blast DB from the temporary blast_schemaonly DB with `migra "postgres:///blast" "postgres:///blast_schemaonly" > /tmp/update.sql`
* Check `/tmp/update.sql` and if it looks good, apply it with `psql -U blast -d blast </tmp/update.sql`
* Create a config directory under the blastmud directory you checked out, and put a listener.conf and gameserver.conf in it, with the content below. Also make a run directory under config.
* From the config directory, run `../target/debug/blastmud_listener`. In another tab, run `../target/debug/blastmud_game`.
* Connect to port 1234 on localhost to test it out locally.

### listener.conf
```
listeners:
  - 127.0.0.1:1234
gameserver: 127.0.0.1:1235
ws_listener: 127.0.0.1:1236
pidfile: ./run/listener.pid
```

### gameserver.conf
```
listener: 127.0.0.1:1235
pidfile: ./run/gameserver.pid
database_conn_string: host=/var/run/postgresql user=blast password=blastuserpasswordhere dbname=blast
```

Adjust password for the database, and the path to the postgresql socket accordingly (you can also put host=localhost to connect over TCP if you prefer, but this is less efficient).

## Getting around the Blastmud codebase
### Listener

The listener lives under `blastmud_listener/` accepts WebSocket and telnet connections. It
establishes and maintains a connection to the gameserver, and sends information
about new connections and user commands (lines of input) to the gameserver. It
accepts commands from the gameserver.

Restarting it will disconnect all users.

### blastmud_interfaces

These live under `blastmud_interfaces/` and define the contract between the listener and
the gameserver.

Since it is a dependency for the listener, changing it will require restarting
the listener and disconnecting all users.

### Gameserver

This lives under `blastmud_game`. It is stateless (other than temporary caches that
can be replaced at any time), with all state living in the database, so that it can
be restarted at any time without impacting users.

It is further divided up as follows:

`main.rs` is the entrypoint.

`version_cutover.rs` handles seamless cutovers - the new version starts up,
finds the existing version, and sends it `SIGUSR1` to tell it to shut down
gracefully. Users will not notice any impact on thier game session.

The `static_content` module has submodules for npcs, rooms, species,
possession_types (including weapons), and fixed_items (features within
rooms that can be looked at for example).

The `regular_tasks` module has the infrastructure for anything that happens
repeatedly (although most actual task logic is in other modules - e.g.
NPC movement is in `static_content/npc`).

The `models` module defines the structure of the content that is stored as
BSON within the database. This for example defines all the fields on
users and items.

The `listener` module defines the interaction with the listener.

The `services` module provides common calculations (e.g. around combat, capacity
limits, skill checks, and broadcasting to everyone in a room).

The `db` module provides support for interacting with the database.

The `message_handler` module handles messages from the listener.
`message_handler/user_commands` in particular has all the logic for
handling commands sent by users.

#### Key models within the gameserver
* A `Session` represents a connected (but possibly unregistered) session.
* A `User` represents a particular registered user of the game. Sessions get
attached to users on login. Note that every `User` has an `Item` of type player
as well - `User` has the (often OOC) details that only make sense for a real
player, such as their password, while everything common to players and NPCs lives
on the item.
* An `Item` represents something that can be seen in the game - a player, NPC,
  possession, room, and so on.
* A `Task` represents something that will happen in the future, either as a once-off or recurring.
