parser: angle, rotation, block_position

This commit is contained in:
Bixilon 2022-05-23 12:10:37 +02:00
parent 0ae6d1a60b
commit 8508442b35
No known key found for this signature in database
GPG Key ID: 5CAD791931B09AC4
11 changed files with 372 additions and 7 deletions

View File

@ -19,6 +19,9 @@ import de.bixilon.minosoft.commands.parser.brigadier._int.IntParser
import de.bixilon.minosoft.commands.parser.brigadier._long.LongParser
import de.bixilon.minosoft.commands.parser.brigadier.bool.BooleanParser
import de.bixilon.minosoft.commands.parser.brigadier.string.StringParser
import de.bixilon.minosoft.commands.parser.minecraft.coordinate.angle.AngleParser
import de.bixilon.minosoft.commands.parser.minecraft.coordinate.block.BlockPositionParser
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.range.RangeParserFactory
@ -54,6 +57,9 @@ object ArgumentParserFactories : DefaultFactory<ArgumentParserFactory<*>>(
Vec2Parser,
Vec3Parser,
BlockPositionParser,
AngleParser,
RotationParser,
DummyParser,
@ -63,7 +69,6 @@ object ArgumentParserFactories : DefaultFactory<ArgumentParserFactory<*>>(
/* TODO:
minecraft:game_profile
minecraft:block_pos
minecraft:column_pos
minecraft:block_state
minecraft:block_predicate
@ -78,8 +83,6 @@ minecraft:objective
minecraft:objective_criteria
minecraft:operation
minecraft:particle
minecraft:rotation
minecraft:angle
minecraft:scoreboard_slot
minecraft:score_holder
minecraft:swizzle

View File

@ -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 <https://www.gnu.org/licenses/>.
*
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
*/
package de.bixilon.minosoft.commands.parser.minecraft.coordinate
import de.bixilon.minosoft.commands.errors.ReaderError
import de.bixilon.minosoft.commands.util.CommandReader
class CaretNotAllowedError(
reader: CommandReader,
pointer: Int,
) : ReaderError(reader, pointer - 1, pointer)

View File

@ -14,11 +14,12 @@
package de.bixilon.minosoft.commands.parser.minecraft.coordinate
import de.bixilon.minosoft.commands.parser.brigadier._float.FloatParser.Companion.readFloat
import de.bixilon.minosoft.commands.parser.brigadier._int.IntParser.Companion.readInt
import de.bixilon.minosoft.commands.util.CommandReader
object CoordinateParserUtil {
fun CommandReader.readCoordinateOrNull(): Coordinate? {
fun CommandReader.readCoordinateOrNull(decimal: Boolean = true, caret: Boolean = true): Coordinate? {
val peek = peek() ?: return null
val type = when (peek) {
'~'.code -> {
@ -27,12 +28,15 @@ object CoordinateParserUtil {
}
'^'.code -> {
read()
if (!caret) {
throw CaretNotAllowedError(this, pointer)
}
CoordinateRelatives.CARET
}
else -> CoordinateRelatives.NONE
}
val offset = if (peekWhitespaces() == 0) readFloat() else null
val offset = if (peekWhitespaces() == 0) if (decimal) readFloat() else readInt()?.toFloat() else null
if (offset == null && type == CoordinateRelatives.NONE) {
return null
}
@ -42,7 +46,7 @@ object CoordinateParserUtil {
}
fun CommandReader.readCoordinate(): Coordinate {
readResult { readCoordinateOrNull() }.let { return it.result ?: throw InvalidCoordinateError(this, it) }
fun CommandReader.readCoordinate(decimal: Boolean = true, caret: Boolean = true): Coordinate {
readResult { readCoordinateOrNull(decimal, caret) }.let { return it.result ?: throw InvalidCoordinateError(this, it) }
}
}

View File

@ -0,0 +1,43 @@
/*
* 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 <https://www.gnu.org/licenses/>.
*
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
*/
package de.bixilon.minosoft.commands.parser.minecraft.coordinate.angle
import de.bixilon.minosoft.commands.parser.ArgumentParser
import de.bixilon.minosoft.commands.parser.factory.ArgumentParserFactory
import de.bixilon.minosoft.commands.parser.minecraft.coordinate.Coordinate
import de.bixilon.minosoft.commands.parser.minecraft.coordinate.CoordinateParserUtil.readCoordinate
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.protocol.PlayInByteBuffer
import de.bixilon.minosoft.util.KUtil.toResourceLocation
object AngleParser : ArgumentParser<Coordinate>, ArgumentParserFactory<AngleParser> {
override val RESOURCE_LOCATION: ResourceLocation = "minecraft:angle".toResourceLocation()
override val examples: List<Any> = listOf("~", "5", "~10.8")
override val placeholder = ChatComponent.of("<angle>")
override fun parse(reader: CommandReader): Coordinate {
return reader.readCoordinate(caret = false) // ToDo: Check min/max?
}
override fun getSuggestions(reader: CommandReader): List<Any> {
if (reader.readString()?.isBlank() != false) {
return examples
}
return emptyList()
}
override fun read(buffer: PlayInByteBuffer) = this
}

View File

@ -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 <https://www.gnu.org/licenses/>.
*
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
*/
package de.bixilon.minosoft.commands.parser.minecraft.coordinate.block
import de.bixilon.minosoft.commands.parser.minecraft.coordinate.Coordinate
data class BlockCoordinate(
val x: Coordinate,
val y: Coordinate,
val z: Coordinate,
)

View File

@ -0,0 +1,42 @@
/*
* 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 <https://www.gnu.org/licenses/>.
*
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
*/
package de.bixilon.minosoft.commands.parser.minecraft.coordinate.block
import de.bixilon.minosoft.commands.parser.ArgumentParser
import de.bixilon.minosoft.commands.parser.factory.ArgumentParserFactory
import de.bixilon.minosoft.commands.parser.minecraft.coordinate.CoordinateParserUtil.readCoordinate
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.protocol.PlayInByteBuffer
import de.bixilon.minosoft.util.KUtil.toResourceLocation
object BlockPositionParser : ArgumentParser<BlockCoordinate>, ArgumentParserFactory<BlockPositionParser> {
override val RESOURCE_LOCATION: ResourceLocation = "minecraft:block_pos".toResourceLocation()
override val examples: List<Any> = listOf("~ ~ ~", "^ ^ ^", "5 5 5")
override val placeholder = ChatComponent.of("<block position>")
override fun parse(reader: CommandReader): BlockCoordinate {
return BlockCoordinate(reader.readCoordinate(decimal = false), reader.readCoordinate(decimal = false), reader.readCoordinate(decimal = false))
}
override fun getSuggestions(reader: CommandReader): List<Any> {
if (reader.readString()?.isBlank() != false) {
return examples
}
return emptyList()
}
override fun read(buffer: PlayInByteBuffer) = this
}

View File

@ -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 <https://www.gnu.org/licenses/>.
*
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
*/
package de.bixilon.minosoft.commands.parser.minecraft.coordinate.rotation
import de.bixilon.minosoft.commands.parser.minecraft.coordinate.Coordinate
data class Rotation(
val yaw: Coordinate,
val pitch: Coordinate,
)

View File

@ -0,0 +1,42 @@
/*
* 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 <https://www.gnu.org/licenses/>.
*
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
*/
package de.bixilon.minosoft.commands.parser.minecraft.coordinate.rotation
import de.bixilon.minosoft.commands.parser.ArgumentParser
import de.bixilon.minosoft.commands.parser.factory.ArgumentParserFactory
import de.bixilon.minosoft.commands.parser.minecraft.coordinate.CoordinateParserUtil.readCoordinate
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.protocol.PlayInByteBuffer
import de.bixilon.minosoft.util.KUtil.toResourceLocation
object RotationParser : ArgumentParser<Rotation>, ArgumentParserFactory<RotationParser> {
override val RESOURCE_LOCATION: ResourceLocation = "minecraft:rotation".toResourceLocation()
override val examples: List<Any> = listOf("~ ~", "5 5", "~10.8 ~12")
override val placeholder = ChatComponent.of("<rotation>")
override fun parse(reader: CommandReader): Rotation {
return Rotation(reader.readCoordinate(caret = false), reader.readCoordinate(caret = false)) // ToDo: Check min/max?
}
override fun getSuggestions(reader: CommandReader): List<Any> {
if (reader.readString()?.isBlank() != false) {
return examples
}
return emptyList()
}
override fun read(buffer: PlayInByteBuffer) = this
}

View File

@ -0,0 +1,68 @@
/*
* 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 <https://www.gnu.org/licenses/>.
*
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
*/
package de.bixilon.minosoft.commands.parser.minecraft.coordinate.angle
import de.bixilon.minosoft.commands.parser.minecraft.coordinate.CaretNotAllowedError
import de.bixilon.minosoft.commands.parser.minecraft.coordinate.Coordinate
import de.bixilon.minosoft.commands.parser.minecraft.coordinate.CoordinateRelatives
import de.bixilon.minosoft.commands.util.CommandReader
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.assertThrows
import kotlin.test.assertEquals
internal class AngleParserTest {
@Test
fun readNumeric() {
val reader = CommandReader("123")
assertEquals(AngleParser.parse(reader), Coordinate(CoordinateRelatives.NONE, 123.0f))
}
@Test
fun readTilde() {
val reader = CommandReader("~123")
assertEquals(AngleParser.parse(reader), Coordinate(CoordinateRelatives.TILDE, 123.0f))
}
@Test
fun readNumber() {
val reader = CommandReader("12")
assertEquals(AngleParser.parse(reader), Coordinate(CoordinateRelatives.NONE, 12.0f))
}
@Test
fun readRelative() {
val reader = CommandReader("~")
assertEquals(AngleParser.parse(reader), Coordinate(CoordinateRelatives.TILDE, 0.0f))
}
@Test
fun readRelativeOffset() {
val reader = CommandReader("~42")
assertEquals(AngleParser.parse(reader), Coordinate(CoordinateRelatives.TILDE, 42.0f))
}
@Test
fun readCaret() {
val reader = CommandReader("^")
assertThrows<CaretNotAllowedError> { AngleParser.parse(reader) }
}
@Test
fun readDecimal() {
val reader = CommandReader("12.34")
assertEquals(AngleParser.parse(reader), Coordinate(CoordinateRelatives.NONE, 12.34f))
}
}

View File

@ -0,0 +1,48 @@
/*
* 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 <https://www.gnu.org/licenses/>.
*
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
*/
package de.bixilon.minosoft.commands.parser.minecraft.coordinate.block
import de.bixilon.minosoft.commands.parser.minecraft.coordinate.Coordinate
import de.bixilon.minosoft.commands.parser.minecraft.coordinate.CoordinateRelatives
import de.bixilon.minosoft.commands.util.CommandReader
import org.junit.jupiter.api.Test
import kotlin.test.assertEquals
internal class BlockPositionParserTest {
@Test
fun readNumber() {
val reader = CommandReader("12 34 45")
assertEquals(BlockPositionParser.parse(reader), BlockCoordinate(Coordinate(CoordinateRelatives.NONE, 12.0f), Coordinate(CoordinateRelatives.NONE, 34.0f), Coordinate(CoordinateRelatives.NONE, 45.0f)))
}
@Test
fun readRelative() {
val reader = CommandReader("~ ~ ~")
assertEquals(BlockPositionParser.parse(reader), BlockCoordinate(Coordinate(CoordinateRelatives.TILDE, 0.0f), Coordinate(CoordinateRelatives.TILDE, 0.0f), Coordinate(CoordinateRelatives.TILDE, 0.0f)))
}
@Test
fun readRelativeOffset() {
val reader = CommandReader("~12 ~34 ~45")
assertEquals(BlockPositionParser.parse(reader), BlockCoordinate(Coordinate(CoordinateRelatives.TILDE, 12.0f), Coordinate(CoordinateRelatives.TILDE, 34.0f), Coordinate(CoordinateRelatives.TILDE, 45.0f)))
}
@Test
fun readDecimal() {
val reader = CommandReader("12 34 45.56")
assertEquals(BlockPositionParser.parse(reader), BlockCoordinate(Coordinate(CoordinateRelatives.NONE, 12.0f), Coordinate(CoordinateRelatives.NONE, 34.0f), Coordinate(CoordinateRelatives.NONE, 45.0f)))
}
}

View File

@ -0,0 +1,50 @@
/*
* 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 <https://www.gnu.org/licenses/>.
*
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
*/
package de.bixilon.minosoft.commands.parser.minecraft.coordinate.rotation
import de.bixilon.minosoft.commands.parser.minecraft.coordinate.Coordinate
import de.bixilon.minosoft.commands.parser.minecraft.coordinate.CoordinateRelatives
import de.bixilon.minosoft.commands.parser.minecraft.coordinate.InvalidCoordinateError
import de.bixilon.minosoft.commands.util.CommandReader
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.assertThrows
import kotlin.test.assertEquals
internal class RotationParserTest {
@Test
fun testNumeric() {
val reader = CommandReader("12 34")
assertEquals(RotationParser.parse(reader), Rotation(Coordinate(CoordinateRelatives.NONE, 12.0f), Coordinate(CoordinateRelatives.NONE, 34.0f)))
}
@Test
fun testMixed() {
val reader = CommandReader("~12 34")
assertEquals(RotationParser.parse(reader), Rotation(Coordinate(CoordinateRelatives.TILDE, 12.0f), Coordinate(CoordinateRelatives.NONE, 34.0f)))
}
@Test
fun testTilde() {
val reader = CommandReader("~ ~")
assertEquals(RotationParser.parse(reader), Rotation(Coordinate(CoordinateRelatives.TILDE, 0.0f), Coordinate(CoordinateRelatives.TILDE, 0.0f)))
}
@Test
fun testInvalid() {
val reader = CommandReader("hm")
assertThrows<InvalidCoordinateError> { RotationParser.parse(reader) }
}
}