Skip to main content

PLAN - Runic Engine Minecraft Server

PLAN: Runic Engine Minecraft Server

Phase 1: Gather Version Information from CurseForge Client

Before building the server, you need to know the exact Minecraft version, Forge version, and modpack version your clients are running.

How to Find Your CurseForge Client Versions

Step 1: Find the Modpack Instance Folder

  1. Open the CurseForge App
  2. Go to My Modpacks tab
  3. Click the Runic Engine modpack icon (not the Play button)
  4. Click the three dots (⋮) or gear/settings icon on the right side
  5. Click "Open Folder" — this opens the modpack's install directory in your file explorer

Step 2: Find the Minecraft Version

  • On the modpack's CurseForge page (or in the app's modpack details), the Minecraft version is displayed prominently (e.g., 1.20.1)
  • Alternatively, in the instance folder, open minecraftinstance.json — look for the gameVersion field

Step 3: Find the Forge Version

  • In the instance folder, look for a file called minecraftinstance.json or check the manifest.json
  • The Forge version will appear in the modloader section, e.g., forge-47.4.0
  • You can also check the CurseForge app: click the modpack → look at the Versions tab — it will list the Forge version required
  • Another method: in the instance folder, check the mods/ directory — look for forge-* in file names, or check version.json inside the .minecraft/versions/ subfolder

Step 4: Find the Mods Folder

  • From the instance folder opened in Step 1, the mods are in the mods/ subdirectory
  • Full typical path on Windows: C:\Users\<username>\curseforge\minecraft\Instances\Runic Engine\mods\
  • Full typical path on macOS/Linux: ~/curseforge/minecraft/Instances/Runic Engine/mods/

Step 5: Confirm Modpack Version

  • In the CurseForge app, the modpack version number is shown on the modpack tile (e.g., 1.6.0)
  • Both players must be on the same modpack version

Phase 2: Build the Docker Compose Configuration

docker-compose.yaml

Create /home/ejm3/docker_storage/runic_engine/docker-compose.yaml with:

  • Image: itzg/minecraft-server:java17 (Java 17 is required for Forge 1.20.1)
  • Type: FORGE
  • VERSION: Match the Minecraft version from Phase 1 (e.g., 1.20.1)
  • FORGE_VERSION: Match the Forge version from Phase 1 (e.g., 47.4.0)
  • Mods bind mount: /nfs_storage/minecraft_mods/runic/mods-src (read-only)
  • COPY_MODS_SRC: /mods-src — the itzg image will copy mods from here into /data/mods at startup
  • REMOVE_OLD_MODS: true — clears old mods before copying
  • MEMORY: 8G (sufficient for 2 players with 230+ mods)
  • Resource limits: 10G memory limit, 3 CPUs

Environment Variables Summary

EULA: "TRUE"
TYPE: FORGE
VERSION: "1.20.1"              # UPDATE from client
FORGE_VERSION: "47.4.0"        # UPDATE from client
MEMORY: 8G
USE_AIKAR_FLAGS: "true"
MOTD: "Runic Engine Server"
DIFFICULTY: normal
MAX_PLAYERS: 5
VIEW_DISTANCE: 10
COPY_MODS_SRC: /mods-src
REMOVE_OLD_MODS: "true"
ENABLE_COMMAND_BLOCK: "true"
SPAWN_PROTECTION: 0
TZ: America/Chicago

Phase 3: Handle Client-Only Mods

When players copy their mods folder to the server, client-only mods must be removed or excluded because they reference client-side classes (rendering, input, audio) that don't exist on a dedicated server, causing NoClassDefFoundError crashes.

Common Client-Only Mods to Exclude

These are well-known client-only mods frequently found in Forge 1.20.1 modpacks. Remove these from the server's mods directory:

Mod Why It's Client-Only
OptiFine Rendering optimization, shaders
Oculus Shader support (Iris fork for Forge)
Rubidium Rendering optimization (Sodium fork for Forge)
Embeddium Rendering optimization (another Sodium fork)
Iris Shaders Shader support (Fabric, but sometimes present)
Sodium Rendering optimization (Fabric, but sometimes present)
Better Fps Client-side FPS optimization
FancyMenu Custom main menu screens
CustomMainMenu Custom main menu screens
Controlling Keybinding UI improvements
Configured Client config GUI
BetterF3 Enhanced F3 debug screen
Toast Control Hides client toast notifications
Blur (Blur API) GUI blur effects
Ding Plays a sound when MC finishes loading
Sound Physics Remastered 3D audio / reverb
Presence Footsteps Enhanced footstep sounds
Dynamic Surroundings Client-side ambient sounds/weather
ReAuth / OAuth Re-authentication helpers
Mod Menu (Fabric) Mod list GUI
Light Overlay Renders light level overlays
AppleSkin Client-side HUD for food values
Xaero's Minimap Minimap rendering (has a server companion but the client mod alone crashes)
Xaero's World Map World map rendering
JourneyMap Minimap/world map (client component)
Mouse Tweaks Inventory mouse improvements
Inventory HUD+ HUD overlays
ItemPhysic Dropped item rendering
NotEnoughAnimations Extra player animations
Skin Layers 3D 3D skin layer rendering
Entity Culling Rendering optimization
FerriteCore Memory optimization (has separate client/server versions — use only the server version)
Smooth Boot Client-side startup optimization
Shutup Experimental Settings Suppresses client warning screen
Catalogue Mod list GUI replacement
Cloth Config Config screen API (often client-only)
Just Enough Items (JEI) Recipe viewer — usually works on both sides, but check if your version is client-only

