diff --git a/ReadMe.md b/ReadMe.md
index aa40faea8..bb0b4d296 100644
--- a/ReadMe.md
+++ b/ReadMe.md
@@ -48,7 +48,7 @@ Minosoft is an open source minecraft client, written from scratch in kotlin (and
- GUI (inventory, menus)
- block entities (e.g. signs, chests)
- basic entity rendering (hitboxes)
-- ~~original physics~
+- ~~original physics~~

A world, with a ton of hud features exposed
diff --git a/pom.xml b/pom.xml
index 2bf2a399b..edac5a867 100644
--- a/pom.xml
+++ b/pom.xml
@@ -499,5 +499,11 @@
fastutil-core
8.5.8
+
+ org.junit.jupiter
+ junit-jupiter-api
+ 5.8.2
+ test
+
diff --git a/src/main/java/de/bixilon/minosoft/commands/errors/ReaderError.kt b/src/main/java/de/bixilon/minosoft/commands/errors/ReaderError.kt
new file mode 100644
index 000000000..32e153093
--- /dev/null
+++ b/src/main/java/de/bixilon/minosoft/commands/errors/ReaderError.kt
@@ -0,0 +1,22 @@
+/*
+ * Minosoft
+ * Copyright (C) 2020-2022 Moritz Zwerger
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If not, see .
+ *
+ * This software is not affiliated with Mojang AB, the original developer of Minecraft.
+ */
+
+package de.bixilon.minosoft.commands.errors
+
+import de.bixilon.minosoft.commands.util.CommandReader
+
+abstract class ReaderError(
+ val reader: CommandReader,
+ val start: Int,
+ val end: Int,
+) : Exception("Error at $start-$end: ${reader.string}")
diff --git a/src/main/java/de/bixilon/minosoft/commands/errors/parser/ParserError.kt b/src/main/java/de/bixilon/minosoft/commands/errors/parser/ParserError.kt
new file mode 100644
index 000000000..d72b519ca
--- /dev/null
+++ b/src/main/java/de/bixilon/minosoft/commands/errors/parser/ParserError.kt
@@ -0,0 +1,20 @@
+/*
+ * Minosoft
+ * Copyright (C) 2020-2022 Moritz Zwerger
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If not, see .
+ *
+ * This software is not affiliated with Mojang AB, the original developer of Minecraft.
+ */
+
+package de.bixilon.minosoft.commands.errors.parser
+
+import de.bixilon.minosoft.commands.errors.ReaderError
+import de.bixilon.minosoft.commands.util.CommandReader
+import de.bixilon.minosoft.commands.util.ReadResult
+
+abstract class ParserError(reader: CommandReader, val result: ReadResult<*>) : ReaderError(reader, result.start, result.end)
diff --git a/src/main/java/de/bixilon/minosoft/commands/errors/reader/InvalidPeekError.kt b/src/main/java/de/bixilon/minosoft/commands/errors/reader/InvalidPeekError.kt
new file mode 100644
index 000000000..0db185ecf
--- /dev/null
+++ b/src/main/java/de/bixilon/minosoft/commands/errors/reader/InvalidPeekError.kt
@@ -0,0 +1,24 @@
+/*
+ * Minosoft
+ * Copyright (C) 2020-2022 Moritz Zwerger
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If not, see .
+ *
+ * This software is not affiliated with Mojang AB, the original developer of Minecraft.
+ */
+
+package de.bixilon.minosoft.commands.errors.reader
+
+import de.bixilon.minosoft.commands.errors.ReaderError
+import de.bixilon.minosoft.commands.util.CommandReader
+
+class InvalidPeekError(
+ reader: CommandReader,
+ pointer: Int,
+ val found: Int,
+ val required: IntArray,
+) : ReaderError(reader, pointer, pointer + 1)
diff --git a/src/main/java/de/bixilon/minosoft/commands/errors/reader/InvalidReadError.kt b/src/main/java/de/bixilon/minosoft/commands/errors/reader/InvalidReadError.kt
new file mode 100644
index 000000000..399d2d40e
--- /dev/null
+++ b/src/main/java/de/bixilon/minosoft/commands/errors/reader/InvalidReadError.kt
@@ -0,0 +1,24 @@
+/*
+ * Minosoft
+ * Copyright (C) 2020-2022 Moritz Zwerger
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If not, see .
+ *
+ * This software is not affiliated with Mojang AB, the original developer of Minecraft.
+ */
+
+package de.bixilon.minosoft.commands.errors.reader
+
+import de.bixilon.minosoft.commands.errors.ReaderError
+import de.bixilon.minosoft.commands.util.CommandReader
+
+class InvalidReadError(
+ reader: CommandReader,
+ pointer: Int,
+ val found: Int,
+ val required: IntArray,
+) : ReaderError(reader, pointer, pointer + 1)
diff --git a/src/main/java/de/bixilon/minosoft/commands/errors/reader/OutOfBoundsError.kt b/src/main/java/de/bixilon/minosoft/commands/errors/reader/OutOfBoundsError.kt
new file mode 100644
index 000000000..9c9bdd31a
--- /dev/null
+++ b/src/main/java/de/bixilon/minosoft/commands/errors/reader/OutOfBoundsError.kt
@@ -0,0 +1,22 @@
+/*
+ * Minosoft
+ * Copyright (C) 2020-2022 Moritz Zwerger
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If not, see .
+ *
+ * This software is not affiliated with Mojang AB, the original developer of Minecraft.
+ */
+
+package de.bixilon.minosoft.commands.errors.reader
+
+import de.bixilon.minosoft.commands.errors.ReaderError
+import de.bixilon.minosoft.commands.util.CommandReader
+
+class OutOfBoundsError(
+ reader: CommandReader,
+ start: Int,
+) : ReaderError(reader, start, reader.length)
diff --git a/src/main/java/de/bixilon/minosoft/commands/errors/reader/UnexpectedBackslashError.kt b/src/main/java/de/bixilon/minosoft/commands/errors/reader/UnexpectedBackslashError.kt
new file mode 100644
index 000000000..b7ef5a9e9
--- /dev/null
+++ b/src/main/java/de/bixilon/minosoft/commands/errors/reader/UnexpectedBackslashError.kt
@@ -0,0 +1,24 @@
+/*
+ * Minosoft
+ * Copyright (C) 2020-2022 Moritz Zwerger
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If not, see .
+ *
+ * This software is not affiliated with Mojang AB, the original developer of Minecraft.
+ */
+
+package de.bixilon.minosoft.commands.errors.reader
+
+import de.bixilon.minosoft.commands.errors.ReaderError
+import de.bixilon.minosoft.commands.util.CommandReader
+
+class UnexpectedBackslashError(
+ reader: CommandReader,
+ start: Int,
+ end: Int,
+ val read: Int,
+) : ReaderError(reader, start, end)
diff --git a/src/main/java/de/bixilon/minosoft/commands/errors/reader/UnfinishedQuotedStringError.kt b/src/main/java/de/bixilon/minosoft/commands/errors/reader/UnfinishedQuotedStringError.kt
new file mode 100644
index 000000000..6f459ec0c
--- /dev/null
+++ b/src/main/java/de/bixilon/minosoft/commands/errors/reader/UnfinishedQuotedStringError.kt
@@ -0,0 +1,22 @@
+/*
+ * Minosoft
+ * Copyright (C) 2020-2022 Moritz Zwerger
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If not, see .
+ *
+ * This software is not affiliated with Mojang AB, the original developer of Minecraft.
+ */
+
+package de.bixilon.minosoft.commands.errors.reader
+
+import de.bixilon.minosoft.commands.errors.ReaderError
+import de.bixilon.minosoft.commands.util.CommandReader
+
+class UnfinishedQuotedStringError(
+ reader: CommandReader,
+ start: Int,
+) : ReaderError(reader, start, reader.length)
diff --git a/src/main/java/de/bixilon/minosoft/commands/errors/suggestion/NoSuggestionError.kt b/src/main/java/de/bixilon/minosoft/commands/errors/suggestion/NoSuggestionError.kt
new file mode 100644
index 000000000..5cccefe29
--- /dev/null
+++ b/src/main/java/de/bixilon/minosoft/commands/errors/suggestion/NoSuggestionError.kt
@@ -0,0 +1,23 @@
+/*
+ * Minosoft
+ * Copyright (C) 2020-2022 Moritz Zwerger
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If not, see .
+ *
+ * This software is not affiliated with Mojang AB, the original developer of Minecraft.
+ */
+
+package de.bixilon.minosoft.commands.errors.suggestion
+
+import de.bixilon.minosoft.commands.errors.parser.ParserError
+import de.bixilon.minosoft.commands.util.CommandReader
+import de.bixilon.minosoft.commands.util.ReadResult
+
+class NoSuggestionError(
+ reader: CommandReader,
+ result: ReadResult<*>,
+) : ParserError(reader, result)
diff --git a/src/main/java/de/bixilon/minosoft/commands/nodes/ArgumentNode.kt b/src/main/java/de/bixilon/minosoft/commands/nodes/ArgumentNode.kt
new file mode 100644
index 000000000..8e6fd90e2
--- /dev/null
+++ b/src/main/java/de/bixilon/minosoft/commands/nodes/ArgumentNode.kt
@@ -0,0 +1,38 @@
+/*
+ * Minosoft
+ * Copyright (C) 2020-2022 Moritz Zwerger
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If not, see .
+ *
+ * This software is not affiliated with Mojang AB, the original developer of Minecraft.
+ */
+
+package de.bixilon.minosoft.commands.nodes
+
+import de.bixilon.minosoft.commands.parser.ArgumentParser
+import de.bixilon.minosoft.commands.stack.CommandExecutor
+import de.bixilon.minosoft.commands.suggestion.types.SuggestionType
+
+class ArgumentNode : ExecutableNode {
+ private val parser: ArgumentParser<*>
+
+ constructor(
+ name: String,
+ parser: ArgumentParser<*>,
+ suggestion: SuggestionType<*>? = null,
+ executable: Boolean = false,
+ redirect: CommandNode? = null,
+ ) : super(name, suggestion, false, null, executable, redirect) {
+ this.parser = parser
+ }
+
+
+ constructor(name: String, parser: ArgumentParser<*>, onlyDirectExecution: Boolean = true, executor: CommandExecutor) : super(name, executable = true, onlyDirectExecution = onlyDirectExecution, executor = executor) {
+ this.executor = executor
+ this.parser = parser
+ }
+}
diff --git a/src/main/java/de/bixilon/minosoft/commands/nodes/CommandNode.kt b/src/main/java/de/bixilon/minosoft/commands/nodes/CommandNode.kt
new file mode 100644
index 000000000..f46103bbd
--- /dev/null
+++ b/src/main/java/de/bixilon/minosoft/commands/nodes/CommandNode.kt
@@ -0,0 +1,19 @@
+/*
+ * Minosoft
+ * Copyright (C) 2020-2022 Moritz Zwerger
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If not, see .
+ *
+ * This software is not affiliated with Mojang AB, the original developer of Minecraft.
+ */
+
+package de.bixilon.minosoft.commands.nodes
+
+abstract class CommandNode(
+ val executable: Boolean,
+ val redirect: CommandNode?,
+)
diff --git a/src/main/java/de/bixilon/minosoft/commands/nodes/ExecutableNode.kt b/src/main/java/de/bixilon/minosoft/commands/nodes/ExecutableNode.kt
new file mode 100644
index 000000000..fa1167ff5
--- /dev/null
+++ b/src/main/java/de/bixilon/minosoft/commands/nodes/ExecutableNode.kt
@@ -0,0 +1,26 @@
+/*
+ * Minosoft
+ * Copyright (C) 2020-2022 Moritz Zwerger
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If not, see .
+ *
+ * This software is not affiliated with Mojang AB, the original developer of Minecraft.
+ */
+
+package de.bixilon.minosoft.commands.nodes
+
+import de.bixilon.minosoft.commands.stack.CommandExecutor
+import de.bixilon.minosoft.commands.suggestion.types.SuggestionType
+
+abstract class ExecutableNode(
+ val name: String,
+ val suggestion: SuggestionType<*>? = null,
+ var onlyDirectExecution: Boolean = true,
+ var executor: CommandExecutor? = null,
+ executable: Boolean = executor != null,
+ redirect: CommandNode? = null,
+) : CommandNode(executable, redirect)
diff --git a/src/main/java/de/bixilon/minosoft/commands/nodes/LiteralNode.kt b/src/main/java/de/bixilon/minosoft/commands/nodes/LiteralNode.kt
new file mode 100644
index 000000000..77ac7bc82
--- /dev/null
+++ b/src/main/java/de/bixilon/minosoft/commands/nodes/LiteralNode.kt
@@ -0,0 +1,30 @@
+/*
+ * Minosoft
+ * Copyright (C) 2020-2022 Moritz Zwerger
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If not, see .
+ *
+ * This software is not affiliated with Mojang AB, the original developer of Minecraft.
+ */
+
+package de.bixilon.minosoft.commands.nodes
+
+import de.bixilon.minosoft.commands.stack.CommandExecutor
+import de.bixilon.minosoft.commands.suggestion.types.SuggestionType
+
+class LiteralNode : ExecutableNode {
+
+ constructor(
+ name: String,
+ suggestion: SuggestionType<*>? = null,
+ executable: Boolean = false,
+ redirect: CommandNode? = null,
+ ) : super(name, suggestion, false, null, executable, redirect)
+
+
+ constructor(name: String, onlyDirectExecution: Boolean = true, executor: CommandExecutor) : super(name, onlyDirectExecution = onlyDirectExecution, executor = executor, executable = true)
+}
diff --git a/src/main/java/de/bixilon/minosoft/commands/nodes/NamedNode.kt b/src/main/java/de/bixilon/minosoft/commands/nodes/NamedNode.kt
new file mode 100644
index 000000000..60bf72594
--- /dev/null
+++ b/src/main/java/de/bixilon/minosoft/commands/nodes/NamedNode.kt
@@ -0,0 +1,23 @@
+/*
+ * Minosoft
+ * Copyright (C) 2020-2022 Moritz Zwerger
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If not, see .
+ *
+ * This software is not affiliated with Mojang AB, the original developer of Minecraft.
+ */
+
+package de.bixilon.minosoft.commands.nodes
+
+import de.bixilon.minosoft.commands.suggestion.types.SuggestionType
+
+abstract class NamedNode(
+ val name: String,
+ val suggestion: SuggestionType<*>?,
+ executable: Boolean,
+ redirect: CommandNode?,
+) : CommandNode(executable, redirect)
diff --git a/src/main/java/de/bixilon/minosoft/commands/nodes/RootNode.kt b/src/main/java/de/bixilon/minosoft/commands/nodes/RootNode.kt
new file mode 100644
index 000000000..ec9a9318f
--- /dev/null
+++ b/src/main/java/de/bixilon/minosoft/commands/nodes/RootNode.kt
@@ -0,0 +1,16 @@
+/*
+ * Minosoft
+ * Copyright (C) 2020-2022 Moritz Zwerger
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If not, see .
+ *
+ * This software is not affiliated with Mojang AB, the original developer of Minecraft.
+ */
+
+package de.bixilon.minosoft.commands.nodes
+
+class RootNode : CommandNode(false, null)
diff --git a/src/main/java/de/bixilon/minosoft/commands/parser/ArgumentParser.kt b/src/main/java/de/bixilon/minosoft/commands/parser/ArgumentParser.kt
new file mode 100644
index 000000000..282855a42
--- /dev/null
+++ b/src/main/java/de/bixilon/minosoft/commands/parser/ArgumentParser.kt
@@ -0,0 +1,28 @@
+/*
+ * Minosoft
+ * Copyright (C) 2020-2022 Moritz Zwerger
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If not, see .
+ *
+ * This software is not affiliated with Mojang AB, the original developer of Minecraft.
+ */
+
+package de.bixilon.minosoft.commands.parser
+
+import de.bixilon.minosoft.commands.util.CommandReader
+import de.bixilon.minosoft.data.text.ChatComponent
+import de.bixilon.minosoft.protocol.protocol.PlayInByteBuffer
+
+interface ArgumentParser {
+ val examples: List
+ val placeholder: ChatComponent
+
+ fun parse(reader: CommandReader): T
+ fun getSuggestions(reader: CommandReader): List
+
+ fun read(buffer: PlayInByteBuffer) = Unit
+}
diff --git a/src/main/java/de/bixilon/minosoft/commands/parser/brigadier/BrigadierParser.kt b/src/main/java/de/bixilon/minosoft/commands/parser/brigadier/BrigadierParser.kt
new file mode 100644
index 000000000..eeb819a36
--- /dev/null
+++ b/src/main/java/de/bixilon/minosoft/commands/parser/brigadier/BrigadierParser.kt
@@ -0,0 +1,18 @@
+/*
+ * Minosoft
+ * Copyright (C) 2020-2022 Moritz Zwerger
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If not, see .
+ *
+ * This software is not affiliated with Mojang AB, the original developer of Minecraft.
+ */
+
+package de.bixilon.minosoft.commands.parser.brigadier
+
+import de.bixilon.minosoft.commands.parser.ArgumentParser
+
+interface BrigadierParser : ArgumentParser
diff --git a/src/main/java/de/bixilon/minosoft/commands/parser/brigadier/bool/BooleanParseError.kt b/src/main/java/de/bixilon/minosoft/commands/parser/brigadier/bool/BooleanParseError.kt
new file mode 100644
index 000000000..05d8f4080
--- /dev/null
+++ b/src/main/java/de/bixilon/minosoft/commands/parser/brigadier/bool/BooleanParseError.kt
@@ -0,0 +1,23 @@
+/*
+ * Minosoft
+ * Copyright (C) 2020-2022 Moritz Zwerger
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If not, see .
+ *
+ * This software is not affiliated with Mojang AB, the original developer of Minecraft.
+ */
+
+package de.bixilon.minosoft.commands.parser.brigadier.bool
+
+import de.bixilon.minosoft.commands.errors.parser.ParserError
+import de.bixilon.minosoft.commands.util.CommandReader
+import de.bixilon.minosoft.commands.util.ReadResult
+
+class BooleanParseError(
+ reader: CommandReader,
+ result: ReadResult,
+) : ParserError(reader, result)
diff --git a/src/main/java/de/bixilon/minosoft/commands/parser/brigadier/bool/BooleanParser.kt b/src/main/java/de/bixilon/minosoft/commands/parser/brigadier/bool/BooleanParser.kt
new file mode 100644
index 000000000..135be035c
--- /dev/null
+++ b/src/main/java/de/bixilon/minosoft/commands/parser/brigadier/bool/BooleanParser.kt
@@ -0,0 +1,53 @@
+/*
+ * Minosoft
+ * Copyright (C) 2020-2022 Moritz Zwerger
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If not, see .
+ *
+ * This software is not affiliated with Mojang AB, the original developer of Minecraft.
+ */
+
+package de.bixilon.minosoft.commands.parser.brigadier.bool
+
+import de.bixilon.minosoft.commands.errors.suggestion.NoSuggestionError
+import de.bixilon.minosoft.commands.parser.brigadier.BrigadierParser
+import de.bixilon.minosoft.commands.parser.factory.ArgumentFactory
+import de.bixilon.minosoft.commands.suggestion.ArraySuggestion
+import de.bixilon.minosoft.commands.util.CommandReader
+import de.bixilon.minosoft.data.registries.ResourceLocation
+import de.bixilon.minosoft.data.text.ChatComponent
+import de.bixilon.minosoft.protocol.network.connection.play.PlayConnection
+import de.bixilon.minosoft.util.KUtil.toResourceLocation
+
+object BooleanParser : BrigadierParser, ArgumentFactory {
+ override val RESOURCE_LOCATION: ResourceLocation = "brigadier:bool".toResourceLocation()
+ override val examples: List = listOf(true, false)
+ private val suggestion = ArraySuggestion(examples)
+ override val placeholder = ChatComponent.of("")
+
+ override fun parse(reader: CommandReader): Boolean {
+ reader.readResult { reader.readBoolean() }.let { return it.result ?: throw BooleanParseError(reader, it) }
+ }
+
+ fun CommandReader.readBoolean(): Boolean? {
+ return when (readUnquotedString()) {
+ "true" -> true
+ "false" -> false
+ else -> null
+ }
+ }
+
+ override fun getSuggestions(reader: CommandReader): List {
+ val text = reader.readResult { reader.readUnquotedString() }
+ if (text.result == null) {
+ return examples
+ }
+ return suggestion.suggest(text.result) ?: throw NoSuggestionError(reader, text)
+ }
+
+ override fun build(connection: PlayConnection?) = this
+}
diff --git a/src/main/java/de/bixilon/minosoft/commands/parser/factory/ArgumentFactories.kt b/src/main/java/de/bixilon/minosoft/commands/parser/factory/ArgumentFactories.kt
new file mode 100644
index 000000000..ed666354a
--- /dev/null
+++ b/src/main/java/de/bixilon/minosoft/commands/parser/factory/ArgumentFactories.kt
@@ -0,0 +1,21 @@
+/*
+ * Minosoft
+ * Copyright (C) 2020-2022 Moritz Zwerger
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If not, see .
+ *
+ * This software is not affiliated with Mojang AB, the original developer of Minecraft.
+ */
+
+package de.bixilon.minosoft.commands.parser.factory
+
+import de.bixilon.minosoft.commands.parser.brigadier.bool.BooleanParser
+import de.bixilon.minosoft.data.registries.factory.DefaultFactory
+
+object ArgumentFactories : DefaultFactory>(
+ BooleanParser,
+)
diff --git a/src/main/java/de/bixilon/minosoft/commands/parser/factory/ArgumentFactory.kt b/src/main/java/de/bixilon/minosoft/commands/parser/factory/ArgumentFactory.kt
new file mode 100644
index 000000000..8db1713e2
--- /dev/null
+++ b/src/main/java/de/bixilon/minosoft/commands/parser/factory/ArgumentFactory.kt
@@ -0,0 +1,23 @@
+/*
+ * Minosoft
+ * Copyright (C) 2020-2022 Moritz Zwerger
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If not, see .
+ *
+ * This software is not affiliated with Mojang AB, the original developer of Minecraft.
+ */
+
+package de.bixilon.minosoft.commands.parser.factory
+
+import de.bixilon.minosoft.commands.parser.ArgumentParser
+import de.bixilon.minosoft.data.registries.CompanionResourceLocation
+import de.bixilon.minosoft.protocol.network.connection.play.PlayConnection
+
+interface ArgumentFactory> : CompanionResourceLocation {
+
+ fun build(connection: PlayConnection?): T
+}
diff --git a/src/main/java/de/bixilon/minosoft/commands/stack/CommandExecutor.kt b/src/main/java/de/bixilon/minosoft/commands/stack/CommandExecutor.kt
new file mode 100644
index 000000000..10b89098d
--- /dev/null
+++ b/src/main/java/de/bixilon/minosoft/commands/stack/CommandExecutor.kt
@@ -0,0 +1,16 @@
+/*
+ * Minosoft
+ * Copyright (C) 2020-2022 Moritz Zwerger
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If not, see .
+ *
+ * This software is not affiliated with Mojang AB, the original developer of Minecraft.
+ */
+
+package de.bixilon.minosoft.commands.stack
+
+typealias CommandExecutor = (stack: CommandStack) -> Unit
diff --git a/src/main/java/de/bixilon/minosoft/commands/stack/CommandStack.kt b/src/main/java/de/bixilon/minosoft/commands/stack/CommandStack.kt
new file mode 100644
index 000000000..e3ccab7c2
--- /dev/null
+++ b/src/main/java/de/bixilon/minosoft/commands/stack/CommandStack.kt
@@ -0,0 +1,16 @@
+/*
+ * Minosoft
+ * Copyright (C) 2020-2022 Moritz Zwerger
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If not, see .
+ *
+ * This software is not affiliated with Mojang AB, the original developer of Minecraft.
+ */
+
+package de.bixilon.minosoft.commands.stack
+
+class CommandStack
diff --git a/src/main/java/de/bixilon/minosoft/commands/suggestion/ArraySuggestion.kt b/src/main/java/de/bixilon/minosoft/commands/suggestion/ArraySuggestion.kt
new file mode 100644
index 000000000..ebe8c55eb
--- /dev/null
+++ b/src/main/java/de/bixilon/minosoft/commands/suggestion/ArraySuggestion.kt
@@ -0,0 +1,35 @@
+/*
+ * Minosoft
+ * Copyright (C) 2020-2022 Moritz Zwerger
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If not, see .
+ *
+ * This software is not affiliated with Mojang AB, the original developer of Minecraft.
+ */
+
+package de.bixilon.minosoft.commands.suggestion
+
+import de.bixilon.minosoft.commands.suggestion.types.SuggestionType
+
+class ArraySuggestion(val values: List) : SuggestionType {
+
+ override fun suggest(input: String): List? {
+ if (input.isBlank()) {
+ return values
+ }
+ val list: MutableList = mutableListOf()
+ for (entry in values) {
+ if (entry.toString().startsWith(input)) {
+ list += entry
+ }
+ }
+ if (list.isEmpty()) {
+ return null
+ }
+ return list
+ }
+}
diff --git a/src/main/java/de/bixilon/minosoft/commands/suggestion/factory/SuggestionFactories.kt b/src/main/java/de/bixilon/minosoft/commands/suggestion/factory/SuggestionFactories.kt
new file mode 100644
index 000000000..ada88e3c6
--- /dev/null
+++ b/src/main/java/de/bixilon/minosoft/commands/suggestion/factory/SuggestionFactories.kt
@@ -0,0 +1,19 @@
+/*
+ * Minosoft
+ * Copyright (C) 2020-2022 Moritz Zwerger
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If not, see .
+ *
+ * This software is not affiliated with Mojang AB, the original developer of Minecraft.
+ */
+
+package de.bixilon.minosoft.commands.suggestion.factory
+
+import de.bixilon.minosoft.data.registries.factory.DefaultFactory
+
+object SuggestionFactories : DefaultFactory>(
+)
diff --git a/src/main/java/de/bixilon/minosoft/commands/suggestion/factory/SuggestionFactory.kt b/src/main/java/de/bixilon/minosoft/commands/suggestion/factory/SuggestionFactory.kt
new file mode 100644
index 000000000..a1c68c120
--- /dev/null
+++ b/src/main/java/de/bixilon/minosoft/commands/suggestion/factory/SuggestionFactory.kt
@@ -0,0 +1,24 @@
+/*
+ * Minosoft
+ * Copyright (C) 2020-2022 Moritz Zwerger
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If not, see .
+ *
+ * This software is not affiliated with Mojang AB, the original developer of Minecraft.
+ */
+
+package de.bixilon.minosoft.commands.suggestion.factory
+
+import de.bixilon.minosoft.commands.suggestion.types.SuggestionType
+import de.bixilon.minosoft.data.registries.CompanionResourceLocation
+import de.bixilon.minosoft.protocol.network.connection.play.PlayConnection
+import de.bixilon.minosoft.protocol.protocol.PlayInByteBuffer
+
+interface SuggestionFactory> : CompanionResourceLocation {
+
+ fun build(connection: PlayConnection?, buffer: PlayInByteBuffer?): T
+}
diff --git a/src/main/java/de/bixilon/minosoft/commands/suggestion/types/SuggestionType.kt b/src/main/java/de/bixilon/minosoft/commands/suggestion/types/SuggestionType.kt
new file mode 100644
index 000000000..81d2211ef
--- /dev/null
+++ b/src/main/java/de/bixilon/minosoft/commands/suggestion/types/SuggestionType.kt
@@ -0,0 +1,19 @@
+/*
+ * Minosoft
+ * Copyright (C) 2020-2022 Moritz Zwerger
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If not, see .
+ *
+ * This software is not affiliated with Mojang AB, the original developer of Minecraft.
+ */
+
+package de.bixilon.minosoft.commands.suggestion.types
+
+interface SuggestionType {
+
+ fun suggest(input: String): List?
+}
diff --git a/src/main/java/de/bixilon/minosoft/commands/util/CommandReader.kt b/src/main/java/de/bixilon/minosoft/commands/util/CommandReader.kt
new file mode 100644
index 000000000..28b6a5c8f
--- /dev/null
+++ b/src/main/java/de/bixilon/minosoft/commands/util/CommandReader.kt
@@ -0,0 +1,208 @@
+/*
+ * Minosoft
+ * Copyright (C) 2020-2022 Moritz Zwerger
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If not, see .
+ *
+ * This software is not affiliated with Mojang AB, the original developer of Minecraft.
+ */
+
+package de.bixilon.minosoft.commands.util
+
+import de.bixilon.minosoft.commands.errors.reader.*
+
+open class CommandReader(val string: String) {
+ var pointer = 0
+ val length = string.length
+
+ fun canPeek(ignoreWhitespaces: Boolean = true): Boolean {
+ if (pointer >= length) {
+ return false
+ }
+ val whitespaces = if (ignoreWhitespaces) peekWhitespaces() else 0
+ return pointer + whitespaces < length
+ }
+
+ fun checkPeekNext(pointer: Int = this.pointer) {
+ if (!canPeekNext(pointer)) {
+ throw OutOfBoundsError(this, length - 1)
+ }
+ }
+
+ fun canPeekNext(pointer: Int = this.pointer): Boolean {
+ return pointer < length
+ }
+
+ fun peekNext(pointer: Int = this.pointer): Int? {
+ if (!canPeekNext()) {
+ return null
+ }
+ return string.codePointAt(pointer)
+ }
+
+ fun readNext(): Int? {
+ val next = peekNext(pointer) ?: return null
+ pointer++
+ return next
+ }
+
+ fun unsafePeekNext(): Int {
+ return peekNext() ?: throw OutOfBoundsError(this, length - 1)
+ }
+
+ fun unsafeReadNext(): Int {
+ return readNext() ?: throw OutOfBoundsError(this, length - 1)
+ }
+
+ fun peekWhitespaces(): Int {
+ var count = 0
+ while (true) {
+ val peek = peekNext(pointer + count) ?: return count
+ if (!Character.isWhitespace(peek)) {
+ break
+ }
+ count++
+ }
+ return count
+ }
+
+ fun skipWhitespaces(): Int {
+ val count = peekWhitespaces()
+ pointer += count
+ return count
+ }
+
+ fun peek(ignoreWhitespaces: Boolean = true): Int? {
+ if (ignoreWhitespaces) {
+ skipWhitespaces()
+ }
+ return peekNext()
+ }
+
+ fun read(ignoreWhitespaces: Boolean = true): Int? {
+ if (ignoreWhitespaces) {
+ skipWhitespaces()
+ }
+ val peek = peekNext() ?: return null
+ pointer++
+ return peek
+ }
+
+ fun unsafePeek(ignoreWhitespaces: Boolean = true): Int {
+ if (ignoreWhitespaces) {
+ skipWhitespaces()
+ }
+ return unsafePeekNext()
+ }
+
+ fun unsafeRead(ignoreWhitespaces: Boolean = true): Int {
+ val peek = unsafePeek(ignoreWhitespaces)
+ pointer++
+ return peek
+ }
+
+ fun peek(vararg chars: Int, ignoreWhitespaces: Boolean = true): Int? {
+ val peek = peek(ignoreWhitespaces) ?: return null
+ if (peek !in chars) {
+ return null
+ }
+ return peek
+ }
+
+ fun read(vararg chars: Int, ignoreWhitespaces: Boolean = true): Int? {
+ val read = read(ignoreWhitespaces) ?: return null
+ if (read !in chars) {
+ return null
+ }
+ return read
+ }
+
+ fun unsafePeek(vararg chars: Int, ignoreWhitespaces: Boolean = true): Int {
+ val peek = unsafePeek(ignoreWhitespaces)
+ if (peek !in chars) {
+ throw InvalidPeekError(this, pointer, peek, chars)
+ }
+ return peek
+ }
+
+ fun unsafeRead(vararg chars: Int, ignoreWhitespaces: Boolean = true): Int {
+ val read = unsafeRead(ignoreWhitespaces)
+ if (read !in chars) {
+ throw InvalidReadError(this, pointer, read, chars)
+ }
+ return read
+ }
+
+ fun readUnquotedString(): String? {
+ val builder = StringBuilder()
+ skipWhitespaces()
+ if (!canPeekNext()) {
+ return null
+ }
+ while (true) {
+ val char = read(false) ?: return builder.toString()
+ if (Character.isWhitespace(char)) {
+ return builder.toString()
+ }
+ builder.appendCodePoint(char)
+ }
+ }
+
+ fun readQuotedString(): String {
+ skipWhitespaces()
+ val start = pointer
+ unsafeRead(STRING_QUOTE)
+ val string = StringBuilder()
+ var skipNextChar = false
+ while (true) {
+ val read = readNext() ?: throw UnfinishedQuotedStringError(this, pointer)
+ if (read == '\\'.code) {
+ if (skipNextChar) {
+ string.append('\\')
+ skipNextChar = false
+ continue
+ }
+ skipNextChar = true
+ continue
+ }
+ if (skipNextChar) {
+ if (read != STRING_QUOTE) {
+ throw UnexpectedBackslashError(this, start, pointer, read)
+ }
+ string.append('"')
+ skipNextChar = false
+ continue
+ }
+ if (read == STRING_QUOTE) {
+ return string.toString()
+ }
+ string.appendCodePoint(read)
+ }
+ }
+
+ fun readString(): String? {
+ skipWhitespaces()
+ val start = unsafePeek()
+ if (start == STRING_QUOTE) {
+ return readQuotedString()
+ }
+ return readUnquotedString()
+ }
+
+ fun readResult(reader: CommandReader.() -> T): ReadResult {
+ val start = pointer
+ val result = reader(this)
+ val end = pointer
+ val read = string.substring(start, end)
+
+ return ReadResult(start, end, read, result)
+ }
+
+ companion object {
+ const val STRING_QUOTE = '"'.code
+ }
+}
diff --git a/src/main/java/de/bixilon/minosoft/commands/util/ReadResult.kt b/src/main/java/de/bixilon/minosoft/commands/util/ReadResult.kt
new file mode 100644
index 000000000..74851d19d
--- /dev/null
+++ b/src/main/java/de/bixilon/minosoft/commands/util/ReadResult.kt
@@ -0,0 +1,21 @@
+/*
+ * Minosoft
+ * Copyright (C) 2020-2022 Moritz Zwerger
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If not, see .
+ *
+ * This software is not affiliated with Mojang AB, the original developer of Minecraft.
+ */
+
+package de.bixilon.minosoft.commands.util
+
+class ReadResult(
+ val start: Int,
+ val end: Int,
+ val read: String,
+ val result: T,
+)
diff --git a/src/main/java/de/bixilon/minosoft/terminal/commands/Command.kt b/src/main/java/de/bixilon/minosoft/terminal/commands/Command.kt
new file mode 100644
index 000000000..9f19c44b1
--- /dev/null
+++ b/src/main/java/de/bixilon/minosoft/terminal/commands/Command.kt
@@ -0,0 +1,21 @@
+/*
+ * Minosoft
+ * Copyright (C) 2020-2022 Moritz Zwerger
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If not, see .
+ *
+ * This software is not affiliated with Mojang AB, the original developer of Minecraft.
+ */
+
+package de.bixilon.minosoft.terminal.commands
+
+import de.bixilon.minosoft.commands.nodes.LiteralNode
+
+interface Command {
+
+ fun build(): LiteralNode
+}
diff --git a/src/main/java/de/bixilon/minosoft/terminal/commands/HelpCommand.kt b/src/main/java/de/bixilon/minosoft/terminal/commands/HelpCommand.kt
new file mode 100644
index 000000000..c44f7525b
--- /dev/null
+++ b/src/main/java/de/bixilon/minosoft/terminal/commands/HelpCommand.kt
@@ -0,0 +1,23 @@
+/*
+ * Minosoft
+ * Copyright (C) 2020-2022 Moritz Zwerger
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If not, see .
+ *
+ * This software is not affiliated with Mojang AB, the original developer of Minecraft.
+ */
+
+package de.bixilon.minosoft.terminal.commands
+
+import de.bixilon.minosoft.commands.nodes.LiteralNode
+
+class HelpCommand : Command {
+
+ override fun build(): LiteralNode {
+ TODO("Not yet implemented")
+ }
+}
diff --git a/src/test/java/de/bixilon/minosoft/commands/parser/brigadier/bool/BooleanParserTest.kt b/src/test/java/de/bixilon/minosoft/commands/parser/brigadier/bool/BooleanParserTest.kt
new file mode 100644
index 000000000..2fd105107
--- /dev/null
+++ b/src/test/java/de/bixilon/minosoft/commands/parser/brigadier/bool/BooleanParserTest.kt
@@ -0,0 +1,88 @@
+/*
+ * Minosoft
+ * Copyright (C) 2020-2022 Moritz Zwerger
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If not, see .
+ *
+ * This software is not affiliated with Mojang AB, the original developer of Minecraft.
+ */
+
+package de.bixilon.minosoft.commands.parser.brigadier.bool
+
+import de.bixilon.minosoft.commands.errors.suggestion.NoSuggestionError
+import de.bixilon.minosoft.commands.util.CommandReader
+import org.junit.jupiter.api.Assertions.*
+import org.junit.jupiter.api.Test
+
+internal class BooleanParserTest {
+
+ @Test
+ fun testTrue() {
+ val reader = CommandReader("true")
+ assertTrue(BooleanParser.parse(reader))
+ }
+
+ @Test
+ fun testFalse() {
+ val reader = CommandReader("false")
+ assertFalse(BooleanParser.parse(reader))
+ }
+
+ @Test
+ fun testCaseSensitivity() {
+ val reader = CommandReader("True")
+ assertThrows(BooleanParseError::class.java) { (BooleanParser.parse(reader)) }
+ }
+
+ @Test
+ fun testEmpty() {
+ val reader = CommandReader("")
+ assertThrows(BooleanParseError::class.java) { (BooleanParser.parse(reader)) }
+ }
+
+ @Test
+ fun testTrash() {
+ val reader = CommandReader("this is trash")
+ assertThrows(BooleanParseError::class.java) { (BooleanParser.parse(reader)) }
+ }
+
+ @Test
+ fun testEmptySuggestion() {
+ val reader = CommandReader("")
+ assertEquals(BooleanParser.getSuggestions(reader).size, 2)
+ }
+
+ @Test
+ fun testTrueSuggestion() {
+ val reader = CommandReader("t")
+ assertEquals(BooleanParser.getSuggestions(reader).getOrNull(0), true)
+ }
+
+ @Test
+ fun testFullTrueSuggestion() {
+ val reader = CommandReader("true")
+ assertEquals(BooleanParser.getSuggestions(reader).getOrNull(0), true)
+ }
+
+ @Test
+ fun testFalseSuggestion() {
+ val reader = CommandReader("fa")
+ assertEquals(BooleanParser.getSuggestions(reader).getOrNull(0), false)
+ }
+
+ @Test
+ fun testFullFalseSuggestion() {
+ val reader = CommandReader("false")
+ assertEquals(BooleanParser.getSuggestions(reader).getOrNull(0), false)
+ }
+
+ @Test
+ fun testNoSuggestion() {
+ val reader = CommandReader("a")
+ assertThrows(NoSuggestionError::class.java) { BooleanParser.getSuggestions(reader).size }
+ }
+}
diff --git a/src/test/java/de/bixilon/minosoft/commands/util/CommandReaderTest.kt b/src/test/java/de/bixilon/minosoft/commands/util/CommandReaderTest.kt
new file mode 100644
index 000000000..fac33b0ca
--- /dev/null
+++ b/src/test/java/de/bixilon/minosoft/commands/util/CommandReaderTest.kt
@@ -0,0 +1,88 @@
+/*
+ * Minosoft
+ * Copyright (C) 2020-2022 Moritz Zwerger
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If not, see .
+ *
+ * This software is not affiliated with Mojang AB, the original developer of Minecraft.
+ */
+
+package de.bixilon.minosoft.commands.util
+
+import de.bixilon.minosoft.commands.errors.reader.OutOfBoundsError
+import org.junit.jupiter.api.Assertions.assertEquals
+import org.junit.jupiter.api.Assertions.assertThrows
+import org.junit.jupiter.api.Test
+
+internal class CommandReaderTest {
+ @Test
+ fun `Peek char`() {
+ val reader = CommandReader("test")
+ assertEquals(reader.peek(), 't'.code)
+ assertEquals(reader.peek(), 't'.code)
+ }
+
+ @Test
+ fun `Read test`() {
+ val reader = CommandReader("test")
+ assertEquals(reader.read(), 't'.code)
+ assertEquals(reader.read(), 'e'.code)
+ assertEquals(reader.read(), 's'.code)
+ assertEquals(reader.read(), 't'.code)
+ }
+
+ @Test
+ fun `Check OutOfBounds null`() {
+ val reader = CommandReader("test")
+ assertEquals(reader.read(), 't'.code)
+ assertEquals(reader.read(), 'e'.code)
+ assertEquals(reader.read(), 's'.code)
+ assertEquals(reader.read(), 't'.code)
+ assertEquals(reader.read(), null)
+ }
+
+ @Test
+ fun `Check OutOfBounds throw`() {
+ val reader = CommandReader("test")
+ assertEquals(reader.read(), 't'.code)
+ assertEquals(reader.read(), 'e'.code)
+ assertEquals(reader.read(), 's'.code)
+ assertEquals(reader.read(), 't'.code)
+ assertThrows(OutOfBoundsError::class.java) { reader.unsafeRead() }
+ }
+
+ @Test
+ fun `Check unquotedString read`() {
+ val reader = CommandReader("test")
+ assertEquals(reader.readString(), "test")
+ }
+
+ @Test
+ fun `Check unquotedString read 2`() {
+ val reader = CommandReader("test test2")
+ assertEquals(reader.readString(), "test")
+ assertEquals(reader.readString(), "test2")
+ }
+
+ @Test
+ fun `Read quoted string`() {
+ val reader = CommandReader("\"test\"")
+ assertEquals(reader.readString(), "test")
+ }
+
+ @Test
+ fun `Read separated quoted string`() {
+ val reader = CommandReader("\"test test\"")
+ assertEquals(reader.readString(), "test test")
+ }
+
+ @Test
+ fun `Read escaped quoted string`() {
+ val reader = CommandReader("\"test \\\"test\"")
+ assertEquals(reader.readString(), "test \"test")
+ }
+}