Moud

Running a fleet#

A server you start yourself runs one place for whoever connects to it. That is enough to test a game with friends, but a game on Moud needs more than that. When fifty people press Play at once they need several servers. A lobby that sends players to an arena needs a server of the arena ready for them. And when everyone leaves, nobody wants ten empty servers sitting there using memory.

A fleet does that work for you. It is one program, moud fleet, that you run on a machine of your own, such as a rented server with a public address. It starts a server of a place when players need one, moves players between servers, and closes the servers nobody is on. It also connects your game to the Moud catalog, so the game's page gets a Play button and players who press it land on one of your servers.

You do not write anything for it. The scripts of a place run the same under a fleet as on one server. What changes is that moving players, reserved servers and the server list start working, and that stores are shared by every server of the game.

What happens when a player presses Play#

It helps to know the path a player takes before setting anything up:

  1. The player presses Play on the game's page, in Moud or on the website.
  2. The catalog looks at the servers your fleet told it about and picks the fullest server of the start place that still has room.
  3. When no server has room, the catalog asks your fleet for a new one. The fleet starts it, which takes about half a minute, and the player waits for it.
  4. The catalog hands the player a ticket for that server, and their game connects to your machine at the address and port the fleet gave.
  5. The server checks the ticket and lets the player in. From here on it is an ordinary server running your place.

Your fleet tells the catalog every few seconds which servers are running and who is on them, which is how the catalog knows where there is room. It also keeps a connection open to the catalog, which is how the catalog asks it for a server and how messages between servers reach it.

What it needs#

A fleet starts each server as its own Java program on the same machine, so the machine has to be big enough for the servers you want running at once.

  • Linux or Windows, with Java 25.
  • About 1 to 2 GB of memory for each server. Even an empty server takes about 700 MB.
  • One open port for each server, a range like 25565 to 25574, opened on the firewall or forwarded on the router.
  • A game on the catalog with at least one accepted version, and its fleet key. File > Publish in the editor puts the game there, see Publishing a game.

The fleet key is how the fleet proves it runs your game. It is on the game's settings page on the website, under Fleet key. The page shows it once, so copy it into fleet.toml right away. Making a new key stops the old one from signing in again, which is what you do if a key leaks.

Setting one up#

Put the fleet jar, moud-cli.jar, in a folder of its own. The fleet keeps everything it downloads and every server it runs inside that folder.

Write a fleet.toml next to it:

java -jar moud-cli.jar fleet init

This writes an example file. Open it and fill in three settings: key with your fleet key, address with the host name or IP players reach this machine on, and eula = true to accept the Minecraft EULA. The fleet refuses to start a server without it, because every server is a Minecraft server.

Then start the fleet:

java -jar moud-cli.jar fleet

It prints what it does as it goes. The first start does the most:

  1. It signs in to the catalog with the key.
  2. It fetches what a server is made of: the Minecraft server from Mojang, Fabric Loader and Fabric API, each checked against its published hash. The Moud engine comes inside the fleet jar. Later starts only check what is already there.
  3. It downloads the latest accepted version of your game and checks every file against the list the catalog keeps for it.
  4. It waits for players.

Leave it running. Press Play on your game's page and watch the fleet start a server and the player arrive on it.

fleet.toml does not have to sit next to the jar. Name the file and the fleet uses the folder that file is in:

java -jar moud-cli.jar fleet /srv/tick-tock/fleet.toml

fleet.toml#

A filled in fleet.toml looks like this:

toml
catalog = "https://api.moud.epistudios.fr"
key = "moud_fleet_..."
name = "my-vps"
address = "play.example.net"
ports = "25565-25574"
maxServers = 10
memory = 1536
warm = 0
emptyGrace = 60
onlineMode = true
eula = true

Most of it is about how big the fleet may grow. ports is the range the servers listen on, one port each, and maxServers is how many may run at once, so the fleet never runs more servers than it has ports for. memory is how much each of them gets. Multiply memory by maxServers and check the machine has that much to spare.

warm decides whether players wait. With warm = 0 the fleet starts a server of the start place only when a player needs one, so the first player in waits about half a minute. With warm = 1 the fleet always keeps one server of the start place running with room, so Play is instant, at the cost of one server's memory even when nobody plays.

emptyGrace is how long an empty server stays up before the fleet stops it. A player who leaves and comes straight back finds the same server still there.

