diff --git a/src/integration-test/kotlin/de/bixilon/minosoft/commands/MsgCommandIT.kt b/src/integration-test/kotlin/de/bixilon/minosoft/commands/MsgCommandIT.kt
new file mode 100644
index 000000000..845c7f1c4
--- /dev/null
+++ b/src/integration-test/kotlin/de/bixilon/minosoft/commands/MsgCommandIT.kt
@@ -0,0 +1,58 @@
+/*
+ * Minosoft
+ * Copyright (C) 2020-2023 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
+
+import de.bixilon.kutil.cast.CastUtil.unsafeCast
+import de.bixilon.minosoft.commands.nodes.ArgumentNode
+import de.bixilon.minosoft.commands.nodes.LiteralNode
+import de.bixilon.minosoft.commands.nodes.RootNode
+import de.bixilon.minosoft.commands.parser.minecraft.message.MessageParser
+import de.bixilon.minosoft.commands.parser.minecraft.target.TargetParser
+import de.bixilon.minosoft.commands.parser.minecraft.target.targets.identifier.name.NameEntityTarget
+import de.bixilon.minosoft.commands.stack.CommandStack
+import org.testng.Assert.*
+import org.testng.annotations.Test
+
+@Test(groups = ["command"])
+class MsgCommandIT {
+
+ private fun createNode(executor: (CommandStack) -> Unit): RootNode {
+ return RootNode().addChild(
+ LiteralNode("msg").addChild(
+ ArgumentNode("targets", TargetParser()).addChild(
+ ArgumentNode("message", MessageParser, executor = executor)
+ )
+ )
+ ).unsafeCast()
+ }
+
+ fun basicExecution() {
+ var executed = false
+ val node = createNode { executed = true }
+
+ node.execute("msg Bixilon hi there!")
+
+ assertTrue(executed)
+ }
+
+ fun validateStack() {
+ val node = createNode {
+ assertNotNull(it["msg"])
+ assertEquals(it["targets"], NameEntityTarget("Bixilon"))
+ assertEquals(it["message"], "hi there!")
+ }
+
+ node.execute("msg Bixilon hi there!")
+ }
+}
diff --git a/src/main/java/de/bixilon/minosoft/commands/parser/factory/ArgumentParserFactories.kt b/src/main/java/de/bixilon/minosoft/commands/parser/factory/ArgumentParserFactories.kt
index 83e9e3776..38f6c61c4 100644
--- a/src/main/java/de/bixilon/minosoft/commands/parser/factory/ArgumentParserFactories.kt
+++ b/src/main/java/de/bixilon/minosoft/commands/parser/factory/ArgumentParserFactories.kt
@@ -26,6 +26,7 @@ import de.bixilon.minosoft.commands.parser.minecraft.coordinate.block.BlockPosit
import de.bixilon.minosoft.commands.parser.minecraft.coordinate.rotation.RotationParser
import de.bixilon.minosoft.commands.parser.minecraft.coordinate.vec2.Vec2Parser
import de.bixilon.minosoft.commands.parser.minecraft.coordinate.vec3.Vec3Parser
+import de.bixilon.minosoft.commands.parser.minecraft.message.MessageParser
import de.bixilon.minosoft.commands.parser.minecraft.range.RangeParserFactory
import de.bixilon.minosoft.commands.parser.minecraft.range._float.FloatRangeParser
import de.bixilon.minosoft.commands.parser.minecraft.range._int.IntRangeParser
@@ -69,6 +70,8 @@ object ArgumentParserFactories : DefaultFactory>(
ChatComponentParser,
+ MessageParser,
+
DummyParser,
ScoreHolderParser,
@@ -85,7 +88,6 @@ object ArgumentParserFactories : DefaultFactory>(
minecraft:block_predicate
minecraft:item_stack
minecraft:item_predicate
- minecraft:message, SIGNED
minecraft:nbt
minecraft:nbt_path
minecraft:objective
diff --git a/src/main/java/de/bixilon/minosoft/commands/parser/minecraft/message/MessageParser.kt b/src/main/java/de/bixilon/minosoft/commands/parser/minecraft/message/MessageParser.kt
new file mode 100644
index 000000000..2548a7a4d
--- /dev/null
+++ b/src/main/java/de/bixilon/minosoft/commands/parser/minecraft/message/MessageParser.kt
@@ -0,0 +1,45 @@
+/*
+ * Minosoft
+ * Copyright (C) 2020-2023 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.minecraft.message
+
+import de.bixilon.minosoft.commands.parser.ArgumentParser
+import de.bixilon.minosoft.commands.parser.SignedParser
+import de.bixilon.minosoft.commands.parser.brigadier.string.StringParser
+import de.bixilon.minosoft.commands.parser.factory.ArgumentParserFactory
+import de.bixilon.minosoft.commands.util.CommandReader
+import de.bixilon.minosoft.data.registries.identified.Namespaces.minecraft
+import de.bixilon.minosoft.data.registries.identified.ResourceLocation
+import de.bixilon.minosoft.protocol.protocol.PlayInByteBuffer
+
+object MessageParser : ArgumentParser, ArgumentParserFactory, SignedParser {
+ override val identifier: ResourceLocation = minecraft("message")
+ override val examples: List = listOf("hi there!")
+ private val parser = StringParser(StringParser.StringModes.GREEDY)
+
+ override fun parse(reader: CommandReader): String {
+ if (!reader.canPeek()) {
+ return ""
+ }
+ return parser.parse(reader)
+ }
+
+ override fun getSuggestions(reader: CommandReader): List {
+ if (reader.readString()?.isBlank() != false) {
+ return examples
+ }
+ return emptyList()
+ }
+
+ override fun read(buffer: PlayInByteBuffer) = this
+}