Adding a game
This guide explains how to add support for a new game to Cobalt.
Backend
Create a new game directory in
cobalt/backend/games/, e.g.new_game. This will hold everything related to the game, including all of its loaders (vanilla, modded, etc).In the root of
new_game, create a package named after the loader, e.g.vanilla. All files related to that specific loader live here.
TIP
A package is a directory with an __init__.py file inside.
TIP
A single game can have multiple loaders, each in its own package.
- Inside the loader package, create
infrastructure/loader.py. This class is responsible for fetching and parsing the list of available game versions for this loader, and building the download link for a specific version.
Example
TIP
If the loader's versions are parsed from GitHub releases, use GithubClientMixin instead of duplicating the pagination logic. See Terraria's tModLoader loader for an example.
- Inside the loader package, create
infrastructure/__init__.py.
- Inside the loader package, create
application/services/servers.py. This service is responsible for creating a server by building and starting the Docker containers defined in steps 6 and 7, and passing them the required data (version, download link, etc).
Example
- Inside the loader package, create
application/services/__init__.py.
- Inside the loader package, create
build/Container.installer. This container simply downloads all the server files into the server's isolated directory.
Example
- Inside the loader package, create
build/Container.runtime. This container runs the actual game server from the isolated directory created in step 7.
Example
- Inside the loader package, create
build/scripts/entrypoint.sh. This is the entrypoint for the runtime container from step 8 - it's responsible for starting the server, creating a FIFO file to pass commands from the dashboard, and gracefully shutting down the server on a stop command.
- In the root of
new_game, createmodule.py. This module initializes all of the game's loaders. Under the hood, it also automatically checks whether the game and its loaders already exist in the database, and adds them if they don't.
Example
- In the root of
new_game, create__init__.pythat exports the game module.
Example
- Register the new game module in
cobalt/backend/games/__init__.pyby adding it toENABLED_GAME_MODULES:
from .dont_starve_together import DontStarveTogetherGameModule
...
from .new_game import NewGameModule
ENABLED_GAME_MODULES = [
DontStarveTogetherGameModule,
...,
NewGameModule
]- Restart the backend container:
docker restart cobalt-backendFrontend
Create a new game directory in
cobalt/frontend/src/assets/images/games/, e.g.new-game. Add the following assets to it:icon.png- max_width: 200x200
background.png- max_width: 1920x1080
Compress all images beforehand.
In
cobalt/frontend/src/utils/games.ts, import the icon:
import newGameIcon from "@/assets/images/games/new-game/icon.png"- In the same file, add an entry to
GameModules:
new_game: {
displayName: "NewGame",
icon: newGameIcon,
loaders: {
vanilla: {
displayName: "Vanilla"
}
},
sort_number: 6
}This is used to display the game in the server creation form.
- Create
cobalt/frontend/src/pages/games/new-game/ServerPage.vue. This is the page that gets rendered when a user opens a server of this game.
Example
- In
cobalt/frontend/src/pages/ServerPage.vue, register the new page ingameComponents:
const gameComponents: Record<string, Component> = {
dont_starve_together: DontStarveTogetherServerPage,
...,
new_game: NewGameServerPage
}This map tells the app which page component to render based on the game type of the opened server.