9
0
mirror of https://github.com/Xiao-MoMi/craft-engine.git synced 2025-12-19 15:09:15 +00:00

支持 Byte, Int, Long 的数组解析.

This commit is contained in:
Catnies
2025-06-26 07:21:02 +08:00
parent 85db623bf2
commit 16d4198d41

View File

@@ -16,6 +16,11 @@ public final class SNBTReader extends DefaultStringReader {
private static final char KEY_VALUE_SEPARATOR = ':';
private static final char ELEMENT_SEPARATOR = ',';
private static final char ARRAY_DELIMITER = ';';
private static final char BYTE_ARRAY = 'b';
private static final char INT_ARRAY = 'i';
private static final char LONG_ARRAY = 'l';
// 数字类型后缀
private static final char BYTE_SUFFIX = 'b';
private static final char SHORT_SUFFIX = 's';
@@ -81,9 +86,31 @@ public final class SNBTReader extends DefaultStringReader {
}
// 解析列表值 [1, 2, 3]
private List<Object> parseList() {
private Object parseList() {
skip(); // 跳过 '['
skipWhitespace();
// 检查接下来的2个非空格字符, 确认是否要走数组解析.
if (canRead()) {
setMarker(cursor); // 记录指针, 尝试解析数组.
char typeChar = peek();
if (typeChar < 'a') typeChar = (char) (typeChar + 32); // 强制转小写进行匹配.
if (typeChar == BYTE_ARRAY || typeChar == INT_ARRAY || typeChar == LONG_ARRAY) {
skip();
skipWhitespace();
if (canRead() && peek() == ARRAY_DELIMITER) { // 下一个必须是 ';'
skip();
return switch (typeChar){ // 解析并返回数组喵
case BYTE_ARRAY -> parseArray(Byte.class);
case INT_ARRAY -> parseArray(Integer.class);
case LONG_ARRAY -> parseArray(Long.class);
default -> throw new IllegalArgumentException("Unknown typed-array prefix: " + typeChar);
};
}
}
restore(); // 复原指针.
}
List<Object> elementList = new ArrayList<>();
if (canRead() && peek() != LIST_END) {
@@ -100,6 +127,55 @@ public final class SNBTReader extends DefaultStringReader {
return elementList;
}
// 解析数组 [I; 11, 41, 54]
// ArrayType -> B, I, L.
private Object parseArray(Class<?> arrayType) {
skipWhitespace();
// 用来暂存解析出的数字
List<Number> elements = new ArrayList<>();
if (canRead() && peek() != LIST_END) {
do {
Object element = parseValue();
// 1.21.6的SNBT原版是支持 {key:[B;1,2b,0xFF]} 这种奇葩写法的, 越界部分会被自动舍弃, 如0xff的byte值为-1.
// 如果需要和原版对齐, 那么只需要判断是否是数字就行了.
// if (!(element instanceof Number number))
// throw new IllegalArgumentException("Error element type at pos " + getCursor());
if (!arrayType.isInstance(element))
throw new IllegalArgumentException("Error element type at pos " + getCursor());
elements.add((Number) element); // 校验通过后加入
skipWhitespace();
} while (canRead() && peek() == ELEMENT_SEPARATOR && ++cursor > 0 /* 跳过 ',' */);
}
if (!canRead() || peek() != LIST_END)
throw new IllegalArgumentException("Expected ']' at position " + getCursor());
skip(); // 跳过 ']'
// 根据数组类型创建并返回对应的数组
// 构造并返回真正的 Java 数组
return switch (arrayType.getSimpleName()) {
case "Byte" -> {
byte[] arr = new byte[elements.size()];
for (int i = 0; i < arr.length; i++) arr[i] = elements.get(i).byteValue();
yield arr;
}
case "Integer" -> {
int[] arr = new int[elements.size()];
for (int i = 0; i < arr.length; i++) arr[i] = elements.get(i).intValue();
yield arr;
}
case "Long" -> {
long[] arr = new long[elements.size()];
for (int i = 0; i < arr.length; i++) arr[i] = elements.get(i).longValue();
yield arr;
}
default -> throw new IllegalArgumentException("Unknown typed-array prefix: " + getCursor());
};
}
// 解析Key值
private String parseKey() {
skipWhitespace();