mirror of
https://gitlab.bixilon.de/bixilon/minosoft.git
synced 2025-09-15 02:15:34 -04:00
cssc: more parsers (nbt and chat component), fixes
This commit is contained in:
parent
73f95a4cc0
commit
04c12f8409
@ -86,7 +86,6 @@ public abstract class CommandNode {
|
||||
}
|
||||
String nextArgument = stringReader.readUnquotedString();
|
||||
if (this.literalChildren.containsKey(nextArgument)) {
|
||||
stringReader.skip(nextArgument.length());
|
||||
this.literalChildren.get(nextArgument).isSyntaxCorrect(connection, stringReader);
|
||||
return;
|
||||
}
|
||||
|
@ -13,9 +13,17 @@
|
||||
|
||||
package de.bixilon.minosoft.data.commands;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParseException;
|
||||
import com.google.gson.stream.JsonReader;
|
||||
import de.bixilon.minosoft.data.commands.parser.exceptions.BooleanCommandParseException;
|
||||
import de.bixilon.minosoft.data.commands.parser.exceptions.InvalidJSONCommandParseException;
|
||||
import de.bixilon.minosoft.data.commands.parser.exceptions.StringCommandParseException;
|
||||
import de.bixilon.minosoft.data.commands.parser.exceptions.identifier.InvalidIdentifierCommandParseException;
|
||||
import de.bixilon.minosoft.data.commands.parser.exceptions.nbt.CompoundTagBadFormatCommandParseException;
|
||||
import de.bixilon.minosoft.data.commands.parser.exceptions.nbt.ListTagBadFormatCommandParseException;
|
||||
import de.bixilon.minosoft.data.commands.parser.exceptions.number.DoubleCommandParseException;
|
||||
import de.bixilon.minosoft.data.commands.parser.exceptions.number.FloatCommandParseException;
|
||||
import de.bixilon.minosoft.data.commands.parser.exceptions.number.IntegerCommandParseException;
|
||||
@ -24,13 +32,25 @@ import de.bixilon.minosoft.data.commands.parser.exceptions.properties.BadPropert
|
||||
import de.bixilon.minosoft.data.commands.parser.exceptions.properties.DuplicatedPropertyKeyCommandParseException;
|
||||
import de.bixilon.minosoft.data.mappings.ModIdentifier;
|
||||
import de.bixilon.minosoft.util.Pair;
|
||||
import de.bixilon.minosoft.util.nbt.tag.CompoundTag;
|
||||
import de.bixilon.minosoft.util.Util;
|
||||
import de.bixilon.minosoft.util.nbt.tag.*;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.StringReader;
|
||||
import java.util.HashMap;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public class CommandStringReader {
|
||||
private static final Pattern NBT_PATTERN_INT = Pattern.compile("[-+]?(0|[1-9][0-9]*)");
|
||||
private static final Pattern NBT_PATTERN_BYTE = Pattern.compile(NBT_PATTERN_INT.pattern() + "b");
|
||||
private static final Pattern NBT_PATTERN_SHORT = Pattern.compile(NBT_PATTERN_INT.pattern() + "s");
|
||||
private static final Pattern NBT_PATTERN_LONG = Pattern.compile(NBT_PATTERN_INT.pattern() + "l");
|
||||
private static final Pattern NBT_PATTERN_FLOAT = Pattern.compile(NBT_PATTERN_INT.pattern() + "([.][0-9]*)?f");
|
||||
private static final Pattern NBT_PATTERN_DOUBLE = Pattern.compile(NBT_PATTERN_INT.pattern() + "([.][0-9]*)?d?");
|
||||
private static final Gson GSON = new Gson();
|
||||
|
||||
private final String string;
|
||||
private int cursor;
|
||||
|
||||
@ -88,11 +108,15 @@ public class CommandStringReader {
|
||||
}
|
||||
|
||||
public void skip(int length) {
|
||||
this.cursor += length;
|
||||
int nextLength = this.cursor + length;
|
||||
if (nextLength > this.string.length() || nextLength < 0) {
|
||||
throw new IllegalStateException("Nothing to skip!");
|
||||
}
|
||||
this.cursor = nextLength;
|
||||
}
|
||||
|
||||
public void skip() {
|
||||
this.cursor++;
|
||||
skip(1);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -148,7 +172,6 @@ public class CommandStringReader {
|
||||
@NotNull
|
||||
public Pair<String, String> readProperty() throws StringCommandParseException, BadPropertyMapCommandParseException {
|
||||
skipWhitespaces();
|
||||
StringBuilder builder = new StringBuilder();
|
||||
String key = readString();
|
||||
skipWhitespaces();
|
||||
if (read() != '=') {
|
||||
@ -162,11 +185,12 @@ public class CommandStringReader {
|
||||
|
||||
@NotNull
|
||||
public Map<String, String> readProperties() throws StringCommandParseException, DuplicatedPropertyKeyCommandParseException, BadPropertyMapCommandParseException {
|
||||
Map<String, String> ret = new HashMap<>();
|
||||
if (peek() != '[') {
|
||||
throw new BadPropertyMapCommandParseException(this, String.valueOf(peek()), "Not a property map!");
|
||||
}
|
||||
Map<String, String> ret = new HashMap<>();
|
||||
skip();
|
||||
skipWhitespaces();
|
||||
if (peek() == ']') {
|
||||
return ret;
|
||||
}
|
||||
@ -338,8 +362,124 @@ public class CommandStringReader {
|
||||
return readStringUntil(true, terminator);
|
||||
}
|
||||
|
||||
public CompoundTag readNBTCompoundTag() {
|
||||
throw new IllegalArgumentException("TODO");
|
||||
public ListTag readNBTListTag() throws ListTagBadFormatCommandParseException, StringCommandParseException, CompoundTagBadFormatCommandParseException {
|
||||
skipWhitespaces();
|
||||
if (peek() != '[') {
|
||||
throw new ListTagBadFormatCommandParseException(this, String.valueOf(peek()), "Not a list tag!");
|
||||
}
|
||||
skip();
|
||||
ListTag listTag = new ListTag();
|
||||
skipWhitespaces();
|
||||
if (peek() == ']') {
|
||||
skip();
|
||||
return listTag;
|
||||
}
|
||||
while (canRead()) {
|
||||
int start = getCursor();
|
||||
try {
|
||||
listTag.addTag(readNBTTag());
|
||||
} catch (IllegalArgumentException exception) {
|
||||
throw new ListTagBadFormatCommandParseException(this, this.string.substring(start, getCursor()), exception);
|
||||
}
|
||||
skipWhitespaces();
|
||||
if (peek() == ',') {
|
||||
skip();
|
||||
skipWhitespaces();
|
||||
}
|
||||
if (peek() == ']') {
|
||||
skip();
|
||||
return listTag;
|
||||
}
|
||||
}
|
||||
throw new ListTagBadFormatCommandParseException(this, String.valueOf(peek()), "No closing tag!");
|
||||
}
|
||||
|
||||
public NBTTag readNBTTag() throws StringCommandParseException, ListTagBadFormatCommandParseException, CompoundTagBadFormatCommandParseException {
|
||||
// ToDo: Array tags
|
||||
skipWhitespaces();
|
||||
if (peek() == '[') {
|
||||
return readNBTListTag();
|
||||
}
|
||||
if (peek() == '{') {
|
||||
return readNBTCompoundTag();
|
||||
}
|
||||
String data = readString().toLowerCase(Locale.ROOT);
|
||||
if (data.equals("true")) {
|
||||
return new ByteTag(true);
|
||||
}
|
||||
if (data.equals("false")) {
|
||||
return new ByteTag(false);
|
||||
}
|
||||
try {
|
||||
if (NBT_PATTERN_BYTE.matcher(data).matches()) {
|
||||
return new ByteTag(Byte.parseByte(data.substring(0, data.length() - 1)));
|
||||
}
|
||||
if (NBT_PATTERN_SHORT.matcher(data).matches()) {
|
||||
return new ShortTag(Short.parseShort(data.substring(0, data.length() - 1)));
|
||||
}
|
||||
if (NBT_PATTERN_LONG.matcher(data).matches()) {
|
||||
return new LongTag(Long.parseLong(data.substring(0, data.length() - 1)));
|
||||
}
|
||||
if (NBT_PATTERN_INT.matcher(data).matches()) {
|
||||
return new IntTag(Integer.parseInt(data));
|
||||
}
|
||||
if (NBT_PATTERN_FLOAT.matcher(data).matches()) {
|
||||
return new FloatTag(Float.parseFloat(data.substring(0, data.length() - 1)));
|
||||
}
|
||||
if (NBT_PATTERN_DOUBLE.matcher(data).matches()) {
|
||||
return new DoubleTag(Double.parseDouble(data.endsWith("d") ? data.substring(0, data.length() - 1) : data));
|
||||
}
|
||||
} catch (NumberFormatException ignored) {
|
||||
}
|
||||
|
||||
return new StringTag(data);
|
||||
}
|
||||
|
||||
public CompoundTag readNBTCompoundTag() throws CompoundTagBadFormatCommandParseException, StringCommandParseException, ListTagBadFormatCommandParseException {
|
||||
if (peek() != '{') {
|
||||
throw new CompoundTagBadFormatCommandParseException(this, String.valueOf(peek()), "Not a compound tag!");
|
||||
}
|
||||
CompoundTag compoundTag = new CompoundTag();
|
||||
skip();
|
||||
skipWhitespaces();
|
||||
if (peek() == '}') {
|
||||
return compoundTag;
|
||||
}
|
||||
while (canRead()) {
|
||||
String key = readString();
|
||||
skipWhitespaces();
|
||||
if (peek() != ':') {
|
||||
throw new CompoundTagBadFormatCommandParseException(this, String.valueOf(peek()), "Invalid map char!");
|
||||
}
|
||||
skip();
|
||||
NBTTag value = readNBTTag();
|
||||
compoundTag.writeTag(key, value);
|
||||
skipWhitespaces();
|
||||
char nextChar = read();
|
||||
if (nextChar == '}') {
|
||||
return compoundTag;
|
||||
} else {
|
||||
skipWhitespaces();
|
||||
if (nextChar != ',') {
|
||||
throw new CompoundTagBadFormatCommandParseException(this, String.valueOf(nextChar), "Invalid map char!");
|
||||
}
|
||||
}
|
||||
}
|
||||
throw new CompoundTagBadFormatCommandParseException(this, String.valueOf(peek()), "No closing tag!");
|
||||
}
|
||||
|
||||
|
||||
public JsonElement readJson() throws InvalidJSONCommandParseException {
|
||||
try {
|
||||
JsonReader jsonReader = new JsonReader(new StringReader(getRemaining()));
|
||||
jsonReader.setLenient(false);
|
||||
JsonObject json = GSON.fromJson(jsonReader, JsonObject.class);
|
||||
|
||||
skip(Util.getJsonReaderPosition(jsonReader) - 1);
|
||||
return json;
|
||||
} catch (JsonParseException exception) {
|
||||
throw new InvalidJSONCommandParseException(this, String.valueOf(peek()), exception);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean readExpected(char... expected) {
|
||||
@ -367,6 +507,9 @@ public class CommandStringReader {
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
if (canRead()) {
|
||||
return String.format("position=%d/%d: \"%s\"", this.cursor, this.string.length(), peekRemaining());
|
||||
}
|
||||
return String.format("position=%d/%d", this.cursor, this.string.length());
|
||||
}
|
||||
}
|
||||
|
@ -13,10 +13,7 @@
|
||||
package de.bixilon.minosoft.data.commands.parser
|
||||
|
||||
import de.bixilon.minosoft.data.commands.CommandStringReader
|
||||
import de.bixilon.minosoft.data.commands.parser.exceptions.BlockNotFoundCommandParseException
|
||||
import de.bixilon.minosoft.data.commands.parser.exceptions.BlockPropertyDuplicatedCommandParseException
|
||||
import de.bixilon.minosoft.data.commands.parser.exceptions.CommandParseException
|
||||
import de.bixilon.minosoft.data.commands.parser.exceptions.UnknownBlockPropertyCommandParseException
|
||||
import de.bixilon.minosoft.data.commands.parser.exceptions.*
|
||||
import de.bixilon.minosoft.data.commands.parser.properties.ParserProperties
|
||||
import de.bixilon.minosoft.data.mappings.blocks.BlockProperties
|
||||
import de.bixilon.minosoft.data.mappings.blocks.BlockRotations
|
||||
@ -26,7 +23,13 @@ class BlockStateParser : CommandParser() {
|
||||
|
||||
@Throws(CommandParseException::class)
|
||||
override fun isParsable(connection: Connection, properties: ParserProperties?, stringReader: CommandStringReader) {
|
||||
val identifier = stringReader.readModIdentifier()
|
||||
if (this == BLOCK_PREDICATE_PARSER) {
|
||||
if (stringReader.peek() != '#') {
|
||||
throw InvalidBlockPredicateCommandParseException(stringReader, stringReader.read().toString())
|
||||
}
|
||||
stringReader.skip()
|
||||
}
|
||||
val identifier = stringReader.readModIdentifier() // ToDo: check tags
|
||||
if (!connection.mapping.doesBlockExist(identifier.value)) {
|
||||
throw BlockNotFoundCommandParseException(stringReader, identifier.key)
|
||||
}
|
||||
@ -51,11 +54,17 @@ class BlockStateParser : CommandParser() {
|
||||
val blockProperty = blockPropertyKey[pair.value] ?: throw UnknownBlockPropertyCommandParseException(stringReader, pair.value)
|
||||
allProperties.add(blockProperty)
|
||||
}
|
||||
}
|
||||
|
||||
if (this == BLOCK_PREDICATE_PARSER) {
|
||||
if (stringReader.canRead() && stringReader.peek() == '{') {
|
||||
stringReader.readNBTCompoundTag()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
val BLOCK_STACK_PARSER = BlockStateParser()
|
||||
val BLOCK_PREDICATE_PARSER = BlockStateParser()
|
||||
}
|
||||
}
|
||||
|
@ -33,13 +33,13 @@ object CommandParsers {
|
||||
ModIdentifier("vec3") to Vec3Parser.VEC3_PARSER,
|
||||
ModIdentifier("vec2") to Vec2Parser.VEC2_PARSER,
|
||||
ModIdentifier("block_state") to BlockStateParser.BLOCK_STACK_PARSER,
|
||||
// block_predicate
|
||||
ModIdentifier("block_predicate") to BlockStateParser.BLOCK_PREDICATE_PARSER,
|
||||
ModIdentifier("item_stack") to ItemStackParser.ITEM_STACK_PARSER,
|
||||
// item_predicate
|
||||
ModIdentifier("item_predicate") to ItemStackParser.ITEM_PREDICATE_PARSER,
|
||||
ModIdentifier("color") to ColorParser.COLOR_PARSER,
|
||||
// chat component
|
||||
ModIdentifier("component") to ComponentParser.COMPONENT_PARSER,
|
||||
ModIdentifier("message") to MessageParser.MESSAGE_PARSER,
|
||||
// nbt
|
||||
ModIdentifier("nbt") to NBTParser.NBT_PARSER,
|
||||
// nbt_path
|
||||
ModIdentifier("objective") to ObjectiveParser.OBJECTIVE_PARSER,
|
||||
// objective_criteria
|
||||
@ -62,8 +62,8 @@ object CommandParsers {
|
||||
ModIdentifier("entity_summon") to IdentifierListParser.SUMMONABLE_ENTITY_PARSER,
|
||||
ModIdentifier("dimension") to IdentifierListParser.DIMENSION_EFFECT_PARSER,
|
||||
ModIdentifier("uuid") to UUIDParser.UUID_PARSER,
|
||||
// nbt_tag
|
||||
// nbt_compound_tag
|
||||
ModIdentifier("nbt_tag") to NBTParser.NBT_TAG_PARSER,
|
||||
ModIdentifier("nbt_compound_tag") to NBTParser.NBT_COMPOUND_PARSER,
|
||||
ModIdentifier("time") to TimeParser.TIME_PARSER
|
||||
)
|
||||
)
|
||||
|
@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Minosoft
|
||||
* Copyright (C) 2020 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.data.commands.parser
|
||||
|
||||
import de.bixilon.minosoft.data.commands.CommandStringReader
|
||||
import de.bixilon.minosoft.data.commands.parser.exceptions.CommandParseException
|
||||
import de.bixilon.minosoft.data.commands.parser.exceptions.InvalidComponentCommandParseException
|
||||
import de.bixilon.minosoft.data.commands.parser.properties.ParserProperties
|
||||
import de.bixilon.minosoft.data.text.BaseComponent
|
||||
import de.bixilon.minosoft.protocol.network.Connection
|
||||
|
||||
class ComponentParser : CommandParser() {
|
||||
|
||||
@Throws(CommandParseException::class)
|
||||
override fun isParsable(connection: Connection, properties: ParserProperties?, stringReader: CommandStringReader) {
|
||||
try {
|
||||
BaseComponent(stringReader.readJson().asJsonObject)
|
||||
} catch (exception: Exception) {
|
||||
stringReader.skip(-1)
|
||||
throw InvalidComponentCommandParseException(stringReader, stringReader.read().toString(), exception)
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
val COMPONENT_PARSER = ComponentParser()
|
||||
}
|
||||
}
|
@ -32,7 +32,7 @@ abstract class CoordinateParser : CommandParser() {
|
||||
if (notation != CoordinateNotations.NONE) {
|
||||
stringReader.skip()
|
||||
}
|
||||
if (!stringReader.canRead() || stringReader.peek() != ' ') {
|
||||
if (!stringReader.canRead() || stringReader.peek() == ' ') {
|
||||
return notation
|
||||
}
|
||||
if (allowDecimal) {
|
||||
|
@ -92,12 +92,10 @@ public class EntityParser extends CommandParser {
|
||||
}
|
||||
}
|
||||
String value = stringReader.readUnquotedString();
|
||||
try {
|
||||
Util.doesStringEqualsRegex(value, ProtocolDefinition.MINECRAFT_NAME_VALIDATOR);
|
||||
return;
|
||||
} catch (IllegalArgumentException ignored) {
|
||||
}
|
||||
|
||||
if (ProtocolDefinition.MINECRAFT_NAME_VALIDATOR.matcher(value).matches()) {
|
||||
return;
|
||||
}
|
||||
if (entityParserProperties.isOnlyPlayers()) {
|
||||
throw new PlayerOnlyEntityCommandParseException(stringReader, value);
|
||||
}
|
||||
|
@ -14,6 +14,7 @@ package de.bixilon.minosoft.data.commands.parser
|
||||
|
||||
import de.bixilon.minosoft.data.commands.CommandStringReader
|
||||
import de.bixilon.minosoft.data.commands.parser.exceptions.CommandParseException
|
||||
import de.bixilon.minosoft.data.commands.parser.exceptions.InvalidItemPredicateCommandParseException
|
||||
import de.bixilon.minosoft.data.commands.parser.exceptions.identifier.ItemNotFoundCommandParseException
|
||||
import de.bixilon.minosoft.data.commands.parser.properties.ParserProperties
|
||||
import de.bixilon.minosoft.protocol.network.Connection
|
||||
@ -22,7 +23,13 @@ class ItemStackParser : CommandParser() {
|
||||
|
||||
@Throws(CommandParseException::class)
|
||||
override fun isParsable(connection: Connection, properties: ParserProperties?, stringReader: CommandStringReader) {
|
||||
val argument = stringReader.readModIdentifier()
|
||||
if (this == ITEM_PREDICATE_PARSER) {
|
||||
if (stringReader.peek() != '#') {
|
||||
throw InvalidItemPredicateCommandParseException(stringReader, stringReader.read().toString())
|
||||
}
|
||||
stringReader.skip()
|
||||
}
|
||||
val argument = stringReader.readModIdentifier() // ToDo: Check predicates
|
||||
if (!connection.mapping.doesItemExist(argument.value)) {
|
||||
throw ItemNotFoundCommandParseException(stringReader, argument.key)
|
||||
}
|
||||
@ -33,5 +40,6 @@ class ItemStackParser : CommandParser() {
|
||||
|
||||
companion object {
|
||||
val ITEM_STACK_PARSER = ItemStackParser()
|
||||
val ITEM_PREDICATE_PARSER = ItemStackParser()
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Minosoft
|
||||
* Copyright (C) 2020 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.data.commands.parser
|
||||
|
||||
import de.bixilon.minosoft.data.commands.CommandStringReader
|
||||
import de.bixilon.minosoft.data.commands.parser.exceptions.CommandParseException
|
||||
import de.bixilon.minosoft.data.commands.parser.exceptions.nbt.ExpectedPrimitiveTagCommandParseException
|
||||
import de.bixilon.minosoft.data.commands.parser.properties.ParserProperties
|
||||
import de.bixilon.minosoft.protocol.network.Connection
|
||||
import de.bixilon.minosoft.util.nbt.tag.CompoundTag
|
||||
|
||||
class NBTParser : CommandParser() {
|
||||
|
||||
@Throws(CommandParseException::class)
|
||||
override fun isParsable(connection: Connection, properties: ParserProperties?, stringReader: CommandStringReader) {
|
||||
when (this) {
|
||||
NBT_PARSER -> {
|
||||
stringReader.readNBTTag()
|
||||
}
|
||||
NBT_TAG_PARSER -> {
|
||||
val startPos = stringReader.cursor
|
||||
val tag = stringReader.readNBTTag()
|
||||
if (tag!! is CompoundTag) {
|
||||
throw ExpectedPrimitiveTagCommandParseException(stringReader, stringReader.string.substring(startPos, stringReader.cursor), "Compound Tag is invalid here!")
|
||||
}
|
||||
}
|
||||
NBT_COMPOUND_PARSER -> stringReader.readNBTCompoundTag()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
companion object {
|
||||
val NBT_PARSER = NBTParser()
|
||||
val NBT_TAG_PARSER = NBTParser()
|
||||
val NBT_COMPOUND_PARSER = NBTParser()
|
||||
}
|
||||
}
|
@ -18,17 +18,14 @@ import de.bixilon.minosoft.data.commands.parser.exceptions.identifier.InvalidIde
|
||||
import de.bixilon.minosoft.data.commands.parser.properties.ParserProperties
|
||||
import de.bixilon.minosoft.protocol.network.Connection
|
||||
import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition
|
||||
import de.bixilon.minosoft.util.Util
|
||||
|
||||
class ObjectiveParser : CommandParser() {
|
||||
|
||||
@Throws(CommandParseException::class)
|
||||
override fun isParsable(connection: Connection, properties: ParserProperties?, stringReader: CommandStringReader) {
|
||||
val argument = stringReader.readUnquotedString()
|
||||
try {
|
||||
Util.doesStringEqualsRegex(argument, ProtocolDefinition.SCOREBOARD_OBJECTIVE_PATTERN)
|
||||
} catch (exception: IllegalArgumentException) {
|
||||
throw InvalidIdentifierCommandParseException(stringReader, argument, exception)
|
||||
if (!ProtocolDefinition.SCOREBOARD_OBJECTIVE_PATTERN.matcher(argument).matches()) {
|
||||
throw InvalidIdentifierCommandParseException(stringReader, argument)
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Minosoft
|
||||
* Copyright (C) 2020 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.data.commands.parser.exceptions
|
||||
|
||||
import de.bixilon.minosoft.data.commands.CommandStringReader
|
||||
|
||||
class InvalidBlockPredicateCommandParseException : CommandParseException {
|
||||
constructor(command: CommandStringReader, currentArgument: String) : super(ERROR_MESSAGE, command, currentArgument)
|
||||
|
||||
constructor(command: CommandStringReader, currentArgument: String, cause: Throwable) : super(ERROR_MESSAGE, command, currentArgument, cause)
|
||||
|
||||
companion object {
|
||||
private const val ERROR_MESSAGE = "Invalid block predicate!"
|
||||
}
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Minosoft
|
||||
* Copyright (C) 2020 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.data.commands.parser.exceptions
|
||||
|
||||
import de.bixilon.minosoft.data.commands.CommandStringReader
|
||||
|
||||
class InvalidComponentCommandParseException : CommandParseException {
|
||||
constructor(command: CommandStringReader, currentArgument: String) : super(ERROR_MESSAGE, command, currentArgument)
|
||||
|
||||
constructor(command: CommandStringReader, currentArgument: String, cause: Throwable) : super(ERROR_MESSAGE, command, currentArgument, cause)
|
||||
|
||||
companion object {
|
||||
private const val ERROR_MESSAGE = "Malformed component!"
|
||||
}
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Minosoft
|
||||
* Copyright (C) 2020 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.data.commands.parser.exceptions
|
||||
|
||||
import de.bixilon.minosoft.data.commands.CommandStringReader
|
||||
|
||||
class InvalidItemPredicateCommandParseException : CommandParseException {
|
||||
constructor(command: CommandStringReader, currentArgument: String) : super(ERROR_MESSAGE, command, currentArgument)
|
||||
|
||||
constructor(command: CommandStringReader, currentArgument: String, cause: Throwable) : super(ERROR_MESSAGE, command, currentArgument, cause)
|
||||
|
||||
companion object {
|
||||
private const val ERROR_MESSAGE = "Invalid item predicate!"
|
||||
}
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Minosoft
|
||||
* Copyright (C) 2020 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.data.commands.parser.exceptions
|
||||
|
||||
import de.bixilon.minosoft.data.commands.CommandStringReader
|
||||
|
||||
class InvalidJSONCommandParseException : CommandParseException {
|
||||
constructor(command: CommandStringReader, currentArgument: String) : super(ERROR_MESSAGE, command, currentArgument)
|
||||
|
||||
constructor(command: CommandStringReader, currentArgument: String, cause: Throwable) : super(ERROR_MESSAGE, command, currentArgument, cause)
|
||||
|
||||
companion object {
|
||||
private const val ERROR_MESSAGE = "Malformed json!"
|
||||
}
|
||||
}
|
@ -17,7 +17,7 @@ import de.bixilon.minosoft.data.commands.CommandStringReader;
|
||||
|
||||
public class UnknownCommandParseException extends CommandParseException {
|
||||
|
||||
private static final String ERROR_MESSAGE = "Unknown command!";
|
||||
private static final String ERROR_MESSAGE = "Unknown command!" + 'a';
|
||||
|
||||
public UnknownCommandParseException(CommandStringReader command, String currentArgument) {
|
||||
super(ERROR_MESSAGE, command, currentArgument);
|
||||
|
@ -0,0 +1,22 @@
|
||||
/*
|
||||
* Minosoft
|
||||
* Copyright (C) 2020 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.data.commands.parser.exceptions.nbt
|
||||
|
||||
import de.bixilon.minosoft.data.commands.CommandStringReader
|
||||
import de.bixilon.minosoft.data.commands.parser.exceptions.CommandParseException
|
||||
|
||||
class CompoundTagBadFormatCommandParseException : CommandParseException {
|
||||
constructor(command: CommandStringReader, currentArgument: String, message: String) : super(message, command, currentArgument)
|
||||
|
||||
constructor(command: CommandStringReader, currentArgument: String, cause: Throwable, message: String) : super(message, command, currentArgument, cause)
|
||||
}
|
@ -0,0 +1,22 @@
|
||||
/*
|
||||
* Minosoft
|
||||
* Copyright (C) 2020 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.data.commands.parser.exceptions.nbt
|
||||
|
||||
import de.bixilon.minosoft.data.commands.CommandStringReader
|
||||
import de.bixilon.minosoft.data.commands.parser.exceptions.CommandParseException
|
||||
|
||||
class ExpectedPrimitiveTagCommandParseException : CommandParseException {
|
||||
constructor(command: CommandStringReader, currentArgument: String, message: String) : super(message, command, currentArgument)
|
||||
|
||||
constructor(command: CommandStringReader, currentArgument: String, cause: Throwable, message: String) : super(message, command, currentArgument, cause)
|
||||
}
|
@ -0,0 +1,22 @@
|
||||
/*
|
||||
* Minosoft
|
||||
* Copyright (C) 2020 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.data.commands.parser.exceptions.nbt
|
||||
|
||||
import de.bixilon.minosoft.data.commands.CommandStringReader
|
||||
import de.bixilon.minosoft.data.commands.parser.exceptions.CommandParseException
|
||||
|
||||
class ListTagBadFormatCommandParseException : CommandParseException {
|
||||
constructor(command: CommandStringReader, currentArgument: String, message: String) : super(message, command, currentArgument)
|
||||
|
||||
constructor(command: CommandStringReader, currentArgument: String, cause: Throwable) : super(cause.message, command, currentArgument, cause)
|
||||
}
|
@ -14,7 +14,6 @@
|
||||
package de.bixilon.minosoft.data.mappings;
|
||||
|
||||
import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition;
|
||||
import de.bixilon.minosoft.util.Util;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
@ -44,9 +43,7 @@ public class ModIdentifier {
|
||||
}
|
||||
|
||||
public static ModIdentifier getIdentifier(String identifier) throws IllegalArgumentException {
|
||||
try {
|
||||
Util.doesStringEqualsRegex(identifier, ProtocolDefinition.IDENTIFIER_PATTERN);
|
||||
} catch (IllegalArgumentException e) {
|
||||
if (!ProtocolDefinition.IDENTIFIER_PATTERN.matcher(identifier).matches()) {
|
||||
throw new IllegalArgumentException(String.format("%s in not a valid identifier!", identifier));
|
||||
}
|
||||
|
||||
|
@ -95,9 +95,7 @@ public class OfflineLoginController implements Initializable {
|
||||
}
|
||||
|
||||
private void checkData(ObservableValue<? extends String> observableValue, String oldValue, String newValue) {
|
||||
try {
|
||||
Util.doesStringEqualsRegex(this.username.getText(), ProtocolDefinition.MINECRAFT_NAME_VALIDATOR);
|
||||
} catch (IllegalArgumentException e) {
|
||||
if (!ProtocolDefinition.MINECRAFT_NAME_VALIDATOR.matcher(this.username.getText()).matches()) {
|
||||
this.addButton.setDisable(true);
|
||||
return;
|
||||
}
|
||||
|
@ -15,7 +15,6 @@ package de.bixilon.minosoft.protocol.packets.clientbound.play;
|
||||
|
||||
import de.bixilon.minosoft.data.commands.CommandNode;
|
||||
import de.bixilon.minosoft.data.commands.CommandRootNode;
|
||||
import de.bixilon.minosoft.data.commands.parser.exceptions.CommandParseException;
|
||||
import de.bixilon.minosoft.logging.Log;
|
||||
import de.bixilon.minosoft.protocol.network.Connection;
|
||||
import de.bixilon.minosoft.protocol.packets.ClientboundPacket;
|
||||
@ -38,26 +37,6 @@ public class PacketDeclareCommands extends ClientboundPacket {
|
||||
@Override
|
||||
public void handle(Connection connection) {
|
||||
connection.setCommandRootNode(getRootNode());
|
||||
// ToDo: Remove these dummy commands
|
||||
String[] commands = {
|
||||
"setblock ~3 ^3 3 minecraft:anvil",
|
||||
"setblock ~3 3 3 minecraft:anvila",
|
||||
"setblock ~3 3 3 minecraft:anvil[facing=east]",
|
||||
"setblock ~3 3 3 minecraft:anvil[facing=\"east\"]",
|
||||
"setblock ~3 3 3 minecraft:anvil[facing=east\"]",
|
||||
"setblock ~3 3 3 minecraft:anvil[facing=aeast]",
|
||||
};
|
||||
for (String command : commands) {
|
||||
try {
|
||||
getRootNode().isSyntaxCorrect(connection, command);
|
||||
Log.game("Command \"%s\" is valid", command);
|
||||
} catch (CommandParseException e) {
|
||||
Log.game("Command \"%s\" is invalid, %s: %s", command, e.getClass().getSimpleName(), e.getErrorMessage());
|
||||
e.printStackTrace();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -16,6 +16,7 @@ package de.bixilon.minosoft.util;
|
||||
import com.google.common.util.concurrent.ThreadFactoryBuilder;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParser;
|
||||
import com.google.gson.stream.JsonReader;
|
||||
import de.bixilon.minosoft.protocol.network.Connection;
|
||||
import de.bixilon.minosoft.protocol.protocol.InByteBuffer;
|
||||
import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition;
|
||||
@ -23,6 +24,7 @@ import org.apache.commons.compress.archivers.tar.TarArchiveEntry;
|
||||
import org.apache.commons.compress.archivers.tar.TarArchiveInputStream;
|
||||
|
||||
import java.io.*;
|
||||
import java.lang.reflect.Field;
|
||||
import java.net.URL;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.security.MessageDigest;
|
||||
@ -32,7 +34,6 @@ import java.util.Random;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ThreadFactory;
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.zip.*;
|
||||
|
||||
@ -42,6 +43,23 @@ public final class Util {
|
||||
public static final String LINE_SEPARATOR = System.getProperty("line.separator");
|
||||
private static final Random THREAD_LOCAL_RANDOM = ThreadLocalRandom.current();
|
||||
|
||||
private static final Field JSON_READER_POS_FIELD;
|
||||
private static final Field JSON_READER_LINE_START_FIELD;
|
||||
|
||||
static {
|
||||
new JsonReader(new StringReader(""));
|
||||
Class<?> jsonReadClass = JsonReader.class;
|
||||
try {
|
||||
JSON_READER_POS_FIELD = jsonReadClass.getDeclaredField("pos");
|
||||
JSON_READER_POS_FIELD.setAccessible(true);
|
||||
JSON_READER_LINE_START_FIELD = jsonReadClass.getDeclaredField("lineStart");
|
||||
JSON_READER_LINE_START_FIELD.setAccessible(true);
|
||||
} catch (NoSuchFieldException e) {
|
||||
e.printStackTrace();
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static UUID getUUIDFromString(String uuid) {
|
||||
uuid = uuid.trim();
|
||||
if (uuid.length() == 36) {
|
||||
@ -292,10 +310,11 @@ public final class Util {
|
||||
return !string.toLowerCase().equals(string);
|
||||
}
|
||||
|
||||
public static void doesStringEqualsRegex(String input, Pattern pattern) throws IllegalArgumentException {
|
||||
Matcher matcher = pattern.matcher(input);
|
||||
if (!matcher.find() || !matcher.group().equals(input)) {
|
||||
throw new IllegalArgumentException();
|
||||
public static int getJsonReaderPosition(JsonReader jsonReader) {
|
||||
try {
|
||||
return JSON_READER_POS_FIELD.getInt(jsonReader) - JSON_READER_LINE_START_FIELD.getInt(jsonReader) + 1;
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -20,36 +20,43 @@ import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
|
||||
public class ListTag extends NBTTag {
|
||||
private final TagTypes type;
|
||||
private final ArrayList<NBTTag> list;
|
||||
private TagTypes type;
|
||||
|
||||
public ListTag(TagTypes type, ArrayList<NBTTag> list) {
|
||||
this.type = type;
|
||||
this.list = list;
|
||||
}
|
||||
|
||||
public ListTag(TagTypes type, NBTTag[] list) {
|
||||
public ListTag(TagTypes type, NBTTag... list) {
|
||||
this.type = type;
|
||||
this.list = new ArrayList<>(Arrays.asList(list));
|
||||
}
|
||||
|
||||
|
||||
public ListTag() {
|
||||
this.type = TagTypes.BYTE; // idk, default value?
|
||||
this.list = new ArrayList<>();
|
||||
}
|
||||
|
||||
public ListTag(InByteBuffer buffer) {
|
||||
this.type = TagTypes.byId(new ByteTag(buffer).getValue());
|
||||
int length = new IntTag(buffer).getValue();
|
||||
this.list = new ArrayList<>();
|
||||
for (int i = 0; i < length; i++) {
|
||||
switch (this.type) {
|
||||
case BYTE -> this.list.add(new ByteTag(buffer));
|
||||
case SHORT -> this.list.add(new ShortTag(buffer));
|
||||
case INT -> this.list.add(new IntTag(buffer));
|
||||
case LONG -> this.list.add(new LongTag(buffer));
|
||||
case FLOAT -> this.list.add(new FloatTag(buffer));
|
||||
case DOUBLE -> this.list.add(new DoubleTag(buffer));
|
||||
case BYTE_ARRAY -> this.list.add(new ByteArrayTag(buffer));
|
||||
case STRING -> this.list.add(new StringTag(buffer));
|
||||
case LIST -> this.list.add(new ListTag(buffer));
|
||||
case COMPOUND -> this.list.add(new CompoundTag(true, buffer));
|
||||
}
|
||||
this.list.add(switch (this.type) {
|
||||
case BYTE -> new ByteTag(buffer);
|
||||
case SHORT -> new ShortTag(buffer);
|
||||
case INT -> new IntTag(buffer);
|
||||
case LONG -> new LongTag(buffer);
|
||||
case FLOAT -> new FloatTag(buffer);
|
||||
case DOUBLE -> new DoubleTag(buffer);
|
||||
case BYTE_ARRAY -> new ByteArrayTag(buffer);
|
||||
case STRING -> new StringTag(buffer);
|
||||
case LIST -> new ListTag(buffer);
|
||||
case COMPOUND -> new CompoundTag(true, buffer);
|
||||
default -> throw new IllegalStateException("Unexpected value: " + this.type);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@ -64,11 +71,23 @@ public class ListTag extends NBTTag {
|
||||
|
||||
new IntTag(this.list.size()).writeBytes(buffer);
|
||||
|
||||
for (NBTTag NBTTag : this.list) {
|
||||
NBTTag.writeBytes(buffer);
|
||||
for (NBTTag tag : this.list) {
|
||||
tag.writeBytes(buffer);
|
||||
}
|
||||
}
|
||||
|
||||
public ListTag addTag(NBTTag tag) {
|
||||
if (this.type == null) {
|
||||
this.type = tag.getType();
|
||||
} else {
|
||||
if (this.type != tag.getType()) {
|
||||
throw new IllegalArgumentException("Can not mix types!");
|
||||
}
|
||||
}
|
||||
this.list.add(tag);
|
||||
return this;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public <K extends NBTTag> ArrayList<K> getValue() {
|
||||
return (ArrayList<K>) this.list;
|
||||
|
Loading…
x
Reference in New Issue
Block a user