Fully working in-game computers for the Laugh School™ Minecraft Server. Not decoys:
every command executes real logic, files persist in world NBT, fetch performs real
HTTP requests, and both arcade games are genuinely playable.
Two builds come out of this repo:
| Build | Artifact | For |
|---|---|---|
| Fabric mod (the main event) | laughschool-computers-<version>.jar |
Fabric 1.21.11 server + Java clients. Terminal screen, arcade, LaughBrowser, Geyser chat mode. |
| Paper plugin | laughschool-computers-paper-<version>.jar |
Paper 1.21.11 servers that can't ask players to install anything. Shell-only, in chat, for everyone. See §8. |
| Player | Experience |
|---|---|
| Java + this mod installed | Full CRT terminal screen, Snake & Pong, everything. |
| Bedrock via Geyser (no mods possible) | Automatic chat mode: right-clicking the computer boots it in chat, commands run via /pc <command>. Full shell, files, and internet — only the arcade screen is Java-mod-exclusive. |
| Anyone on the Paper build | Chat mode, always — Paper has no client mod to talk to. |
The switch is automatic: the server checks whether the client registered the mod's
packet channels (ServerPlayNetworking.canSend) and falls back to chat mode if not.
All logic (shell, file storage, HTTP whitelist, high-score validation) runs
server-side, so both paths hit the exact same brain.
- Computer block — Redstone Blocks creative tab, or
/give @s lscomputers:computer. Right-click to boot. - LaughOS shell —
help,motd,name,files/write/read/rm(32 files × 512 chars, saved in world NBT),ping,time,uptime,whoami,neofetch,sudo,credits. - Python —
python <expr>runs a snippet in a tiny built-in Python 3 interpreter (variables, arithmetic, strings, comparisons,print/len/str/int/float/abs/round/type/min/max/sum). Statements split on;, so you can save and run scripts:write hi.py x=21; print(x*2)thenpython hi.py. No loops/imports/IO — it always terminates and can't touch the game, disk, or network. - Locking —
lock <password>claims the machine and locks it (salted SHA-256, stored in world NBT).unlock <password>logs you in;passwd [new](owner) changes/removes it;logoutre-locks. A reboot re-locks everyone — it's a login prompt, not a keep-out sign. Scores and the browser are gated behind the lock too. - Internet —
fetch example.com: real async HTTP GET, domain-whitelisted, size/time capped, redirects refused, IP literals blocked. Server-side only; unbypassable from clients. - Web browser —
browse [url]opens the LaughBrowser: a text-mode ("Lynx-style") browser with an address bar, arrow-through links, history (Backspace), and page scrolling. Fetching is the same whitelisted, server-side path asfetch. In chat modebrowsefalls back tofetch. - Games (Java modded clients) —
games, thensnake,pong,tetris,2048,breakout. High scores validated & stored per computer. - Config —
config/laughschool-computers.json, live-reload via/lscomputers reload(op 2). Also editable in-game: runsettingsin the terminal, or open it from Mod Menu if installed. In singleplayer / a self-hosted world the changes apply immediately. If Mod Menu isn't installed, the settings screen offers a one-click optional download of the matching build into yourmods/folder (takes effect after a restart). - Easter eggs — try
laugh. Old-school gamers should try a certain 10-key code in the terminal.
Requires JDK 21+ (25 works fine — the mod targets 21). The complete Gradle
wrapper is included (gradlew, gradlew.bat, gradle/wrapper/gradle-wrapper.jar,
official Gradle 9.4.0) — no Gradle installation needed:
./gradlew build
# → build/libs/laughschool-computers-<version>.jar (Fabric mod)
# → paper/build/libs/laughschool-computers-paper-<version>.jar (Paper plugin)One build produces both; ./gradlew :paper:build builds only the plugin (much faster —
no Minecraft decompile or remap). CI does the same on every push and pull request
(.github/workflows/build.yml), and pushing a v* tag builds both and publishes a
GitHub Release with the jars attached (.github/workflows/release.yml).
On the first run the wrapper automatically downloads the Gradle 9.4.0 distribution
and Gradle resolves the build dependencies (Minecraft 1.21.11, Mojang mappings,
Loom, Fabric Loader, Fabric API) from Mojang's and Fabric's servers into your local
cache (~/.gradle). That's by design — those artifacts are machine-cached, not
project files. After the first build, everything is offline-cached.
The one runtime file to download separately: Fabric API 0.141.4+1.21.11 for the
mods/ folders (server + Java clients), from
https://modrinth.com/mod/fabric-api/versions (pick the 1.21.11 build).
Toolchain: Minecraft 1.21.11 (the last obfuscated version), Loom 1.14
(net.fabricmc.fabric-loom-remap), Mojang official mappings, Fabric Loader
0.18.1, Fabric API 0.141.4+1.21.11.
- Fabric 1.21.11 server, Java 21+. Into
mods/: this jar + Fabric API. - Install Geyser-Fabric and Floodgate (both from https://geysermc.org/download) into
mods/as usual. - Java players who want the full terminal also install this jar + Fabric API client-side.
- Bedrock players just join through Geyser — nothing to install, chat mode kicks in.
Honest limitations with Geyser:
- The computer is a modded block, so Bedrock clients render it as a fallback block (Geyser substitutes unknown blocks). It's still fully right-clickable and functional. If you want it to look right on Bedrock, Geyser's experimental custom block mappings + a Bedrock resource pack can skin it — see the GeyserMC wiki ("Custom Blocks"); that's config on the Geyser side, not part of this jar.
- The arcade (Snake/Pong) is rendered by the Java client mod and can't exist on Bedrock. Chat mode says so politely.
- Vanilla Java clients (no mod) still can't join: Fabric registry sync requires Java clients to know the mod's block/item. That's a Fabric/registry fact of life, not something this mod can waive — Bedrock players are exempt because Geyser translates for them.
{
"enableInternet": true,
"allowedDomains": ["example.com", "api.github.com", "wttr.in"],
"allowAllDomains": false,
"maxResponseLines": 16,
"maxResponseBytes": 8192,
"requestTimeoutSeconds": 5,
"motd": "Welcome to LaughOS(TM) ...",
"easterEggs": true
}Created with defaults on first run, rewritten on load so new options appear after
updates. Only root domains you list are allowed (plus their subdomains) — unless
you set allowAllDomains: true, which removes the whitelist entirely and lets
fetch/browse reach any host (IP literals and localhost are still refused). You
can flip this from the in-game settings screen too.
- Shell + HTTP run server-side; a hacked client can only send command strings.
- Packets rejected unless the player is within 8 blocks of a real computer
(
/pcrequires ~4 blocks). - Scores clamped server-side; inputs length-capped and control-character-stripped.
fetchnever follows redirects and refuses IP literals/localhost.
Built exclusively for the Laugh School™ Minecraft Server. No decoys were used in the making of this mod. Bedrock friends welcome.
paper/ is the same computers as a Paper 1.21.11 plugin, for servers that can't
require a mod on the client. It is the mod's server half: the LaughOS shell, the file
system, the salted password lock, the built-in Python and whitelisted fetch — the
python interpreter is literally the same source file, compiled into both jars.
./gradlew :paper:build
# → paper/build/libs/laughschool-computers-paper-<version>.jarDrop it in plugins/, restart, then:
/lscomputers give— hands you a Laugh School™ Computer (a tagged Lodestone by default; changecomputerBlockinconfig.ymlto any block you like).- Place it, right-click to boot.
/pc help,/pc write notes.txt hello,/pc python 2 ** 10,/pc lock hunter2, …
Commands and permissions:
| Command | Permission | What |
|---|---|---|
/pc <command> |
lscomputers.use (default: everyone) |
The terminal. Works on the nearest computer within ~4 blocks. |
/lscomputers reload |
lscomputers.admin (default: op) |
Re-read config.yml; also re-locks every machine and drops registrations whose block is gone. |
/lscomputers give [player] |
lscomputers.admin |
Hand out a computer. |
/lscomputers list |
lscomputers.admin |
How many computers exist, and the nearest one. |
- No terminal screen, no arcade, no LaughBrowser. Those are client-mod rendering.
games/browse/settingssay so;browse <url>degrades tofetch. - The computer is a vanilla block wearing a tag, because Bukkit can't register a
new block. Placement is tracked by the plugin, so a computer placed from a
/lscomputers giveitem is a computer and a plain Lodestone next to it is not. - State lives in
plugins/LaughSchoolComputers/computers.yml, not world NBT (saved on change every 5 minutes and on shutdown). Breaking a computer drops the item and deletes its files — same as destroying the modded block's block entity. Explosions leave computers standing, and pistons refuse to push them, so a machine can't lose its disk to a stray creeper. config.ymluses the same option names as the mod's JSON, pluscomputerBlock.- Bedrock players via Geyser get exactly what Java players get here: chat mode. On this build the fallback isn't a fallback, it's the whole product.