mirror of
https://github.com/ViaVersion/ViaLegacy.git
synced 2025-01-08 19:28:11 +01:00
Rewrote nbt and text translation
This commit is contained in:
parent
1a706fd04f
commit
b4d755cf07
@ -155,7 +155,7 @@ public class Protocol1_7_2_5to1_6_4 extends AbstractProtocol<ClientboundPackets1
|
||||
this.registerClientbound(State.LOGIN, ClientboundPackets1_6_4.DISCONNECT.getId(), ClientboundLoginPackets.LOGIN_DISCONNECT.getId(), new PacketHandlers() {
|
||||
@Override
|
||||
public void register() {
|
||||
map(Types1_6_4.STRING, Type.STRING, ChatComponentRewriter::toClient); // reason
|
||||
map(Types1_6_4.STRING, Type.STRING, ChatComponentRewriter::toClientDisconnect); // reason
|
||||
}
|
||||
});
|
||||
this.cancelClientbound(State.LOGIN, ClientboundPackets1_6_4.PLUGIN_MESSAGE.getId());
|
||||
@ -884,7 +884,7 @@ public class Protocol1_7_2_5to1_6_4 extends AbstractProtocol<ClientboundPackets1
|
||||
this.registerClientbound(ClientboundPackets1_6_4.DISCONNECT, new PacketHandlers() {
|
||||
@Override
|
||||
public void register() {
|
||||
map(Types1_6_4.STRING, Type.STRING, ChatComponentRewriter::toClient);
|
||||
map(Types1_6_4.STRING, Type.STRING, ChatComponentRewriter::toClientDisconnect); // reason
|
||||
}
|
||||
});
|
||||
this.cancelClientbound(ClientboundPackets1_6_4.CREATIVE_INVENTORY_ACTION);
|
||||
|
@ -17,24 +17,24 @@
|
||||
*/
|
||||
package net.raphimc.vialegacy.protocols.release.protocol1_7_2_5to1_6_4.rewriter;
|
||||
|
||||
import com.viaversion.viaversion.libs.gson.JsonElement;
|
||||
import com.viaversion.viaversion.libs.gson.JsonObject;
|
||||
import com.viaversion.viaversion.rewriter.ComponentRewriter;
|
||||
import net.lenni0451.mcstructs.text.ATextComponent;
|
||||
import net.lenni0451.mcstructs.text.components.StringComponent;
|
||||
import net.lenni0451.mcstructs.text.serializer.LegacyStringDeserializer;
|
||||
import net.lenni0451.mcstructs.text.serializer.TextComponentSerializer;
|
||||
import net.lenni0451.mcstructs.text.utils.TextUtils;
|
||||
|
||||
public class ChatComponentRewriter {
|
||||
|
||||
private static final ComponentRewriter FIX_COMPONENT = new ComponentRewriter() {
|
||||
@Override
|
||||
protected void handleTranslate(JsonObject object, String translate) {
|
||||
final JsonElement args = object.remove("using");
|
||||
if (args != null) {
|
||||
object.add("with", args);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
public static String toClient(final String text) {
|
||||
return FIX_COMPONENT.processText(text).toString();
|
||||
final ATextComponent component = TextComponentSerializer.V1_6.deserialize(text);
|
||||
// Convert all section sign formatted strings to json formatted ones with styles so the formatting isn't reset on chat line split
|
||||
final ATextComponent newComponent = TextUtils.replace(component, ".*", c -> LegacyStringDeserializer.parse(c.asSingleString(), true).setStyle(c.getStyle()));
|
||||
// Also convert "using" -> "with" in translatable components
|
||||
return TextComponentSerializer.V1_7.serialize(newComponent);
|
||||
}
|
||||
|
||||
public static String toClientDisconnect(final String reason) {
|
||||
return TextComponentSerializer.V1_7.serialize(new StringComponent(reason));
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -29,9 +29,10 @@ import com.viaversion.viaversion.libs.opennbt.tag.builtin.CompoundTag;
|
||||
import com.viaversion.viaversion.libs.opennbt.tag.builtin.ShortTag;
|
||||
import com.viaversion.viaversion.libs.opennbt.tag.builtin.StringTag;
|
||||
import com.viaversion.viaversion.rewriter.ComponentRewriter;
|
||||
import net.lenni0451.mcstructs.snbt.SNbtSerializer;
|
||||
import net.raphimc.vialegacy.ViaLegacy;
|
||||
import net.raphimc.vialegacy.protocols.release.protocol1_8to1_7_6_10.Protocol1_8to1_7_6_10;
|
||||
import net.raphimc.vialegacy.util.ViaStringTagReader1_11_2;
|
||||
import net.raphimc.vialegacy.util.NbtConverter;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
@ -375,8 +376,8 @@ public class ChatItemRewriter {
|
||||
|
||||
final CompoundTag tag;
|
||||
try {
|
||||
tag = ViaStringTagReader1_11_2.getTagFromJson(text);
|
||||
} catch (Exception e) {
|
||||
tag = (CompoundTag) NbtConverter.mcStructToVia(SNbtSerializer.V1_7.deserialize(text));
|
||||
} catch (Throwable e) {
|
||||
ViaLegacy.getPlatform().getLogger().warning("Error reading NBT in show_item:" + text);
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
65
src/main/java/net/raphimc/vialegacy/util/NbtConverter.java
Normal file
65
src/main/java/net/raphimc/vialegacy/util/NbtConverter.java
Normal file
@ -0,0 +1,65 @@
|
||||
/*
|
||||
* This file is part of ViaLegacy - https://github.com/RaphiMC/ViaLegacy
|
||||
* Copyright (C) 2023 RK_01/RaphiMC and contributors
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package net.raphimc.vialegacy.util;
|
||||
|
||||
import com.viaversion.viaversion.libs.opennbt.tag.builtin.*;
|
||||
import net.lenni0451.mcstructs.nbt.INbtTag;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public class NbtConverter {
|
||||
|
||||
public static Tag mcStructToVia(final INbtTag tag) {
|
||||
if (tag == null) return null;
|
||||
if (tag instanceof net.lenni0451.mcstructs.nbt.tags.ByteTag) {
|
||||
return new ByteTag(tag.asByteTag().getValue());
|
||||
} else if (tag instanceof net.lenni0451.mcstructs.nbt.tags.ShortTag) {
|
||||
return new ShortTag(tag.asShortTag().getValue());
|
||||
} else if (tag instanceof net.lenni0451.mcstructs.nbt.tags.IntTag) {
|
||||
return new IntTag(tag.asIntTag().getValue());
|
||||
} else if (tag instanceof net.lenni0451.mcstructs.nbt.tags.LongTag) {
|
||||
return new LongTag(tag.asLongTag().getValue());
|
||||
} else if (tag instanceof net.lenni0451.mcstructs.nbt.tags.FloatTag) {
|
||||
return new FloatTag(tag.asFloatTag().getValue());
|
||||
} else if (tag instanceof net.lenni0451.mcstructs.nbt.tags.DoubleTag) {
|
||||
return new DoubleTag(tag.asDoubleTag().getValue());
|
||||
} else if (tag instanceof net.lenni0451.mcstructs.nbt.tags.ByteArrayTag) {
|
||||
return new ByteArrayTag(tag.asByteArrayTag().getValue());
|
||||
} else if (tag instanceof net.lenni0451.mcstructs.nbt.tags.StringTag) {
|
||||
return new StringTag(tag.asStringTag().getValue());
|
||||
} else if (tag instanceof net.lenni0451.mcstructs.nbt.tags.ListTag) {
|
||||
final ListTag list = new ListTag();
|
||||
for (INbtTag e : tag.asListTag()) {
|
||||
list.add(mcStructToVia(e));
|
||||
}
|
||||
return list;
|
||||
} else if (tag instanceof net.lenni0451.mcstructs.nbt.tags.CompoundTag) {
|
||||
final CompoundTag compound = new CompoundTag();
|
||||
for (Map.Entry<String, INbtTag> e : tag.asCompoundTag().getValue().entrySet()) {
|
||||
compound.put(e.getKey(), mcStructToVia(e.getValue()));
|
||||
}
|
||||
return compound;
|
||||
} else if (tag instanceof net.lenni0451.mcstructs.nbt.tags.IntArrayTag) {
|
||||
return new IntArrayTag(tag.asIntArrayTag().getValue());
|
||||
} else if (tag instanceof net.lenni0451.mcstructs.nbt.tags.LongArrayTag) {
|
||||
return new LongArrayTag(tag.asLongArrayTag().getValue());
|
||||
}
|
||||
throw new IllegalArgumentException("Unsupported tag type: " + tag.getClass().getName());
|
||||
}
|
||||
|
||||
}
|
@ -1,439 +0,0 @@
|
||||
/*
|
||||
* This file is part of ViaLegacy - https://github.com/RaphiMC/ViaLegacy
|
||||
* Copyright (C) 2023 RK_01/RaphiMC and contributors
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package net.raphimc.vialegacy.util;
|
||||
|
||||
import com.google.common.base.Splitter;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.viaversion.viaversion.libs.opennbt.tag.builtin.*;
|
||||
|
||||
import java.util.Stack;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
@Deprecated // Replace with mcstructs
|
||||
public class ViaStringTagReader1_11_2 {
|
||||
|
||||
private static final Pattern INT_ARRAY_MATCHER = Pattern.compile("\\[[-+\\d|,\\s]+\\]");
|
||||
|
||||
public static CompoundTag getTagFromJson(String jsonString) throws RuntimeException {
|
||||
jsonString = jsonString.trim();
|
||||
|
||||
if (!jsonString.startsWith("{")) {
|
||||
throw new RuntimeException("Invalid tag encountered, expected '{' as first char.");
|
||||
} else if (topTagsCount(jsonString) != 1) {
|
||||
throw new RuntimeException("Encountered multiple top tags, only one expected");
|
||||
} else {
|
||||
return (CompoundTag) nameValueToNBT("tag", jsonString).parse();
|
||||
}
|
||||
}
|
||||
|
||||
static int topTagsCount(String str) throws RuntimeException {
|
||||
int i = 0;
|
||||
boolean flag = false;
|
||||
Stack<Character> stack = new Stack<>();
|
||||
|
||||
for (int j = 0; j < str.length(); ++j) {
|
||||
char c0 = str.charAt(j);
|
||||
|
||||
if (c0 == 34) {
|
||||
if (isCharEscaped(str, j)) {
|
||||
if (!flag) {
|
||||
throw new RuntimeException("Illegal use of \\\": " + str);
|
||||
}
|
||||
} else {
|
||||
flag = !flag;
|
||||
}
|
||||
} else if (!flag) {
|
||||
if (c0 != 123 && c0 != 91) {
|
||||
if (c0 == 125 && (stack.isEmpty() || stack.pop() != 123)) {
|
||||
throw new RuntimeException("Unbalanced curly brackets {}: " + str);
|
||||
}
|
||||
|
||||
if (c0 == 93 && (stack.isEmpty() || stack.pop() != 91)) {
|
||||
throw new RuntimeException("Unbalanced square brackets []: " + str);
|
||||
}
|
||||
} else {
|
||||
if (stack.isEmpty()) {
|
||||
++i;
|
||||
}
|
||||
|
||||
stack.push(c0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (flag) {
|
||||
throw new RuntimeException("Unbalanced quotation: " + str);
|
||||
} else if (!stack.isEmpty()) {
|
||||
throw new RuntimeException("Unbalanced brackets: " + str);
|
||||
} else {
|
||||
if (i == 0 && !str.isEmpty()) {
|
||||
i = 1;
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
static ViaStringTagReader1_11_2.Any joinStrToNBT(String... args) throws RuntimeException {
|
||||
return nameValueToNBT(args[0], args[1]);
|
||||
}
|
||||
|
||||
static ViaStringTagReader1_11_2.Any nameValueToNBT(String key, String value) throws RuntimeException {
|
||||
value = value.trim();
|
||||
|
||||
if (value.startsWith("{")) {
|
||||
value = value.substring(1, value.length() - 1);
|
||||
ViaStringTagReader1_11_2.Compound jsontonbt$compound;
|
||||
String s1;
|
||||
|
||||
for (jsontonbt$compound = new ViaStringTagReader1_11_2.Compound(key); value.length() > 0; value = value.substring(s1.length() + 1)) {
|
||||
s1 = nextNameValuePair(value, true);
|
||||
|
||||
if (s1.length() > 0) {
|
||||
jsontonbt$compound.tagList.add(getTagFromNameValue(s1, false));
|
||||
}
|
||||
|
||||
if (value.length() < s1.length() + 1) {
|
||||
break;
|
||||
}
|
||||
|
||||
char c1 = value.charAt(s1.length());
|
||||
|
||||
if (c1 != 44 && c1 != 123 && c1 != 125 && c1 != 91 && c1 != 93) {
|
||||
throw new RuntimeException("Unexpected token '" + c1 + "' at: " + value.substring(s1.length()));
|
||||
}
|
||||
}
|
||||
|
||||
return jsontonbt$compound;
|
||||
} else if (value.startsWith("[") && !INT_ARRAY_MATCHER.matcher(value).matches()) {
|
||||
value = value.substring(1, value.length() - 1);
|
||||
ViaStringTagReader1_11_2.List jsontonbt$list;
|
||||
String s;
|
||||
|
||||
for (jsontonbt$list = new ViaStringTagReader1_11_2.List(key); value.length() > 0; value = value.substring(s.length() + 1)) {
|
||||
s = nextNameValuePair(value, false);
|
||||
|
||||
if (s.length() > 0) {
|
||||
jsontonbt$list.tagList.add(getTagFromNameValue(s, true));
|
||||
}
|
||||
|
||||
if (value.length() < s.length() + 1) {
|
||||
break;
|
||||
}
|
||||
|
||||
char c0 = value.charAt(s.length());
|
||||
|
||||
if (c0 != 44 && c0 != 123 && c0 != 125 && c0 != 91 && c0 != 93) {
|
||||
throw new RuntimeException("Unexpected token '" + c0 + "' at: " + value.substring(s.length()));
|
||||
}
|
||||
}
|
||||
|
||||
return jsontonbt$list;
|
||||
} else {
|
||||
return new ViaStringTagReader1_11_2.Primitive(key, value);
|
||||
}
|
||||
}
|
||||
|
||||
private static ViaStringTagReader1_11_2.Any getTagFromNameValue(String str, boolean isArray) throws RuntimeException {
|
||||
String s = locateName(str, isArray);
|
||||
String s1 = locateValue(str, isArray);
|
||||
return joinStrToNBT(s, s1);
|
||||
}
|
||||
|
||||
private static String nextNameValuePair(String str, boolean isCompound) throws RuntimeException {
|
||||
int i = getNextCharIndex(str, ':');
|
||||
int j = getNextCharIndex(str, ',');
|
||||
|
||||
if (isCompound) {
|
||||
if (i == -1) {
|
||||
throw new RuntimeException("Unable to locate name/value separator for string: " + str);
|
||||
}
|
||||
|
||||
if (j != -1 && j < i) {
|
||||
throw new RuntimeException("Name error at: " + str);
|
||||
}
|
||||
} else if (i == -1 || i > j) {
|
||||
i = -1;
|
||||
}
|
||||
|
||||
return locateValueAt(str, i);
|
||||
}
|
||||
|
||||
private static String locateValueAt(String str, int index) throws RuntimeException {
|
||||
Stack<Character> stack = new Stack<>();
|
||||
int i = index + 1;
|
||||
boolean flag = false;
|
||||
boolean flag1 = false;
|
||||
boolean flag2 = false;
|
||||
|
||||
for (int j = 0; i < str.length(); ++i) {
|
||||
char c0 = str.charAt(i);
|
||||
|
||||
if (c0 == 34) {
|
||||
if (isCharEscaped(str, i)) {
|
||||
if (!flag) {
|
||||
throw new RuntimeException("Illegal use of \\\": " + str);
|
||||
}
|
||||
} else {
|
||||
flag = !flag;
|
||||
|
||||
if (flag && !flag2) {
|
||||
flag1 = true;
|
||||
}
|
||||
|
||||
if (!flag) {
|
||||
j = i;
|
||||
}
|
||||
}
|
||||
} else if (!flag) {
|
||||
if (c0 != 123 && c0 != 91) {
|
||||
if (c0 == 125 && (stack.isEmpty() || stack.pop() != 123)) {
|
||||
throw new RuntimeException("Unbalanced curly brackets {}: " + str);
|
||||
}
|
||||
|
||||
if (c0 == 93 && (stack.isEmpty() || stack.pop() != 91)) {
|
||||
throw new RuntimeException("Unbalanced square brackets []: " + str);
|
||||
}
|
||||
|
||||
if (c0 == 44 && stack.isEmpty()) {
|
||||
return str.substring(0, i);
|
||||
}
|
||||
} else {
|
||||
stack.push(c0);
|
||||
}
|
||||
}
|
||||
|
||||
if (!Character.isWhitespace(c0)) {
|
||||
if (!flag && flag1 && j != i) {
|
||||
return str.substring(0, j + 1);
|
||||
}
|
||||
|
||||
flag2 = true;
|
||||
}
|
||||
}
|
||||
|
||||
return str.substring(0, i);
|
||||
}
|
||||
|
||||
private static String locateName(String str, boolean isArray) throws RuntimeException {
|
||||
if (isArray) {
|
||||
str = str.trim();
|
||||
|
||||
if (str.startsWith("{") || str.startsWith("[")) {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
int i = getNextCharIndex(str, ':');
|
||||
|
||||
if (i == -1) {
|
||||
if (isArray) {
|
||||
return "";
|
||||
} else {
|
||||
throw new RuntimeException("Unable to locate name/value separator for string: " + str);
|
||||
}
|
||||
} else {
|
||||
return str.substring(0, i).trim();
|
||||
}
|
||||
}
|
||||
|
||||
private static String locateValue(String str, boolean isArray) throws RuntimeException {
|
||||
if (isArray) {
|
||||
str = str.trim();
|
||||
|
||||
if (str.startsWith("{") || str.startsWith("[")) {
|
||||
return str;
|
||||
}
|
||||
}
|
||||
|
||||
int i = getNextCharIndex(str, ':');
|
||||
|
||||
if (i == -1) {
|
||||
if (isArray) {
|
||||
return str;
|
||||
} else {
|
||||
throw new RuntimeException("Unable to locate name/value separator for string: " + str);
|
||||
}
|
||||
} else {
|
||||
return str.substring(i + 1).trim();
|
||||
}
|
||||
}
|
||||
|
||||
private static int getNextCharIndex(String str, char targetChar) {
|
||||
int i = 0;
|
||||
|
||||
for (boolean flag = true; i < str.length(); ++i) {
|
||||
char c0 = str.charAt(i);
|
||||
|
||||
if (c0 == 34) {
|
||||
if (!isCharEscaped(str, i)) {
|
||||
flag = !flag;
|
||||
}
|
||||
} else if (flag) {
|
||||
if (c0 == targetChar) {
|
||||
return i;
|
||||
}
|
||||
|
||||
if (c0 == 123 || c0 == 91) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
private static boolean isCharEscaped(String str, int index) {
|
||||
return index > 0 && str.charAt(index - 1) == 92 && !isCharEscaped(str, index - 1);
|
||||
}
|
||||
|
||||
abstract static class Any {
|
||||
protected String json;
|
||||
|
||||
public abstract Tag parse() throws RuntimeException;
|
||||
}
|
||||
|
||||
static class Compound extends ViaStringTagReader1_11_2.Any {
|
||||
protected java.util.List<ViaStringTagReader1_11_2.Any> tagList = Lists.newArrayList();
|
||||
|
||||
public Compound(String jsonIn) {
|
||||
this.json = jsonIn;
|
||||
}
|
||||
|
||||
public Tag parse() throws RuntimeException {
|
||||
CompoundTag nbttagcompound = new CompoundTag();
|
||||
|
||||
for (ViaStringTagReader1_11_2.Any jsontonbt$any : this.tagList) {
|
||||
nbttagcompound.put(jsontonbt$any.json, jsontonbt$any.parse());
|
||||
}
|
||||
|
||||
return nbttagcompound;
|
||||
}
|
||||
}
|
||||
|
||||
static class List extends ViaStringTagReader1_11_2.Any {
|
||||
protected java.util.List<ViaStringTagReader1_11_2.Any> tagList = Lists.newArrayList();
|
||||
|
||||
public List(String json) {
|
||||
this.json = json;
|
||||
}
|
||||
|
||||
public Tag parse() throws RuntimeException {
|
||||
ListTag nbttaglist = new ListTag();
|
||||
|
||||
for (ViaStringTagReader1_11_2.Any jsontonbt$any : this.tagList) {
|
||||
nbttaglist.add(jsontonbt$any.parse());
|
||||
}
|
||||
|
||||
return nbttaglist;
|
||||
}
|
||||
}
|
||||
|
||||
static class Primitive extends ViaStringTagReader1_11_2.Any {
|
||||
private static final Pattern DOUBLE = Pattern.compile("[-+]?[0-9]*\\.?[0-9]+[d|D]");
|
||||
private static final Pattern FLOAT = Pattern.compile("[-+]?[0-9]*\\.?[0-9]+[f|F]");
|
||||
private static final Pattern BYTE = Pattern.compile("[-+]?[0-9]+[b|B]");
|
||||
private static final Pattern LONG = Pattern.compile("[-+]?[0-9]+[l|L]");
|
||||
private static final Pattern SHORT = Pattern.compile("[-+]?[0-9]+[s|S]");
|
||||
private static final Pattern INTEGER = Pattern.compile("[-+]?[0-9]+");
|
||||
private static final Pattern DOUBLE_UNTYPED = Pattern.compile("[-+]?[0-9]*\\.?[0-9]+");
|
||||
private static final Splitter SPLITTER = Splitter.on(',').omitEmptyStrings();
|
||||
protected String jsonValue;
|
||||
|
||||
public Primitive(String jsonIn, String valueIn) {
|
||||
this.json = jsonIn;
|
||||
this.jsonValue = valueIn;
|
||||
}
|
||||
|
||||
public Tag parse() throws RuntimeException {
|
||||
try {
|
||||
if (DOUBLE.matcher(this.jsonValue).matches()) {
|
||||
return new DoubleTag(Double.parseDouble(this.jsonValue.substring(0, this.jsonValue.length() - 1)));
|
||||
}
|
||||
|
||||
if (FLOAT.matcher(this.jsonValue).matches()) {
|
||||
return new FloatTag(Float.parseFloat(this.jsonValue.substring(0, this.jsonValue.length() - 1)));
|
||||
}
|
||||
|
||||
if (BYTE.matcher(this.jsonValue).matches()) {
|
||||
return new ByteTag(Byte.parseByte(this.jsonValue.substring(0, this.jsonValue.length() - 1)));
|
||||
}
|
||||
|
||||
if (LONG.matcher(this.jsonValue).matches()) {
|
||||
return new LongTag(Long.parseLong(this.jsonValue.substring(0, this.jsonValue.length() - 1)));
|
||||
}
|
||||
|
||||
if (SHORT.matcher(this.jsonValue).matches()) {
|
||||
return new ShortTag(Short.parseShort(this.jsonValue.substring(0, this.jsonValue.length() - 1)));
|
||||
}
|
||||
|
||||
if (INTEGER.matcher(this.jsonValue).matches()) {
|
||||
return new IntTag(Integer.parseInt(this.jsonValue));
|
||||
}
|
||||
|
||||
if (DOUBLE_UNTYPED.matcher(this.jsonValue).matches()) {
|
||||
return new DoubleTag(Double.parseDouble(this.jsonValue));
|
||||
}
|
||||
|
||||
if ("true".equalsIgnoreCase(this.jsonValue) || "false".equalsIgnoreCase(this.jsonValue)) {
|
||||
return new ByteTag((byte) (Boolean.parseBoolean(this.jsonValue) ? 1 : 0));
|
||||
}
|
||||
} catch (NumberFormatException var6) {
|
||||
this.jsonValue = this.jsonValue.replaceAll("\\\\\"", "\"");
|
||||
return new StringTag(this.jsonValue);
|
||||
}
|
||||
|
||||
if (this.jsonValue.startsWith("[") && this.jsonValue.endsWith("]")) {
|
||||
String s = this.jsonValue.substring(1, this.jsonValue.length() - 1);
|
||||
String[] astring = Iterables.toArray(SPLITTER.split(s), String.class);
|
||||
|
||||
try {
|
||||
int[] aint = new int[astring.length];
|
||||
|
||||
for (int j = 0; j < astring.length; ++j) {
|
||||
aint[j] = Integer.parseInt(astring[j].trim());
|
||||
}
|
||||
|
||||
return new IntArrayTag(aint);
|
||||
} catch (NumberFormatException var5) {
|
||||
return new StringTag(this.jsonValue);
|
||||
}
|
||||
} else {
|
||||
if (this.jsonValue.startsWith("\"") && this.jsonValue.endsWith("\"")) {
|
||||
this.jsonValue = this.jsonValue.substring(1, this.jsonValue.length() - 1);
|
||||
}
|
||||
|
||||
this.jsonValue = this.jsonValue.replaceAll("\\\\\"", "\"");
|
||||
StringBuilder stringbuilder = new StringBuilder();
|
||||
|
||||
for (int i = 0; i < this.jsonValue.length(); ++i) {
|
||||
if (i < this.jsonValue.length() - 1 && this.jsonValue.charAt(i) == 92 && this.jsonValue.charAt(i + 1) == 92) {
|
||||
stringbuilder.append('\\');
|
||||
++i;
|
||||
} else {
|
||||
stringbuilder.append(this.jsonValue.charAt(i));
|
||||
}
|
||||
}
|
||||
|
||||
return new StringTag(stringbuilder.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -1,425 +0,0 @@
|
||||
/*
|
||||
* This file is part of ViaLegacy - https://github.com/RaphiMC/ViaLegacy
|
||||
* Copyright (C) 2023 RK_01/RaphiMC and contributors
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package net.raphimc.vialegacy.util;
|
||||
|
||||
|
||||
import com.viaversion.viaversion.libs.opennbt.tag.TagRegistry;
|
||||
import com.viaversion.viaversion.libs.opennbt.tag.builtin.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
@Deprecated // Replace with mcstructs
|
||||
public class ViaStringTagReader1_12_2 {
|
||||
|
||||
private static final Pattern DOUBLE_PATTERN_IMPLICIT = Pattern.compile("[-+]?(?:[0-9]+[.]|[0-9]*[.][0-9]+)(?:e[-+]?[0-9]+)?", Pattern.CASE_INSENSITIVE);
|
||||
private static final Pattern DOUBLE_PATTERN = Pattern.compile("[-+]?(?:[0-9]+[.]?|[0-9]*[.][0-9]+)(?:e[-+]?[0-9]+)?d", Pattern.CASE_INSENSITIVE);
|
||||
private static final Pattern FLOAT_PATTERN = Pattern.compile("[-+]?(?:[0-9]+[.]?|[0-9]*[.][0-9]+)(?:e[-+]?[0-9]+)?f", Pattern.CASE_INSENSITIVE);
|
||||
private static final Pattern BYTE_PATTERN = Pattern.compile("[-+]?(?:0|[1-9][0-9]*)b", Pattern.CASE_INSENSITIVE);
|
||||
private static final Pattern LONG_PATTERN = Pattern.compile("[-+]?(?:0|[1-9][0-9]*)l", Pattern.CASE_INSENSITIVE);
|
||||
private static final Pattern SHORT_PATTERN = Pattern.compile("[-+]?(?:0|[1-9][0-9]*)s", Pattern.CASE_INSENSITIVE);
|
||||
private static final Pattern INT_PATTERN = Pattern.compile("[-+]?(?:0|[1-9][0-9]*)");
|
||||
private final String JSON_TAG;
|
||||
private int currentPosition;
|
||||
|
||||
private ViaStringTagReader1_12_2(String jsonTag) {
|
||||
this.JSON_TAG = jsonTag;
|
||||
}
|
||||
|
||||
public static CompoundTag getTagFromJson(String jsonString) throws NBTException {
|
||||
return (new ViaStringTagReader1_12_2(jsonString)).readCompound();
|
||||
}
|
||||
|
||||
private CompoundTag readCompound() throws NBTException {
|
||||
CompoundTag nbttagcompound = this.parseCompound();
|
||||
this.skipWhitespace();
|
||||
|
||||
if (this.canRead()) {
|
||||
++this.currentPosition;
|
||||
throw this.makeError("Trailing data found");
|
||||
} else {
|
||||
return nbttagcompound;
|
||||
}
|
||||
}
|
||||
|
||||
private String readString() throws NBTException {
|
||||
this.skipWhitespace();
|
||||
|
||||
if (!this.canRead()) {
|
||||
throw this.makeError("Expected key");
|
||||
} else {
|
||||
return this.peek() == '"' ? this.readQuotedString() : this.readUnquotedString();
|
||||
}
|
||||
}
|
||||
|
||||
private NBTException makeError(String message) {
|
||||
return new NBTException(message, this.JSON_TAG, this.currentPosition);
|
||||
}
|
||||
|
||||
private Tag parseTagPrimitive() throws NBTException {
|
||||
this.skipWhitespace();
|
||||
|
||||
if (this.peek() == '"') {
|
||||
return new StringTag(this.readQuotedString());
|
||||
} else {
|
||||
String s = this.readUnquotedString();
|
||||
|
||||
if (s.isEmpty()) {
|
||||
throw this.makeError("Expected value");
|
||||
} else {
|
||||
return this.parsePrimitive(s);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Tag parsePrimitive(String input) {
|
||||
try {
|
||||
if (FLOAT_PATTERN.matcher(input).matches()) {
|
||||
return new FloatTag(Float.parseFloat(input.substring(0, input.length() - 1)));
|
||||
}
|
||||
|
||||
if (BYTE_PATTERN.matcher(input).matches()) {
|
||||
return new ByteTag(Byte.parseByte(input.substring(0, input.length() - 1)));
|
||||
}
|
||||
|
||||
if (LONG_PATTERN.matcher(input).matches()) {
|
||||
return new LongTag(Long.parseLong(input.substring(0, input.length() - 1)));
|
||||
}
|
||||
|
||||
if (SHORT_PATTERN.matcher(input).matches()) {
|
||||
return new ShortTag(Short.parseShort(input.substring(0, input.length() - 1)));
|
||||
}
|
||||
|
||||
if (INT_PATTERN.matcher(input).matches()) {
|
||||
return new IntTag(Integer.parseInt(input));
|
||||
}
|
||||
|
||||
if (DOUBLE_PATTERN.matcher(input).matches()) {
|
||||
return new DoubleTag(Double.parseDouble(input.substring(0, input.length() - 1)));
|
||||
}
|
||||
|
||||
if (DOUBLE_PATTERN_IMPLICIT.matcher(input).matches()) {
|
||||
return new DoubleTag(Double.parseDouble(input));
|
||||
}
|
||||
|
||||
if ("true".equalsIgnoreCase(input)) {
|
||||
return new ByteTag((byte) 1);
|
||||
}
|
||||
|
||||
if ("false".equalsIgnoreCase(input)) {
|
||||
return new ByteTag((byte) 0);
|
||||
}
|
||||
} catch (NumberFormatException ignored) {
|
||||
}
|
||||
|
||||
return new StringTag(input);
|
||||
}
|
||||
|
||||
private String readQuotedString() throws NBTException {
|
||||
int i = ++this.currentPosition;
|
||||
StringBuilder stringbuilder = null;
|
||||
boolean flag = false;
|
||||
|
||||
while (this.canRead()) {
|
||||
char c0 = this.read();
|
||||
|
||||
if (flag) {
|
||||
if (c0 != '\\' && c0 != '"') {
|
||||
throw this.makeError("Invalid escape of '" + c0 + "'");
|
||||
}
|
||||
|
||||
flag = false;
|
||||
} else {
|
||||
if (c0 == '\\') {
|
||||
flag = true;
|
||||
|
||||
if (stringbuilder == null) {
|
||||
stringbuilder = new StringBuilder(this.JSON_TAG.substring(i, this.currentPosition - 1));
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (c0 == '"') {
|
||||
return stringbuilder == null ? this.JSON_TAG.substring(i, this.currentPosition - 1) : stringbuilder.toString();
|
||||
}
|
||||
}
|
||||
|
||||
if (stringbuilder != null) {
|
||||
stringbuilder.append(c0);
|
||||
}
|
||||
}
|
||||
|
||||
throw this.makeError("Missing termination quote");
|
||||
}
|
||||
|
||||
private String readUnquotedString() {
|
||||
int i = this.currentPosition;
|
||||
|
||||
while (this.canRead() && this.isAllowedInUnquotedString(this.peek())) {
|
||||
this.currentPosition++;
|
||||
}
|
||||
|
||||
return this.JSON_TAG.substring(i, this.currentPosition);
|
||||
}
|
||||
|
||||
private Tag parseTag() throws NBTException {
|
||||
this.skipWhitespace();
|
||||
|
||||
if (!this.canRead()) {
|
||||
throw this.makeError("Expected value");
|
||||
} else {
|
||||
char c0 = this.peek();
|
||||
|
||||
if (c0 == '{') {
|
||||
return this.parseCompound();
|
||||
} else {
|
||||
return c0 == '[' ? this.parseTagArray() : this.parseTagPrimitive();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Tag parseTagArray() throws NBTException {
|
||||
return this.canRead(2) && this.peek(1) != '"' && this.peek(2) == ';' ? this.parseTagPrimitiveArray() : this.parseListTag();
|
||||
}
|
||||
|
||||
private CompoundTag parseCompound() throws NBTException {
|
||||
this.expect('{');
|
||||
CompoundTag nbttagcompound = new CompoundTag();
|
||||
this.skipWhitespace();
|
||||
|
||||
while (this.canRead() && this.peek() != '}') {
|
||||
String key = this.readString();
|
||||
|
||||
if (key.isEmpty()) {
|
||||
throw this.makeError("Expected non-empty key");
|
||||
}
|
||||
|
||||
this.expect(':');
|
||||
Tag tag = this.parseTag();
|
||||
nbttagcompound.put(key, tag);
|
||||
|
||||
if (!this.readComma()) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (!this.canRead()) {
|
||||
throw this.makeError("Expected key");
|
||||
}
|
||||
}
|
||||
|
||||
this.expect('}');
|
||||
return nbttagcompound;
|
||||
}
|
||||
|
||||
private Tag parseListTag() throws NBTException {
|
||||
this.expect('[');
|
||||
this.skipWhitespace();
|
||||
|
||||
if (!this.canRead()) {
|
||||
throw this.makeError("Expected value");
|
||||
} else {
|
||||
ListTag nbttaglist = new ListTag();
|
||||
int i = -1;
|
||||
|
||||
while (this.peek() != ']') {
|
||||
Tag nbtbase = this.parseTag();
|
||||
int j = TagRegistry.getIdFor(nbtbase.getClass());
|
||||
|
||||
if (i < 0) {
|
||||
i = j;
|
||||
} else if (j != i) {
|
||||
throw this.makeError("Unable to insert " + TagRegistry.getClassFor(j).getSimpleName() + " into ListTag of type " + TagRegistry.getClassFor(i).getSimpleName());
|
||||
}
|
||||
|
||||
nbttaglist.add(nbtbase);
|
||||
|
||||
if (!this.readComma()) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (!this.canRead()) {
|
||||
throw this.makeError("Expected value");
|
||||
}
|
||||
}
|
||||
|
||||
this.expect(']');
|
||||
return nbttaglist;
|
||||
}
|
||||
}
|
||||
|
||||
private Tag parseTagPrimitiveArray() throws NBTException {
|
||||
this.expect('[');
|
||||
char c0 = this.read();
|
||||
this.read();
|
||||
this.skipWhitespace();
|
||||
|
||||
if (!this.canRead()) {
|
||||
throw this.makeError("Expected value");
|
||||
} else if (c0 == 'B') {
|
||||
return new ByteArrayTag(toByteArray(this.readArray((byte) 7, (byte) 1)));
|
||||
} else if (c0 == 'L') {
|
||||
return new LongArrayTag(toLongArray(this.readArray((byte) 12, (byte) 4)));
|
||||
} else if (c0 == 'I') {
|
||||
return new IntArrayTag(toIntArray(this.readArray((byte) 11, (byte) 3)));
|
||||
} else {
|
||||
throw this.makeError("Invalid array type '" + c0 + "' found");
|
||||
}
|
||||
}
|
||||
|
||||
private static byte[] toByteArray(List<Byte> list) {
|
||||
byte[] bs = new byte[list.size()];
|
||||
|
||||
for (int i = 0; i < list.size(); ++i) {
|
||||
Byte byte_ = list.get(i);
|
||||
bs[i] = byte_ == null ? 0 : byte_;
|
||||
}
|
||||
|
||||
return bs;
|
||||
}
|
||||
|
||||
private static long[] toLongArray(List<Long> list) {
|
||||
long[] ls = new long[list.size()];
|
||||
|
||||
for (int i = 0; i < list.size(); ++i) {
|
||||
Long long_ = list.get(i);
|
||||
ls[i] = long_ == null ? 0L : long_;
|
||||
}
|
||||
|
||||
return ls;
|
||||
}
|
||||
|
||||
private static int[] toIntArray(List<Integer> list) {
|
||||
int[] is = new int[list.size()];
|
||||
|
||||
for (int i = 0; i < list.size(); ++i) {
|
||||
Integer integer = list.get(i);
|
||||
is[i] = integer == null ? 0 : integer;
|
||||
}
|
||||
|
||||
return is;
|
||||
}
|
||||
|
||||
private <T extends Number> List<T> readArray(byte b, byte c) throws NBTException {
|
||||
List<T> list = new ArrayList<>();
|
||||
|
||||
while (true) {
|
||||
if (this.peek() != ']') {
|
||||
Tag nbtbase = this.parseTag();
|
||||
int i = TagRegistry.getIdFor(nbtbase.getClass());
|
||||
|
||||
if (i != c) {
|
||||
throw this.makeError("Unable to insert " + TagRegistry.getClassFor(i).getSimpleName() + " into " + TagRegistry.getClassFor(b).getSimpleName());
|
||||
}
|
||||
|
||||
if (c == 1) {
|
||||
list.add((T) ((ByteTag) nbtbase).getValue());
|
||||
} else if (c == 4) {
|
||||
list.add((T) ((LongTag) nbtbase).getValue());
|
||||
} else {
|
||||
list.add((T) ((IntTag) nbtbase).getValue());
|
||||
}
|
||||
|
||||
if (this.readComma()) {
|
||||
if (!this.canRead()) {
|
||||
throw this.makeError("Expected value");
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
this.expect(']');
|
||||
return list;
|
||||
}
|
||||
}
|
||||
|
||||
private void skipWhitespace() {
|
||||
while (this.canRead() && Character.isWhitespace(this.peek())) {
|
||||
++this.currentPosition;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean readComma() {
|
||||
this.skipWhitespace();
|
||||
|
||||
if (this.canRead() && this.peek() == ',') {
|
||||
++this.currentPosition;
|
||||
this.skipWhitespace();
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private void expect(char expectedChar) throws NBTException {
|
||||
this.skipWhitespace();
|
||||
boolean flag = this.canRead();
|
||||
|
||||
if (flag && this.peek() == expectedChar) {
|
||||
++this.currentPosition;
|
||||
} else {
|
||||
throw new NBTException("Expected '" + expectedChar + "' but got '" + (flag ? this.peek() : "<EOF>") + "'", this.JSON_TAG, this.currentPosition + 1);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isAllowedInUnquotedString(char c) {
|
||||
return c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c >= 'a' && c <= 'z' || c == '_' || c == '-' || c == '.' || c == '+';
|
||||
}
|
||||
|
||||
private boolean canRead(int offset) {
|
||||
return this.currentPosition + offset < this.JSON_TAG.length();
|
||||
}
|
||||
|
||||
private boolean canRead() {
|
||||
return this.canRead(0);
|
||||
}
|
||||
|
||||
private char peek(int offset) {
|
||||
return this.JSON_TAG.charAt(this.currentPosition + offset);
|
||||
}
|
||||
|
||||
private char peek() {
|
||||
return this.peek(0);
|
||||
}
|
||||
|
||||
private char read() {
|
||||
return this.JSON_TAG.charAt(this.currentPosition++);
|
||||
}
|
||||
|
||||
public static final class NBTException extends Exception {
|
||||
public NBTException(String message, String jsonTag, int position) {
|
||||
super(message + " at: " + generate(jsonTag, position));
|
||||
}
|
||||
|
||||
private static String generate(String jsonTag, int position) {
|
||||
StringBuilder stringbuilder = new StringBuilder();
|
||||
int i = Math.min(jsonTag.length(), position);
|
||||
|
||||
if (i > 35) {
|
||||
stringbuilder.append("...");
|
||||
}
|
||||
|
||||
stringbuilder.append(jsonTag, Math.max(0, i - 35), i);
|
||||
stringbuilder.append("<--[HERE]");
|
||||
return stringbuilder.toString();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue
Block a user