plugins/Halt/. Most keys apply after /halt reload. Invalid YAML, wrong types, or bad enum values are rejected; the last known-good config stays active and /halt reload reports reload_failed.
Do not use Bukkit /reload. Use /halt reload or a full restart.
Boolean fields must be true or false. Severity values are INFO, LOW, MEDIUM, HIGH, CRITICAL. CrashGuard actions are ALERT, ALERT_CANCEL, ALERT_KICK.
config.yml
plugins/Halt/config.yml
- Disabling
lockdownsuppresses lockdown commands, active state, history, and restriction enforcement - Disabling
incident_logsuppresses new incident persistence and incident command results - Disabling
alert_bridgesuppresses staff, console, and Discord fan-out;/halt webhook testreports disabled
containment.mode is off, contain, or lockdown. /halt arm and /halt setup <watch|contain|lockdown> persist this key. ttl_seconds: 0 means until staff runs /halt contain off. kick_on_critical kicks only that player after containment starts; it never bans.
punish.enabled is off by default. When on, /halt incident <id> punish runs owner punish.commands with {player} {uuid} {incident} {type} {severity}. Still not auto-ban.
lockdown.suggest_on_critical adds suggest copy for CRITICAL incidents while unarmed. It never auto-starts lockdown.
checks.yml
Four watch families. Each check has enabled, windows, thresholds, cooldown_seconds, and either an action (CrashGuard) or severity (the others). Cooldowns suppress repeated incident/risk creation for the same check key; the check action (cancel/kick) can still run.
CrashGuard
Command spam, inventory click bursts, book/sign text limits, failed interactions, anvil rename length, container-open spam.ignored_commands is only for command spam (base command label, no slash).
anvil_rename_limit measures PrepareAnvilEvent rename length. container_open_spam uses rapid InventoryOpenEvent counts. Missing sections in older checks.yml files stay disabled.
DupeWatch
Shulker cycles, hopper bursts, drop/pickup loops, high-value growth, death-drop recovery, ender-chest swap, bundle churn, villager trade burst.high_value_growth and death_drop_recovery use valuable_items weights times item amount. Pickups matching the player’s own recent drop, including partial pickups from the same dropped stack, count as one drop/pickup-loop cycle per stack, not item-growth evidence. ender_chest_swap, bundle_churn, and villager_trade_burst are alert-first; they do not cancel the click. Armed containment is the cancel path.
MineWatch
enabled_worlds means all worlds. A non-empty list is an allowlist. alert_ratio is weighted ore score across the sample window (ore_weights); it must be greater than 0 and at most 1. direct_ore_path counts short non-ore runs that lead into valuable ore. y_band_cluster is a weighted-ore spike inside a tight Y/radius window.
FreecamWatch
max_distance and max_angle_degrees must be greater than 0. geyser_lenient (default true) uses geyser_max_distance / geyser_max_angle_degrees for Geyser/Floodgate client brands. See Modules.
Material keys in valuable_items and ore_weights are trimmed and uppercased. Weights must be positive integers. Duplicate keys after normalization are rejected.
lockdowns.yml
Must define at least one profile. blocked_commands entries must be non-blank scalars (no leading slash). Copy extra shop plugin labels from examples/lockdown-command-packs.yml in the jar.
plugins/Halt/lockdowns.yml
alerts.yml
plugins/Halt/alerts.yml
config.yml alerts.discord: true, alerts.yml discord.enabled: true, a valid http or https webhook_url with a host, and rate_limit_per_minute above zero. Enabled Discord alerts are embeds with severity-colored sidebars, sent on the async scheduler, still rate-limited.
Staff chat format and MiniMessage strings live here. Missing messages entries fall back to packaged English defaults. Visible GUI titles still come from locale MiniMessage in locale/en_us.yml, not from gui.yml title strings.
Alert template placeholders: {id}, {type} / {type_label}, {player}, {severity} / {severity_label} / {severity_styled}, {summary}, {status}, {world} / {x} / {y} / {z}, {brand}, {suggest_suffix} (CRITICAL lockdown suggest while unarmed; armed HIGH/CRITICAL uses contain-off copy instead).
gui.yml
Staff list chrome (incidents, scan picker): slots 0 search, 2 sort, 4 type/scope filter, 6 status filter (incidents only), 8 reset, 45 previous, 49 back, 53 next. Set a button to -1 to hide it. Hub, lockdown, and incident detail do not use this chrome.
Reload vs restart
Safe to reload: messages, display settings,gui.yml list chrome, most thresholds, containment.mode, module settings where listeners can be re-registered.
Restart required: storage.type, storage.sqlite.file, any storage.mysql value. Those keys are rejected during /halt reload.