summaryrefslogtreecommitdiff
path: root/engine
diff options
context:
space:
mode:
authorSho Sakuma <me@m1sk9.dev>2026-08-30 21:11:46 +0900
committerSho Sakuma <me@m1sk9.dev>2026-08-30 21:11:46 +0900
commit1c79bee8f3c8fe20582afa96527cd298c043daa5 (patch)
tree1c28055f6296d7866ea3916a65a005be2fb1a6bc /engine
parent68052ce335ae11c4cb10a388848b42571bfc65b9 (diff)
downloadLunaticChat-1c79bee8f3c8fe20582afa96527cd298c043daa5.tar.gz
LunaticChat-1c79bee8f3c8fe20582afa96527cd298c043daa5.tar.bz2
LunaticChat-1c79bee8f3c8fe20582afa96527cd298c043daa5.zip
fix(paper): stop the command category logging on every tree build
Three findings from review of #296. Brigadier evaluates a `requires` predicate when it builds the command tree it sends to a player - on every join and every updateCommands() - not when someone is refused. The denial line sitting there put one entry per gated node per player in the log, burying the command results the category exists to show. It is dropped rather than moved: a hidden node is never reached by an execution, so there is no refusal path to log from. `all` was honoured by `debug: all` and `/lc debug all on` but not by `categories: [all]`, which resolved to an unknown name - leaving `enabled: true` with nothing switched on, reported as off by /lc status, explained only by a warning in the log. The word now lives in one place that all three read. Two dumps in the same second left one file, because the name is only accurate to the second and the write replaces. Reproducing a bug means dumping either side of the step that triggers it, so the second one now takes a suffix. Co-Authored-By: Claude <noreply@anthropic.com>
Diffstat (limited to 'engine')
-rw-r--r--engine/src/main/kotlin/dev/m1sk9/lunaticChat/engine/debug/DebugCategories.kt13
-rw-r--r--engine/src/main/kotlin/dev/m1sk9/lunaticChat/engine/debug/DebugCategory.kt3
-rw-r--r--engine/src/test/kotlin/dev/m1sk9/lunaticChat/engine/debug/DebugCategoriesTest.kt17
3 files changed, 32 insertions, 1 deletions
diff --git a/engine/src/main/kotlin/dev/m1sk9/lunaticChat/engine/debug/DebugCategories.kt b/engine/src/main/kotlin/dev/m1sk9/lunaticChat/engine/debug/DebugCategories.kt
index 3231295..c3d7d95 100644
--- a/engine/src/main/kotlin/dev/m1sk9/lunaticChat/engine/debug/DebugCategories.kt
+++ b/engine/src/main/kotlin/dev/m1sk9/lunaticChat/engine/debug/DebugCategories.kt
@@ -19,7 +19,10 @@ object DebugCategories {
val active: Set<DebugCategory> get() = if (enabled) categories else emptySet()
}
- private val allWords = setOf("true", "yes", "on", "y", "all")
+ /** The word that stands for every category at once, wherever a category may be named. */
+ const val ALL = "all"
+
+ private val allWords = setOf("true", "yes", "on", "y", ALL)
private val noneWords = setOf("false", "no", "off", "n", "none")
/**
@@ -48,6 +51,14 @@ object DebugCategories {
.map { it.trim() }
.filter { it.isNotEmpty() }
.forEach { name ->
+ // [ALL] is honoured here as well as in [parse] and /lc debug: an operator who has
+ // read `debug: all` or `/lc debug all on` writes `categories: [all]` next, and
+ // reporting that as an unknown name would leave them with a switch that logs
+ // nothing while saying it is on.
+ if (name.equals(ALL, ignoreCase = true)) {
+ categories += DebugCategory.entries
+ return@forEach
+ }
val category = DebugCategory.fromKey(name)
if (category == null) unknown += name else categories += category
}
diff --git a/engine/src/main/kotlin/dev/m1sk9/lunaticChat/engine/debug/DebugCategory.kt b/engine/src/main/kotlin/dev/m1sk9/lunaticChat/engine/debug/DebugCategory.kt
index 9c12a92..40cc0e8 100644
--- a/engine/src/main/kotlin/dev/m1sk9/lunaticChat/engine/debug/DebugCategory.kt
+++ b/engine/src/main/kotlin/dev/m1sk9/lunaticChat/engine/debug/DebugCategory.kt
@@ -23,6 +23,9 @@ enum class DebugCategory(
companion object {
private val byKey = entries.associateBy { it.key }
+ /** Every [key], for the "known categories are ..." half of a message about a typo. */
+ val keyList: String = entries.joinToString(", ") { it.key }
+
/** The category [key] names, or null when no category is spelled that way. */
fun fromKey(key: String): DebugCategory? = byKey[key.trim().lowercase()]
}
diff --git a/engine/src/test/kotlin/dev/m1sk9/lunaticChat/engine/debug/DebugCategoriesTest.kt b/engine/src/test/kotlin/dev/m1sk9/lunaticChat/engine/debug/DebugCategoriesTest.kt
index 44ccb86..5931c60 100644
--- a/engine/src/test/kotlin/dev/m1sk9/lunaticChat/engine/debug/DebugCategoriesTest.kt
+++ b/engine/src/test/kotlin/dev/m1sk9/lunaticChat/engine/debug/DebugCategoriesTest.kt
@@ -68,6 +68,23 @@ class DebugCategoriesTest {
}
@Test
+ fun `all names every category wherever a category may be named`() {
+ // The same word works as `debug: all`, as `categories: [all]` and as `/lc debug all on`;
+ // reading it as a category name in only two of the three would log nothing for the third.
+ assertEquals(DebugCategory.entries.toSet(), DebugCategories.parse("all").active)
+ assertEquals(DebugCategory.entries.toSet(), DebugCategories.resolve(listOf("all")).active)
+ assertEquals(emptyList(), DebugCategories.resolve(listOf("ALL")).unknown)
+ }
+
+ @Test
+ fun `all beside a named category still names every category`() {
+ val parsed = DebugCategories.resolve(listOf("velocity", "all"))
+
+ assertEquals(DebugCategory.entries.toSet(), parsed.active)
+ assertEquals(emptyList(), parsed.unknown)
+ }
+
+ @Test
fun `every category is reachable by the key operators write`() {
DebugCategory.entries.forEach { category ->
assertEquals(category, DebugCategory.fromKey(category.key))