Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion minecraft-java/template.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ spec:
displayName: Minecraft (Java Edition)
game: minecraft-java
# Kept in lockstep with module.yaml's bundle version from 2.5.0 onward.
version: 2.8.1
version: 2.9.0
categories: [Sandbox, Survival, Building, Modded, Creative]
# Brand color the dashboard tints this game's icon/accents with.
accentColor: "#5b9a3e"
Expand Down
2 changes: 1 addition & 1 deletion nuclear-option/module.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
apiVersion: gameplane.local/module/v1
name: nuclear-option
displayName: Nuclear Option
version: 1.0.0
version: 1.0.1
game: nuclear-option
categories: [Simulation, PvP]
summary: Nuclear Option dedicated server with remote-command console, runtime-downloaded via SteamCMD.
Expand Down
11 changes: 4 additions & 7 deletions nuclear-option/template.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ spec:
displayName: Nuclear Option
game: nuclear-option
# Kept in lockstep with module.yaml's bundle version.
version: 1.0.0
version: 1.0.1
categories: [Simulation, PvP]
# Brand color for the dashboard.
accentColor: "#ff6b6b"
Expand Down Expand Up @@ -166,12 +166,9 @@ spec:
list:
command: "get-player-list"
entryRegex: '"steamId":\s*"(?P<name>[^"]*)"'
kick:
command: "kick-player {{.Player}}"
ban:
command: "banlist-add {{.Player}}"
unban:
command: "banlist-remove {{.Player}}"
kick: "kick-player {{.Player}}"
ban: "banlist-add {{.Player}}"
unban: "banlist-remove {{.Player}}"
# Note: the server returns 2000 (success) for kick/ban/unban even when
# the Steam ID is not present, so the agent cannot distinguish a
# successful moderation from a silent no-op.
Expand Down
5 changes: 3 additions & 2 deletions terraria/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ override) or add an entry to `spec.versions`.
tModLoader servers get a **Mods** tab that manages modpacks under
`/opt/terraria/config/ModPacks` — its own per-(version+loader) volume, so
each tModLoader build keeps its own set. Select the active modpack with the
**Active modpack** (`MODPACK`) config field. Vanilla Terraria has no mods, so
**Active modpack** (`MODPACK`) config field; left blank, tModLoader servers start a built-in empty `vanilla` pack. Vanilla Terraria has no mods, so
the tab is hidden for vanilla servers. Installs are allowed from GitHub
(max 512 MiB), subject to the agent's SSRF guard.

Expand All @@ -36,7 +36,8 @@ offered.
## Console

No RCON. The **Console** tab attaches to the container's stdin/stdout (pty) —
type `help` for the command list.
type `help` for the command list. The image runs the server inside a detached tmux session, so the
template's start wrapper forwards each console line into that session; the Stop button's `exit` saves the world and stops within seconds.

## Ports

Expand Down
2 changes: 1 addition & 1 deletion terraria/module.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
apiVersion: gameplane.local/module/v1
name: terraria
displayName: Terraria
version: 2.2.2
version: 2.2.3
game: terraria
categories: [Sandbox, Survival, Adventure, Modded]
summary: Terraria + tModLoader dedicated server (passivelemon/terraria-docker) with a vanilla/tModLoader version picker and a tModLoader ModPacks volume. Console via container stdin.
Expand Down
1 change: 1 addition & 0 deletions terraria/specs.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ Declared ports under `spec.ports`:

- **Protocol**: `none`
- **Console Mode**: `pty`
- **Console Bridge**: The start wrapper forwards pty lines to the game's tmux session with `tmux send-keys -l` (as `PUID:PGID` via gosu/su-exec) and forwards SIGTERM to the entrypoint.
- **Authentication**: N/A (interactive stdin/stdout console).
- **Command Support**: Standard Terraria CLI commands (`say`, `save`, `kick`, `ban`, `settle`, `motd`, `dawn`, `noon`, `dusk`, `midnight`).

Expand Down
65 changes: 63 additions & 2 deletions terraria/template.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ spec:
displayName: Terraria
game: terraria
# Kept in lockstep with module.yaml's bundle version from 2.1.0 onward.
version: 2.2.0
version: 2.2.3
categories: [Sandbox, Survival, Adventure, Modded]
# Brand color the dashboard tints this game's icon/accents with.
accentColor: "#4a90d9"
Expand All @@ -36,6 +36,58 @@ spec:
# authoritative source for the wizard's picker.
image: passivelemon/terraria-docker:terraria-latest@sha256:d60f280522d6c71079638b5036bdd6c4ac9f93c9f3250477ddb345fc2c6933f3

