argument parser: color

This commit is contained in:
Bixilon 2022-06-01 13:44:50 +02:00
parent 3e285ca378
commit ec134bf56e
No known key found for this signature in database
GPG Key ID: 5CAD791931B09AC4
9 changed files with 208 additions and 16 deletions

View File

@ -19,6 +19,7 @@ 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.color.ColorParser
import de.bixilon.minosoft.commands.parser.minecraft.component.ChatComponentParser
import de.bixilon.minosoft.commands.parser.minecraft.coordinate.angle.AngleParser
import de.bixilon.minosoft.commands.parser.minecraft.coordinate.block.BlockPositionParser
@ -62,6 +63,8 @@ object ArgumentParserFactories : DefaultFactory<ArgumentParserFactory<*>>(
AngleParser,
RotationParser,
ColorParser,
ChatComponentParser,
DummyParser,
@ -77,7 +80,6 @@ minecraft:block_state
minecraft:block_predicate
minecraft:item_stack
minecraft:item_predicate
minecraft:color
minecraft:message
minecraft:nbt
minecraft:nbt_path

View File

@ -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 <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.color
import de.bixilon.minosoft.commands.errors.parser.ParserError
import de.bixilon.minosoft.commands.util.ReadResult
import de.bixilon.minosoft.commands.util.StringReader
import de.bixilon.minosoft.data.text.RGBColor
class ColorParseError(
reader: StringReader,
result: ReadResult<RGBColor?>,
) : ParserError(reader, result)

View File

@ -0,0 +1,73 @@
/*
* 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.color
import de.bixilon.minosoft.commands.parser.ArgumentParser
import de.bixilon.minosoft.commands.parser.factory.ArgumentParserFactory
import de.bixilon.minosoft.commands.util.CommandReader
import de.bixilon.minosoft.data.registries.ResourceLocation
import de.bixilon.minosoft.data.text.ChatColors
import de.bixilon.minosoft.data.text.ChatComponent
import de.bixilon.minosoft.data.text.RGBColor
import de.bixilon.minosoft.data.text.RGBColor.Companion.asColor
import de.bixilon.minosoft.protocol.protocol.PlayInByteBuffer
import de.bixilon.minosoft.util.KUtil.toResourceLocation
class ColorParser(
val supportsRGB: Boolean = true,
) : ArgumentParser<RGBColor> {
override val examples: List<Any> = listOf()
override val placeholder = ChatComponent.of("<color>")
override fun parse(reader: CommandReader): RGBColor {
reader.readResult { reader.readColor() }.let { return it.result ?: throw ColorParseError(reader, it) }
}
fun CommandReader.readColor(): RGBColor? {
val peek = peek() ?: return null
if (peek == '#'.code) {
if (!supportsRGB) {
throw HexNotSupportedError(this, readResult { read()!!.toChar() })
}
read()
val colorString = readWord(false) ?: return null
return try {
colorString.asColor()
} catch (ignored: NumberFormatException) {
null
}
}
val string = readString() ?: return null
if (string == "reset") {
return ChatColors.WHITE // ToDo
}
return ChatColors.NAME_MAP[string.lowercase()]
}
override fun getSuggestions(reader: CommandReader): List<Any> {
if (reader.readString()?.isBlank() != false) {
return examples
}
return emptyList()
}
companion object : ArgumentParserFactory<ColorParser> {
override val RESOURCE_LOCATION: ResourceLocation = "minecraft:color".toResourceLocation()
override fun read(buffer: PlayInByteBuffer): ColorParser {
return ColorParser(buffer.connection.version.supportsRGBChat)
}
}
}

View File

@ -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 <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.color
import de.bixilon.minosoft.commands.errors.parser.ParserError
import de.bixilon.minosoft.commands.util.ReadResult
import de.bixilon.minosoft.commands.util.StringReader
class HexNotSupportedError(
reader: StringReader,
result: ReadResult<Char?>,
) : ParserError(reader, result)

View File

@ -264,12 +264,14 @@ open class StringReader(val string: String) {
return builder.toString()
}
fun readWord(): String? {
fun readWord(skipWhitespace: Boolean = true): String? {
if (!canPeek()) {
return null
}
val builder = StringBuilder()
skipWhitespaces()
if (skipWhitespace) {
skipWhitespaces()
}
while (true) {
val peek = peekNext() ?: break
if (peek.isWord()) {

View File

@ -58,8 +58,9 @@ class Version(
val flattened: Boolean get() = versionId >= ProtocolDefinition.FLATTING_VERSION_ID
val hasOffhand: Boolean get() = versionId >= V_15W31A
val maxPacketLength get() = (versionId < ProtocolVersions.V_1_17_1_RC2).decide(1 shl 21, 1 shl 23)
val maxChatMessageSize get() = (versionId < ProtocolVersions.V_16W38A).decide(100, 256)
val maxPacketLength get() = if (versionId < ProtocolVersions.V_1_17_1_RC2) 1 shl 21 else 1 shl 23
val maxChatMessageSize get() = if (versionId < ProtocolVersions.V_16W38A) 100 else 256
val hasAttackCooldown get() = versionId >= ProtocolVersions.V_15W34A
val requiresSignedChat get() = versionId >= ProtocolVersions.V_22W17A
val supportsRGBChat get() = versionId >= ProtocolVersions.V_20W17A
}

View File

@ -117,17 +117,16 @@ class RGBColor(val rgba: Int) : ChatCode, TextFormattable {
const val COLOR_FLOAT_DIVIDER = 255.0f
fun String.asColor(): RGBColor {
return RGBColor(let {
var colorString = this
if (colorString.startsWith("#")) {
colorString = colorString.substring(1)
}
return@let if (colorString.length == 6) {
Integer.parseUnsignedInt(colorString + "ff", 16)
} else {
Integer.parseUnsignedInt(colorString, 16)
}
})
var colorString = this
if (colorString.startsWith("#")) {
colorString = colorString.substring(1)
}
val rgb = if (colorString.length == 6) {
Integer.parseUnsignedInt(colorString + "ff", 16)
} else {
Integer.parseUnsignedInt(colorString, 16)
}
return RGBColor(rgb)
}
fun Int.asRGBColor(): RGBColor {

View File

@ -33,9 +33,11 @@ open class EventMaster(vararg parents: AbstractEventMaster) : AbstractEventMaste
override val size: Int
get() {
var size = eventInvokers.size
parentLock.acquire()
for (parent in parents) {
size += parent.size
}
parentLock.release()
return size
}

View File

@ -0,0 +1,66 @@
/*
* 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.color
import de.bixilon.minosoft.commands.util.CommandReader
import de.bixilon.minosoft.data.text.ChatColors
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.assertThrows
import kotlin.test.assertEquals
internal class ColorParserTest {
@Test
fun testYellow() {
val reader = CommandReader("yellow")
val parser = ColorParser()
assertEquals(parser.parse(reader), ChatColors.YELLOW)
}
@Test
fun testGreen() {
val reader = CommandReader("green")
val parser = ColorParser()
assertEquals(parser.parse(reader), ChatColors.GREEN)
}
@Test
fun testHexBlack() {
val reader = CommandReader("#000000")
val parser = ColorParser()
assertEquals(parser.parse(reader), ChatColors.BLACK)
}
@Test
fun testHexWhite() {
val reader = CommandReader("#FFFFFF")
val parser = ColorParser()
assertEquals(parser.parse(reader), ChatColors.WHITE)
}
@Test
fun testInvalidHex() {
val reader = CommandReader("#FFIFFF")
val parser = ColorParser()
assertThrows<ColorParseError> { parser.parse(reader) }
}
@Test
fun testHexDisabled() {
val reader = CommandReader("#ABCDEF")
val parser = ColorParser(supportsRGB = false)
assertThrows<HexNotSupportedError> { parser.parse(reader) }
}
}