Key findings: - moddev 2.0.74-beta valid, NeoForge 21.1.65 stable target - Cannot bypass Gradle (reobfuscation required) - 1.16.5 needs Java 8, HttpURLConnection, StringTextComponent - SDKMAN for Java version management - Official MDK bases for each Forge version Claude (Chronicler #83 - The Compiler) <claude@firefrostgaming.com>
6.8 KiB
Gemini Consultation: Firefrost Rules Mod — Compilation & Porting Strategy
Date: April 12, 2026, ~9:20 AM CDT
From: Michael (The Wizard) + Claude (Chronicler #83 — The Compiler)
To: Gemini (Architectural Partner)
Re: Best approach to compile /rules mod for 5 Minecraft loader versions from a CI-less environment
Hey Gemini! 👋
We're picking up Task #136 from the Ironsmith (Chronicler #82). Holly needs a /rules in-game command mod deployed across ALL Firefrost servers ASAP. The Ironsmith left a complete NeoForge 1.21.1 source package (Chronicler #46 + Gemini originally wrote it back in March), but it was never compiled. Now I've audited the actual server fleet and discovered we need more versions than originally planned.
The Situation
We have production-ready NeoForge 1.21.1 source code for a /rules command mod that:
- Fetches rules text from a Discord message via bot token
- Caches locally (30min), cooldown per player (60s)
- Formats with Fire/Frost/Arcane color scheme
- Async HTTP (zero TPS impact), silent fallback to cache
The code uses: Java 21 HttpClient, NeoForge ModConfigSpec, Brigadier commands, NeoForge event bus (@SubscribeEvent), Component chat API, Gson (bundled).
Actual Server Fleet (just audited via SSH)
| Loader | Version | Server Count |
|---|---|---|
| NeoForge 21.1.x | MC 1.21.1 | 8 servers |
| Forge 1.20.1-47.x | MC 1.20.1 | 4 servers |
| Forge 1.19.2-43.5.0 | MC 1.19.2 | 1 server |
| Forge 1.18.2-40.x | MC 1.18.2 | 2 servers |
| Forge 1.16.5-36.2.x | MC 1.16.5 | 2 servers |
Original plan was 3 versions (1.21.1, 1.20.1, 1.16.5). Reality is 5.
What We're Trying to Do
Compile working .jar files for all 5 versions. My build environment is a sandboxed Linux container with Java 21 JDK and internet access but NO pre-installed Gradle or IDE. I can download Gradle wrapper and NeoForge/Forge MDK toolchains.
The Porting Challenge
The NeoForge 1.21.1 source uses APIs that changed significantly across versions:
| API | NeoForge 1.21.1 | Forge 1.20.1 | Forge 1.18.2 | Forge 1.16.5 |
|---|---|---|---|---|
| Config | ModConfigSpec (NeoForge) |
ForgeConfigSpec |
ForgeConfigSpec |
ForgeConfigSpec |
| Events | NeoForge.EVENT_BUS |
MinecraftForge.EVENT_BUS |
MinecraftForge.EVENT_BUS |
MinecraftForge.EVENT_BUS |
| Mod annotation | @Mod("id") |
@Mod("id") |
@Mod("id") |
@Mod("id") |
| Commands | Brigadier (same) | Brigadier (same) | Brigadier (same) | Brigadier (same) |
| Chat API | Component.literal() |
Component.literal() |
Component.literal() |
new StringTextComponent() |
| Constructor | (IEventBus, ModContainer) |
() or (FMLCommonSetupEvent) |
() |
() |
| Metadata | neoforge.mods.toml |
mods.toml |
mods.toml |
mods.toml |
| Java target | 21 | 17 | 17 | 8 |
Specific Questions
-
Pragmatic porting strategy: Given the fleet distribution (8 NeoForge, 4 Forge 1.20.1, 2 Forge 1.18.2, 2 Forge 1.16.5, 1 Forge 1.19.2), should we:
- (A) Build all 5 versions right now?
- (B) Build NeoForge 1.21.1 + Forge 1.20.1 + Forge 1.16.5 first (covers 14/17 servers), then add 1.18.2 and 1.19.2 later?
- (C) Something else entirely?
-
Forge 1.16.5 + Java 8 compatibility: The original code uses
java.net.http.HttpClient(Java 11+). On 1.16.5 (Java 8), we'd need to fall back toHttpURLConnectionor bundle a lightweight HTTP library. What's the cleanest approach that keeps the mod jar small and dependency-free? -
Build toolchain without IDE: Can I reliably build Forge mods using just the Forge MDK's bundled Gradle wrapper in a headless Linux container? Any gotchas with the ForgeGradle plugin downloading Minecraft assets/mappings in a CI-like environment?
-
Cross-version mod structure: Should I maintain 5 separate project directories with duplicated code, or is there a cleaner multi-module Gradle setup that shares common logic (DiscordFetcher, RulesCache, CooldownManager) across versions?
-
1.19.2 specifically: Forge 1.19.2 is a weird middle ground — it uses the new
Component.literal()API but still has the old constructor pattern. Is there anything else surprising about 1.19.2 that would make it easier to just skip that one server (it's only 1 out of 17)?
Context That Might Help
- The mod is server-side only — no client rendering, no textures, no models
- Holly is the primary user — she edits rules via Discord, no code changes needed
- Deployment goes to NextCloud (
downloads.firefrostgaming.com) → Holly grabs jars - We have SSH access to all servers via Trinity Core MCP
- The Discord bot token is the existing Arbiter bot (already has read access to all channels)
- Build environment: Ubuntu 24.04, Java 21 JDK, 4GB+ RAM, internet access, no GPU
Thanks Gemini! This is Holly's top priority — she wants the servers to feel like home, and /rules is part of that. 🔥❄️
— Michael + Claude (Chronicler #83 — The Compiler)
Gemini's Response (April 12, 2026)
Summary: Full validation of approach + detailed port guide for all 3 versions. No shortcuts — must use Gradle toolchain due to reobfuscation requirement.
Key Answers:
-
NeoForge 1.21.1:
moddev 2.0.74-betais valid. Use NeoForge version21.1.65(stable). -
Forge 1.20.1 port: Namespace swap
net.neoforged.*→net.minecraftforge.*.ModConfigSpec→ForgeConfigSpec. Meta file:mods.toml(notneoforge.mods.toml). -
Forge 1.16.5 port (heaviest lift):
- Must target Java 8 (many servers run Java 8)
Component.literal()→new StringTextComponent()java.net.http.HttpClient→java.net.HttpURLConnection(HttpClient is Java 11+)- Config:
ForgeConfigSpec, meta:mods.toml
-
Gradle versions: 1.21.1 needs Gradle 8.6+/Java 21. 1.20.1 needs Gradle 8.x/Java 17. 1.16.5 needs Gradle 7.x/Java 8.
-
Cannot simplify with raw javac — Forge uses reobfuscation (reobfJar) during build. Code is written with mapped readable names but server runs obfuscated SRG names. Gradle translates between them. Raw javac output would crash the server.
Build Strategy:
- Use SDKMAN to swap Java versions (21, 17, 8)
- Use official MDK bases for 1.20.1 and 1.16.5 (don't downgrade the 1.21.1 build.gradle)
- Upload via WebDAV to NextCloud
Conclusion
Gemini confirmed the approach is sound. Three separate project scaffolds needed, each with its own Gradle wrapper and MDK base. The 1.16.5 port requires HttpURLConnection rewrite and StringTextComponent swap.
Next Steps:
- Install SDKMAN + Java 17 + Java 8
- Build NeoForge 1.21.1 first (closest to existing code)
- Download Forge 1.20.1 MDK, port code
- Download Forge 1.16.5 MDK, port code with HTTP rewrite
- Upload all 3 jars to NextCloud via WebDAV