Diagnostics
New in 6.1.0 · Requires History Stages 6.1.0+ on NeoForge 1.21, Forge 1.20.1 or
Fabric 1.21.1. On Fabric both events reach registerStageChecks and registerReportSections of
the plugin. → On Fabric
The debug report a pack author attaches to a bug is also yours. An addon can check its own data
in every stage file, add a block of its own to the report, and write lines into the runtime log.
Everything here lives in net.bananemdnsa.historystages.api.diagnostics.
The report itself is config/historystages/logs/debug-*.log, written at every world start and after
/history reload. Its header names every mod that uses the API, so a report already shows that your
addon is installed. → Getting Help
Checking stage data
Register a StageCheck on the mod bus. It runs once per loaded stage, after History Stages' own
checks:
modEventBus.addListener(RegisterStageChecksEvent.class, event ->
event.register("mymod:relic_sets", ctx -> {
for (String set : MyCategory.get().read(ctx.entry())) {
if (!RelicSets.exists(set)) {
ctx.problems().warn("Relic Sets", "Unknown relic set '" + set + "'.");
}
}
}));
- It runs when the world starts and after
/history reload. Registries are complete by then, so item and entity ids can be looked up. It does not run while the stage files load, because stages load before the registries are filled. - What it reports lands in the report under that stage's file. Errors and warnings also go to
latest.log. ctx.problems()haserror,warnandinfo. Error: the stage cannot work as written. Warn: it works, but probably not as meant. Info: worth knowing.- Your namespace is put in front of the category, so
warn("Relic Sets", …)frommymod:shows asmymod: Relic Sets. - Keep it to reading. A check must not change the stage.
- A check that throws is reported in the report, never thrown on.
A section of your own
A ReportSection adds a block to the report — your version, counts, anything that helps when someone
attaches it to a bug:
modEventBus.addListener(RegisterReportSectionsEvent.class, event ->
event.register("mymod:relics", "Relic sets",
out -> out.value("Sets loaded", RelicSets.count())));
ReportWriter has line(String) and value(String label, Object value); History Stages does the
indenting. It is called every time the report is written. A section that writes nothing is left
out; one that throws shows the exception, and the report carries on.
History Stages' own lock totals and config sections are registered the same way.
Runtime log lines
The runtime log, config/historystages/logs/runtime-*.log, records what happens during play while a
pack has enableRuntimeLogging on. Keep a category as a constant and write through RuntimeLog:
static final RuntimeCategory RELIC_LOCK =
RuntimeCategory.of("mymod:relic_lock", "Relic Lock", Kind.LOCK);
RuntimeLog.write(RELIC_LOCK, player, "Opened a sealed relic.");
| Method | What it does |
|---|---|
write(RuntimeCategory, String) | one line |
write(RuntimeCategory, ServerPlayer, String) | one line, starting with <player name> |
throttled(RuntimeCategory, String key, String) | at most one line per key every five seconds, for things that can happen every tick |
Kind is the column a reader skims by: LOCK (a lock stopped something), STAGE (a stage was
gained, lost or refused), ADMIN (a command or the editor changed something) and SYSTEM (the mod
itself).
No registration: two categories with the same id are the same category. With logging off,
RuntimeLog does nothing, so a call on a hot path costs one config read. Lines are buffered and
written every 30 seconds. Throttle keys are kept apart per category, so an addon cannot silence one
of History Stages' own lines.