# passivelemon's tModLoader scripts exit when MODPACK is blank or its
# ModPacks/<pack>/Mods/enabled.json is missing. On tModLoader images
# (GP_LOADER=tmodloader) a blank MODPACK selects a built-in empty "vanilla"
# pack, created on first start and never overwritten. The image runs the
# game in a detached tmux session that never reads container stdin, so the
# wrapper also bridges the console: each line from the pty is sent to the
# game with tmux send-keys (as the game user), and SIGTERM is forwarded to
# the entrypoint so its save-and-exit trap still runs.
command: ["/bin/sh", "-c"]
args:
- |
pid=
trap 'if [ -n "$pid" ]; then kill -TERM "$pid" 2>/dev/null; else exit 143; fi' TERM
if [ "${GP_LOADER:-}" = "tmodloader" ]; then
: "${MODPACK:=vanilla}"; export MODPACK
if [ "$MODPACK" = "vanilla" ]; then
mkdir -p /opt/terraria/config/ModPacks/vanilla/Mods
[ -e /opt/terraria/config/ModPacks/vanilla/Mods/enabled.json ] || printf '[]\n' > /opt/terraria/config/ModPacks/vanilla/Mods/enabled.json
fi
fi
/opt/terraria/entrypoint.sh &
pid=$!
rpid=
if [ -t 0 ]; then
exec 3<&0
(
cr=$(printf '\r')
as=
if [ "$(id -u)" = 0 ]; then
if command -v gosu >/dev/null 2>&1; then as="gosu"; else as="su-exec"; fi
as="$as ${PUID:-1000}:${PGID:-1000}"
fi
while :; do
while IFS= read -r line <&3; do
line=${line%"$cr"}
[ -n "$line" ] || continue
if ! { $as /usr/bin/tmux send-keys -l -- "$line" && $as /usr/bin/tmux send-keys Enter; } 2>/dev/null; then
echo "[gameplane] console not ready; input ignored"
fi
done
sleep 1
done
) &
rpid=$!
fi
while :; do
wait "$pid"; rc=$?
kill -0 "$pid" 2>/dev/null || break
done
[ -z "$rpid" ] || kill "$rpid" 2>/dev/null
exit "$rc"

ports:
- name: game
containerPort: 7777
Expand Down Expand Up @@ -78,17 +130,26 @@ spec:
displayName: "tModLoader · latest"
image: passivelemon/terraria-docker:tmodloader-latest@sha256:3f2d8703421159f1037084bd2c0901a3a63b85a00801cf36f6f928e8b666b44e
loader: tmodloader
env:
- name: GP_LOADER
value: tmodloader
# Year channel: follows tModLoader's 2026.x stable line without jumping
# to the next yearly major — steadier for servers with version-sensitive
# mod sets than the plain latest tag.
- id: tmodloader-2026
displayName: "tModLoader · 2026 stable"
image: passivelemon/terraria-docker:tmodloader-2026@sha256:3f2d8703421159f1037084bd2c0901a3a63b85a00801cf36f6f928e8b666b44e
loader: tmodloader
env:
- name: GP_LOADER
value: tmodloader
- id: tmodloader-preview
displayName: "tModLoader · latest preview"
image: passivelemon/terraria-docker:tmodloader-latest-pre # gameplane:floating
loader: tmodloader
env:
- name: GP_LOADER
value: tmodloader

probes:
readiness:
Expand Down Expand Up @@ -253,6 +314,6 @@ spec:
default: "en-US"
- name: MODPACK
displayName: Active modpack
description: tModLoader only — a modpack folder name under ModPacks. Leave blank for none.
description: tModLoader only — a modpack folder name under ModPacks. Leave blank for the built-in empty "vanilla" pack.
type: string
default: ""
2 changes: 1 addition & 1 deletion the-isle/module.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ name: the-isle
displayName: The Isle
version: 1.0.0
game: the-isle
categories: [Survival, Dinosaur, Open World, Multiplayer]
categories: [Survival, Dinosaurs, Open World, Multiplayer]
summary: The Isle dedicated server (Unreal Engine 4) with Source RCON remote administration and persistent world save management.
homepage: https://findtheisle.com/
license: MIT
Expand Down
2 changes: 1 addition & 1 deletion the-isle/template.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ spec:
displayName: The Isle
game: the-isle
version: 1.0.0
categories: [Survival, Dinosaur, Open World, Multiplayer]
categories: [Survival, Dinosaurs, Open World, Multiplayer]
accentColor: "#22543d"
description: |
The Isle dedicated multiplayer server running on Unreal Engine.
Expand Down
10 changes: 5 additions & 5 deletions tmodloader/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,11 @@ kubectl apply -f modules/tmodloader/template.yaml