Setting
catalog the address of the Moud catalog, its api and not the website
key the fleet key of your game
name a name for this machine, shown to you on the website. Optional
address the host name or IP players reach this machine on, without a port
ports the ports the servers listen on, one each, as "first-last". 25565 to 25574 when left out
maxServers the most servers running at once, at most one per port. As many as ports has when left out
memory megabytes for each server, at least 512. 1536 when left out
warm servers of the start place kept running with room. 0 when left out
emptyGrace seconds a server stays up with nobody on it. 60 when left out
onlineMode true checks every player's Microsoft account, as a public server should. false is for testing on your own machine
eula true accepts the Minecraft EULA. The fleet does not start a server without it
java the Java that runs the servers. The one running the fleet when left out
engine a Moud engine jar to run instead of the one inside the fleet jar
control the port the servers talk to the fleet on, on this machine only. Picked for you when left out

A setting the fleet does not know, or a value out of range, stops it before it starts, with a line that names the setting and says what it expected.

How servers come and go#

The fleet tries to keep players together. Play sends a player to the fullest server of the start place that still has room, so ten players fill one server instead of spreading over ten. How many fit on a server is maxPlayers in that place's place.toml.

When no server has room, the catalog asks the fleet to start one and the player waits on it. Players who press Play while that server is starting all wait for the same one rather than each starting their own.

A teleport works the same way for any place of the game. The fleet picks the fullest server of that place with room for everyone moving, and starts one when none has room. The players wait on their loading screen while it starts. A reserved server starts with the first teleport that brings its code.

A server that has been empty for emptyGrace seconds is stopped. Its game:bindToClose handlers run first, so a place that saves on close saves. The servers kept for warm stay up.

Servers can also stop on their own, from a crash or an error in the place. The fleet drops such a server from its list and the catalog stops sending players to it. Its log says why, see The folder. A server that has not finished starting after three minutes is stopped as well. When servers fail to start three times in a row, the fleet starts no warm servers for five minutes, so a broken version does not start and crash in a loop.

Updating the game#

You update the game by publishing a new version and getting it accepted. Nothing needs doing on the machine. The fleet hears of the new version within ten seconds, downloads it, and starts every new server on it.

Servers that were already running keep their players and the version they started with. They take no new players, and they stop once they are empty, so players move over to the new version as their sessions end instead of being thrown off mid-game. A fleet also fetches the latest version each time it starts.

When the game is taken down on the catalog, the fleet stops every server.

Stopping it#

Press Ctrl+C, or stop the program the way your system stops services. The fleet stops every server the way Minecraft stops: game:bindToClose runs on each with the players still connected, for up to 30 seconds, so they get saved. Then it tells the catalog the servers are gone.

The folder#

Everything the fleet uses lives next to fleet.toml:

fleet.toml
moud-cli.jar
runtime/       Minecraft, Fabric and the engine, fetched once, and the fleet's token
versions/      each version of the game, unpacked
servers/       one folder per running server, removed when it stops
logs/          the log of each server that stopped, named by its id

When something goes wrong on a server, its log is where to look. While the server runs it is servers/<id>/console.log, and once it has stopped it is moved to logs/<id>.log. The id is the server's game.serverId, which the fleet also prints when it starts and stops each server.

There is nothing of the players' saves in this folder. The game's stores are kept by the catalog, so there is nothing to back up here.

runtime/fleet-token is what the fleet signs in with after the first time. Keep it, and a fleet that restarts is the same fleet on the website instead of a new one. Without it, the fleet signs in again with its key and is matched by name.

More than one machine#

When one machine is not enough, run a second fleet of the same game on another machine, with the same key. The two share the game's stores and messages between servers, and Play sends players to the servers of either.

They do not share everything. A teleport and servers:list only see the servers of the fleet they run on, so players moved from a lobby on one machine land on a server of the same machine.

When the network is down#

Everything the fleet downloads stays in runtime/ and versions/. When Mojang, Fabric or Modrinth can not be reached, it starts from what it fetched last time and says so.

The catalog is different, since it is what sends players to you. Without it nobody is sent to your servers, and stores and messages between servers stop working.

Testing on your own machine#

You can run the whole chain on one computer. Run a catalog locally, the website and the api, and point catalog at the api with http://127.0.0.1 and its port, 8787 unless it says otherwise. Point the Moud client at the same address with -Dmoud.catalog=http://127.0.0.1:8787. Then set address to 127.0.0.1 and onlineMode = false.

Plain http is only accepted for a catalog on the same machine. Anywhere else the catalog must be https.

Building the fleet jar from the repository#

./gradlew :cli:fleetJar builds the fleet jar with the engine of the same checkout inside, in cli/build/libs, the one ending in -fleet.jar. ./gradlew :cli:jar builds it without the engine, for a fleet whose fleet.toml names one with engine.