v1.0.3: Fix config read — wrong event bus + section header comments

1.20.1: ModConfigEvent fires on mod bus, not MinecraftForge.EVENT_BUS.
Moved Loading/Reloading to FMLJavaModLoadingContext.getModEventBus().
Added config file header warning about preserving [section] headers.
Debug logging in RulesCommand prints token length + channel at runtime.
All 6 builds bumped to 1.0.3.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Claude (Chronicler #83 - The Compiler)
2026-04-13 17:53:22 -05:00
parent 75c9feecec
commit 29f0127a60
98 changed files with 94 additions and 20 deletions

View File

@@ -0,0 +1,26 @@
# Architectural Response
**Re:** REQ-2026-04-13-rules-mod-config-not-read-at-runtime
**Date:** 2026-04-13
## 1. Root Cause (two bugs)
**Bug 1: Wrong event bus (1.20.1 only).** `ModConfigEvent.Loading` and `Reloading` fire on the mod event bus, not `MinecraftForge.EVENT_BUS`. The `@SubscribeEvent` handlers were registered on the wrong bus and never fired. Fixed by switching to `FMLJavaModLoadingContext.get().getModEventBus().addListener()`.
**Bug 2: Config file section headers removed.** The Chronicler's config file had values at the top level without `[discord]` section headers. ForgeConfigSpec looks for `discord.bot_token` — without the section, it can't find the values and returns defaults.
## 2. Fixes Applied (all 6 builds, v1.0.3)
- 1.20.1: Config events moved to mod event bus
- All versions: Added prominent warning comment to generated config file
- 1.20.1: Added debug logging in RulesCommand (token length + channel ID)
- INSTALL.md: Section header preservation warning added
## 3. Chronicler Deploy Steps
1. Stop Otherworld
2. Replace jar with firefrostrules-1.0.3-1.20.1-forge.jar
3. Delete config/firefrostrules-common.toml
4. Start server — generates fresh config with section headers
5. Stop server
6. Edit ONLY the values under [discord] — keep headers intact
7. Start server — check logs for "config loaded successfully"
8. Player runs /rules — should show real Discord rules

View File

@@ -10,7 +10,7 @@ buildscript {
apply plugin: 'net.minecraftforge.gradle'
version = '1.0.2'
version = '1.0.3'
group = 'com.discordrules'
archivesBaseName = 'discordrules'

View File

@@ -16,7 +16,10 @@ public class ServerRulesConfig {
static {
ForgeConfigSpec.Builder builder = new ForgeConfigSpec.Builder();
builder.push("discord");
builder.comment("Discord Rules Mod Configuration",
"IMPORTANT: Do not remove [section] headers when editing.",
"Values must stay under their section or the mod cannot read them.")
.push("discord");
BOT_TOKEN = builder.comment("Discord Bot Token").define("bot_token", "YOUR_TOKEN_HERE");
CHANNEL_ID = builder.comment("Discord Channel ID").define("channel_id", "1234567890123456789");
MESSAGE_ID = builder.comment("Discord Message ID").define("message_id", "1234567890123456789");

View File

@@ -10,7 +10,7 @@ buildscript {
apply plugin: 'net.minecraftforge.gradle'
version = '1.0.2'
version = '1.0.3'
group = 'com.discordrules'
archivesBaseName = 'discordrules'

View File

@@ -8,6 +8,7 @@ import net.minecraftforge.fml.ModLoadingContext;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.config.ModConfig;
import net.minecraftforge.fml.event.config.ModConfigEvent;
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -17,6 +18,8 @@ public class ServerRules {
public ServerRules() {
ModLoadingContext.get().registerConfig(ModConfig.Type.COMMON, ServerRulesConfig.SPEC);
FMLJavaModLoadingContext.get().getModEventBus().addListener(this::onConfigLoaded);
FMLJavaModLoadingContext.get().getModEventBus().addListener(this::onConfigReload);
MinecraftForge.EVENT_BUS.register(this);
LOGGER.info("Discord Rules Mod Initialized.");
}
@@ -32,8 +35,7 @@ public class ServerRules {
CooldownManager.removePlayer(event.getEntity().getUUID());
}
@SubscribeEvent
public void onConfigLoaded(ModConfigEvent.Loading event) {
private void onConfigLoaded(ModConfigEvent.Loading event) {
if (event.getConfig().getSpec() == ServerRulesConfig.SPEC) {
String token = ServerRulesConfig.BOT_TOKEN.get();
if (token.equals("YOUR_TOKEN_HERE")) {
@@ -44,8 +46,7 @@ public class ServerRules {
}
}
@SubscribeEvent
public void onConfigReload(ModConfigEvent.Reloading event) {
private void onConfigReload(ModConfigEvent.Reloading event) {
LOGGER.info("Rules configuration reloaded! Invalidating cache.");
RulesCache.invalidate();
}

View File

@@ -16,7 +16,10 @@ public class ServerRulesConfig {
static {
ForgeConfigSpec.Builder builder = new ForgeConfigSpec.Builder();
builder.push("discord");
builder.comment("Discord Rules Mod Configuration",
"IMPORTANT: Do not remove [section] headers when editing.",
"Values must stay under their section or the mod cannot read them.")
.push("discord");
BOT_TOKEN = builder.comment("Discord Bot Token").define("bot_token", "YOUR_TOKEN_HERE");
CHANNEL_ID = builder.comment("Discord Channel ID").define("channel_id", "1234567890123456789");
MESSAGE_ID = builder.comment("Discord Message ID").define("message_id", "1234567890123456789");

View File

@@ -6,5 +6,5 @@ neo_version=21.1.65
mod_id=discordrules
mod_name=Discord Rules
mod_version=1.0.2
mod_version=1.0.3
mod_group_id=com.discordrules

View File

@@ -16,7 +16,10 @@ public class ServerRulesConfig {
static {
ModConfigSpec.Builder builder = new ModConfigSpec.Builder();
builder.push("discord");
builder.comment("Discord Rules Mod Configuration",
"IMPORTANT: Do not remove [section] headers when editing.",
"Values must stay under their section or the mod cannot read them.")
.push("discord");
BOT_TOKEN = builder.comment("Discord Bot Token").define("bot_token", "YOUR_TOKEN_HERE");
CHANNEL_ID = builder.comment("Discord Channel ID").define("channel_id", "1234567890123456789");
MESSAGE_ID = builder.comment("Discord Message ID").define("message_id", "1234567890123456789");

View File

@@ -0,0 +1,2 @@
#Mon Apr 13 17:03:03 CDT 2026
gradle.version=7.6.4

Binary file not shown.

View File

@@ -10,7 +10,7 @@ buildscript {
apply plugin: 'net.minecraftforge.gradle'
version = '1.0.2'
version = '1.0.3'
group = 'com.firefrostgaming.rules'
archivesBaseName = 'firefrostrules'

View File

@@ -13,7 +13,10 @@ public class ServerRulesConfig {
static {
ForgeConfigSpec.Builder builder = new ForgeConfigSpec.Builder();
builder.push("discord");
builder.comment("Firefrost Rules Mod Configuration",
"IMPORTANT: Do not remove [section] headers when editing.",
"Values must stay under their section or the mod cannot read them.")
.push("discord");
BOT_TOKEN = builder.comment("Discord Bot Token").define("bot_token", "YOUR_TOKEN_HERE");
CHANNEL_ID = builder.comment("Discord Channel ID").define("channel_id", "1234567890123456789");
MESSAGE_ID = builder.comment("Discord Message ID").define("message_id", "1234567890123456789");

View File

@@ -0,0 +1,2 @@
#Mon Apr 13 17:02:56 CDT 2026
gradle.version=8.8

Binary file not shown.

View File

@@ -10,7 +10,7 @@ buildscript {
apply plugin: 'net.minecraftforge.gradle'
version = '1.0.2'
version = '1.0.3'
group = 'com.firefrostgaming.rules'
archivesBaseName = 'firefrostrules'

View File

@@ -20,6 +20,10 @@ public class RulesCommand {
return 1;
}
ServerPlayer player = (ServerPlayer) source.getEntity();
LOGGER.debug("Config state — token length: {}, channel: {}, message: {}",
ServerRulesConfig.BOT_TOKEN.get().length(),
ServerRulesConfig.CHANNEL_ID.get(),
ServerRulesConfig.MESSAGE_ID.get());
if (!CooldownManager.checkAndUpdateCooldown(player)) return 0;
if (RulesCache.isCacheValid()) {
player.sendSystemMessage(DiscordFormatter.formatRules(RulesCache.getRules()));

View File

@@ -8,6 +8,7 @@ import net.minecraftforge.fml.ModLoadingContext;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.config.ModConfig;
import net.minecraftforge.fml.event.config.ModConfigEvent;
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -17,6 +18,8 @@ public class ServerRules {
public ServerRules() {
ModLoadingContext.get().registerConfig(ModConfig.Type.COMMON, ServerRulesConfig.SPEC);
FMLJavaModLoadingContext.get().getModEventBus().addListener(this::onConfigLoaded);
FMLJavaModLoadingContext.get().getModEventBus().addListener(this::onConfigReload);
MinecraftForge.EVENT_BUS.register(this);
LOGGER.info("Firefrost Rules Mod Initialized.");
}
@@ -32,8 +35,7 @@ public class ServerRules {
CooldownManager.removePlayer(event.getEntity().getUUID());
}
@SubscribeEvent
public void onConfigLoaded(ModConfigEvent.Loading event) {
private void onConfigLoaded(ModConfigEvent.Loading event) {
if (event.getConfig().getSpec() == ServerRulesConfig.SPEC) {
String token = ServerRulesConfig.BOT_TOKEN.get();
if (token.equals("YOUR_TOKEN_HERE")) {
@@ -44,8 +46,7 @@ public class ServerRules {
}
}
@SubscribeEvent
public void onConfigReload(ModConfigEvent.Reloading event) {
private void onConfigReload(ModConfigEvent.Reloading event) {
LOGGER.info("Rules configuration reloaded! Invalidating cache.");
RulesCache.invalidate();
}

View File

@@ -13,7 +13,10 @@ public class ServerRulesConfig {
static {
ForgeConfigSpec.Builder builder = new ForgeConfigSpec.Builder();
builder.push("discord");
builder.comment("Firefrost Rules Mod Configuration",
"IMPORTANT: Do not remove [section] headers when editing.",
"Values must stay under their section or the mod cannot read them.")
.push("discord");
BOT_TOKEN = builder.comment("Discord Bot Token").define("bot_token", "YOUR_TOKEN_HERE");
CHANNEL_ID = builder.comment("Discord Channel ID").define("channel_id", "1234567890123456789");
MESSAGE_ID = builder.comment("Discord Message ID").define("message_id", "1234567890123456789");

View File

@@ -0,0 +1,2 @@
#Mon Apr 13 17:02:47 CDT 2026
gradle.version=8.8

Binary file not shown.

View File

@@ -6,5 +6,5 @@ neo_version=21.1.65
mod_id=firefrostrules
mod_name=Firefrost Rules
mod_version=1.0.2
mod_version=1.0.3
mod_group_id=com.firefrostgaming.rules

View File

@@ -13,7 +13,10 @@ public class ServerRulesConfig {
static {
ModConfigSpec.Builder builder = new ModConfigSpec.Builder();
builder.push("discord");
builder.comment("Firefrost Rules Mod Configuration",
"IMPORTANT: Do not remove [section] headers when editing.",
"Values must stay under their section or the mod cannot read them.")
.push("discord");
BOT_TOKEN = builder.comment("Discord Bot Token").define("bot_token", "YOUR_TOKEN_HERE");
CHANNEL_ID = builder.comment("Discord Channel ID").define("channel_id", "1234567890123456789");
MESSAGE_ID = builder.comment("Discord Message ID").define("message_id", "1234567890123456789");

View File

@@ -1,5 +1,21 @@
# Rules Mod Changelog
## [1.0.3] - 2026-04-13
### Fixed
- **1.20.1: Config events on wrong bus** — `ModConfigEvent.Loading` and `Reloading` fire on the mod event bus, not `MinecraftForge.EVENT_BUS`. Moved to `FMLJavaModLoadingContext.getModEventBus().addListener()`
- **Config file section headers** — values placed outside `[discord]` section are invisible to the spec. Added prominent warning comments to generated config file
### Added
- Debug logging in RulesCommand (1.20.1) prints token length + channel ID at command time
- Config file header comment: "Do not remove [section] headers when editing"
- INSTALL.md updated with section header preservation warning
### Applies To
- All 6 builds bumped to 1.0.3
---
## [1.0.2] - 2026-04-13
### Fixed

View File

@@ -9,6 +9,8 @@
- Set `bot_token` to your Discord bot token
- Set `channel_id` to the channel containing your rules message
- Set `message_id` to the specific message ID
- **IMPORTANT: Keep the [discord] and [performance] section headers!**
- Only change the values, not the file structure
5. Start the server again
## Verify It Worked