Files
firefrost-operations-manual/docs/consultations/gemini-rules-mod-compilation-2026-04-12.md
Claude (Chronicler #83 - The Compiler) 1c3a4469a9 docs(consultation): Gemini response — Rules Mod build strategy confirmed
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>
2026-04-12 14:30:10 +00:00

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

  1. 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?
  2. 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 to HttpURLConnection or bundle a lightweight HTTP library. What's the cleanest approach that keeps the mod jar small and dependency-free?

  3. 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?

  4. 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?

  5. 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:

  1. NeoForge 1.21.1: moddev 2.0.74-beta is valid. Use NeoForge version 21.1.65 (stable).

  2. Forge 1.20.1 port: Namespace swap net.neoforged.*net.minecraftforge.*. ModConfigSpecForgeConfigSpec. Meta file: mods.toml (not neoforge.mods.toml).

  3. Forge 1.16.5 port (heaviest lift):

    • Must target Java 8 (many servers run Java 8)
    • Component.literal()new StringTextComponent()
    • java.net.http.HttpClientjava.net.HttpURLConnection (HttpClient is Java 11+)
    • Config: ForgeConfigSpec, meta: mods.toml
  4. 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.

  5. 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:

  1. Install SDKMAN + Java 17 + Java 8
  2. Build NeoForge 1.21.1 first (closest to existing code)
  3. Download Forge 1.20.1 MDK, port code
  4. Download Forge 1.16.5 MDK, port code with HTTP rewrite
  5. Upload all 3 jars to NextCloud via WebDAV