## Mod Management

tModLoader mods (`.tmod`) and modpacks are managed through the **Mods** tab. Mod files are stored under `/root/.local/share/Terraria/tModLoader/Mods`. Installs are allowed from GitHub release archives (max 512 MiB).
A fresh server starts the built-in empty `vanilla` modpack (no mods). The **Mods** tab manages `.tmod` files in that pack, under `/opt/terraria/config/ModPacks/vanilla/Mods`; a mod loads once its name is listed in that folder's `enabled.json`. To run another modpack, put it under `/opt/terraria/config/ModPacks/<name>/Mods` (with its `enabled.json`) and set **Active modpack** (`MODPACK`) to `<name>`. Installs are allowed from GitHub release archives (max 512 MiB).

## Console (PTY)

Terraria engines do not provide an RCON TCP port. The **Console** tab attaches directly to the container's stdin/stdout (pty) using the kubelet pod-attach API. Stop sequence issues `exit` to trigger world flushing before shutdown.
Terraria engines do not provide an RCON TCP port. The **Console** tab attaches directly to the container's stdin/stdout (pty) using the kubelet pod-attach API. Stop sequence issues `exit` to trigger world flushing before shutdown. The image runs the server inside a detached tmux session, so the template's start wrapper forwards each console line into that session.

## Ports

Expand All @@ -26,10 +26,10 @@ Terraria engines do not provide an RCON TCP port. The **Console** tab attaches d

## Storage

Storage is mounted at `/root/.local/share/Terraria/tModLoader` (4 GiB default), holding:
Storage is mounted at `/opt/terraria/config` (4 GiB default), holding:
- World files (`Worlds/`)
- Installed mods (`Mods/`)
- Mod configurations and loadouts
- Modpacks (`ModPacks/<name>/Mods/`, including the default `vanilla` pack)
- The generated `serverconfig.txt`

## Sample

Expand Down
2 changes: 1 addition & 1 deletion tmodloader/module.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
apiVersion: gameplane.local/module/v1
name: tmodloader
displayName: tModLoader
version: 1.0.1
version: 1.0.2
game: tmodloader
categories: [Sandbox, Survival, Adventure, Modded]
summary: tModLoader dedicated server for modded Terraria gameplay with PTY console, .tmod mod manager, and world saves.
Expand Down
1 change: 0 additions & 1 deletion tmodloader/samples/gameserver.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ spec:
DIFFICULTY: "1"
MAXPLAYERS: "8"
MOTD: "Welcome to Gameplane tModLoader Server"
MODPACK: ""

networking:
expose: NodePort
Expand Down
5 changes: 3 additions & 2 deletions tmodloader/specs.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
- **Base Image**: `passivelemon/terraria-docker:tmodloader-latest@sha256:3f2d8703421159f1037084bd2c0901a3a63b85a00801cf36f6f928e8b666b44e`
- **Architecture**: `linux/amd64`
- **Runtime Model**: .NET 6 runtime host running `tModLoader.dll` with integrated mono/native runtime dependencies.
- **User & Execution Context**: Root container execution (`/`).
- **User & Execution Context**: Starts as root; a small wrapper picks the default `vanilla` modpack when `MODPACK` is blank, then the image entrypoint drops to the `terraria` user (uid/gid 1000) via su-exec.

---

Expand All @@ -30,7 +30,7 @@ Declared ports under `spec.ports`:

## 4. Storage & Persistence Layout

- **Mount Path**: `/root/.local/share/Terraria/tModLoader`
- **Mount Path**: `/opt/terraria/config`
- **Default Sizing**: `4Gi`
- **Persisted Content**:
- Generated modded worlds (`Worlds/*.wld`)
Expand All @@ -44,6 +44,7 @@ Declared ports under `spec.ports`:

- **Protocol**: `none`
- **Console Mode**: `pty`
- **Console Bridge**: The start wrapper forwards pty lines to the game's tmux session with `tmux send-keys -l` (as `PUID:PGID` via gosu/su-exec) and forwards SIGTERM to the entrypoint.
- **Authentication**: N/A (interactive terminal console).
- **Command Support**: Standard Terraria and tModLoader CLI commands (`say`, `save`, `exit`, mod reload commands).

Expand Down
67 changes: 62 additions & 5 deletions tmodloader/template.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
#
# Backed by passivelemon/terraria-docker:tmodloader-latest. Dedicated server
# running the tModLoader .NET 6 modding framework for Terraria. Console
# attaches to container stdin (pty); no RCON.
# attaches to container stdin (pty); no RCON. A blank MODPACK starts the
# built-in empty "vanilla" modpack (see the command wrapper below).
#
# Cluster-scoped; apply once per cluster:
# kubectl apply -f modules/tmodloader/template.yaml
Expand All @@ -17,7 +18,7 @@ metadata:
spec:
displayName: tModLoader
game: tmodloader
version: 1.0.0
version: 1.0.2
categories: [Sandbox, Survival, Adventure, Modded]
accentColor: "#10b981"
description: |
Expand All @@ -26,6 +27,62 @@ spec:

image: passivelemon/terraria-docker:tmodloader-latest@sha256:3f2d8703421159f1037084bd2c0901a3a63b85a00801cf36f6f928e8b666b44e

env:
- name: GP_LOADER
value: tmodloader

# passivelemon's tModLoader scripts exit when MODPACK is blank or its
# ModPacks/<pack>/Mods/enabled.json is missing. On tModLoader images
# (GP_LOADER=tmodloader) a blank MODPACK selects a built-in empty "vanilla"
# pack, created on first start and never overwritten. The image runs the
# game in a detached tmux session that never reads container stdin, so the
# wrapper also bridges the console: each line from the pty is sent to the
# game with tmux send-keys (as the game user), and SIGTERM is forwarded to
# the entrypoint so its save-and-exit trap still runs.
command: ["/bin/sh", "-c"]
args:
- |
pid=
trap 'if [ -n "$pid" ]; then kill -TERM "$pid" 2>/dev/null; else exit 143; fi' TERM
if [ "${GP_LOADER:-}" = "tmodloader" ]; then
: "${MODPACK:=vanilla}"; export MODPACK
if [ "$MODPACK" = "vanilla" ]; then
mkdir -p /opt/terraria/config/ModPacks/vanilla/Mods
[ -e /opt/terraria/config/ModPacks/vanilla/Mods/enabled.json ] || printf '[]\n' > /opt/terraria/config/ModPacks/vanilla/Mods/enabled.json
fi
fi
/opt/terraria/entrypoint.sh &
pid=$!
rpid=
if [ -t 0 ]; then
exec 3<&0
(
cr=$(printf '\r')
as=
if [ "$(id -u)" = 0 ]; then
if command -v gosu >/dev/null 2>&1; then as="gosu"; else as="su-exec"; fi
as="$as ${PUID:-1000}:${PGID:-1000}"
fi
while :; do
while IFS= read -r line <&3; do
line=${line%"$cr"}
[ -n "$line" ] || continue
if ! { $as /usr/bin/tmux send-keys -l -- "$line" && $as /usr/bin/tmux send-keys Enter; } 2>/dev/null; then
echo "[gameplane] console not ready; input ignored"
fi
done
sleep 1
done
) &
rpid=$!
fi
while :; do
wait "$pid"; rc=$?
kill -0 "$pid" 2>/dev/null || break
done
[ -z "$rpid" ] || kill "$rpid" 2>/dev/null
exit "$rc"

security:
fsGroup: 1000

Expand All @@ -38,7 +95,7 @@ spec:

storage:
size: 4Gi
mountPath: /root/.local/share/Terraria/tModLoader
mountPath: /opt/terraria/config

resources:
requests:
Expand Down Expand Up @@ -84,7 +141,7 @@ spec:
transport: stdin
command: "save"
mods:
path: Mods
path: ModPacks/vanilla/Mods
extensions: [".tmod", ".zip"]
install:
allowedHosts:
Expand Down Expand Up @@ -124,6 +181,6 @@ spec:
default: "Welcome to Gameplane tModLoader Server"
- name: MODPACK
displayName: Active modpack
description: Active modpack name under ModPacks. Leave blank for none.
description: Active modpack folder name under ModPacks. Leave blank for the built-in empty "vanilla" pack.
type: string
default: ""
Loading
Loading