Note on JEI/REI: These recipe viewers often work on both client and server. They typically won't crash the server, but they're unnecessary there. If in doubt, keep them — they'll just be ignored.

Note on map mods (JourneyMap, Xaero's): Some have server-side companion plugins. The main .jar is usually client-only. Check the mod's CurseForge page for "server" vs "client" labels.

How to Identify Other Client-Only Mods

If a mod not on this list crashes the server, here's how to identify it:

Method 1: Check the CurseForge Page

  1. Go to the mod's CurseForge page
  2. Look at the "Environment" or "Side" field in the mod details sidebar
  3. It will say: Client, Server, or Both
  4. If it says Client — remove it from the server

Method 2: Check the mod's mods.toml

  1. Open the .jar file (it's a zip) with any archive tool
  2. Navigate to META-INF/mods.toml
  3. Look for a side field:
    • side = "CLIENT" → client-only, remove from server
    • side = "BOTH" → safe on server
    • side = "SERVER" → server-only

Method 3: Read the Server Crash Log

  1. If the server crashes on startup, check logs/latest.log or crash-reports/
  2. Look for errors like:
    • NoClassDefFoundError: net/minecraft/client/...
    • ClassNotFoundException: ...client...
    • Mod <modname> requires client-side classes
  3. The mod name will be in the stack trace — remove that mod's .jar and restart

Method 4: Binary Search

  1. If you can't identify the offending mod from logs:
  2. Remove half the mods, try starting the server
  3. If it works, the problem mod is in the removed half
  4. Repeat until you find the specific mod

Implementation: Exclusion Script

Rather than manually deleting mods each time, we'll create a small script or use the itzg image's built-in exclusion:

Option A: REMOVE_OLD_MODS_EXCLUDE + manual removal

  • Use COPY_MODS_SRC with REMOVE_OLD_MODS=true
  • Add a startup script that deletes known client-only jars after copy

Option B: Curated server mods directory

  • Instead of copying the full client mods folder, maintain a separate "server-safe" copy
  • Script that copies mods from the NFS share and removes known client-only ones

We will implement Option B with a shell script (filter-mods.sh) that:

  1. Copies all mods from the NFS bind mount
  2. Deletes any matching a known exclusion list
  3. Runs before the server starts

Phase 4: Directory Structure

/home/ejm3/docker_storage/runic_engine/
├── docker-compose.yaml
├── filter-mods.sh              # Script to remove client-only mods
├── client-only-mods.txt        # List of client-only mod filenames to exclude
├── docs/
│   ├── PRD.md
│   └── PLAN.md
└── server-data/                # (gitignored) server world data, configs, etc.
/nfs_storage/minecraft_mods/runic/   # Players copy their mods here
├── mod1.jar
├── mod2.jar
├── oculus-1.20.1.jar            # ← will be filtered out by script
├── rubidium-1.20.1.jar          # ← will be filtered out by script
└── ...

Phase 5: Create Files

5.1 docker-compose.yaml

Write the compose file with:

  • itzg/minecraft-server:java17 image
  • Forge type with version pinning
  • NFS mods bind mount (read-only) at /mods-src
  • Named volume for server data
  • filter-mods.sh mounted and used as a custom entrypoint wrapper
  • Resource limits (10G memory, 3 CPUs)
  • Standard server settings (MOTD, difficulty, etc.)

5.2 filter-mods.sh

Startup script that:

  1. Copies all .jar files from /mods-src/ to /data/mods/
  2. Reads /client-only-mods.txt for patterns
  3. Removes any matching jars from /data/mods/
  4. Logs what was removed
  5. Executes the original entrypoint

5.3 client-only-mods.txt

A simple text file with one pattern per line (case-insensitive glob patterns):

optifine*
oculus*
rubidium*
embeddium*
fancymenu*
custommainmenu*
controlling*
configured*
betterf3*
toastcontrol*
blur*
ding*
soundphysics*
presencefootsteps*
dynamicsurroundings*
reauth*
lightoverlay*
mousetweaks*
inventoryhud*
itemphysic*
notenoughanimations*
skinlayers3d*
entityculling*
smoothboot*
shutupexperimentalsettings*
catalogue*

5.4 README with player instructions

A brief README in the project root with:

  • How to find CurseForge version info (from Phase 1)
  • How to copy mods to the NFS share
  • How to connect to the server
  • Troubleshooting tips

Phase 6: Testing & Validation

  1. Verify the Forge version and Minecraft version match the clients
  2. Start the server with docker compose up -d
  3. Check logs: docker compose logs -f — confirm Forge loads and mods are accepted
  4. If crash occurs, check the crash log for client-only mod references (Phase 3 methods)
  5. Have both players connect and verify they can join
  6. Confirm the MOTD and server settings are correct

Implementation Order

  1. Get version info from a client (Phase 1) — requires player input
  2. Create docker-compose.yaml (Phase 5.1)
  3. Create filter-mods.sh (Phase 5.2)
  4. Create client-only-mods.txt (Phase 5.3)
  5. Have a player copy mods to NFS share
  6. Start server and iterate (Phase 6) — remove additional client-only mods as discovered
  7. Write README (Phase 5.4) — after everything works