Allow specifying nbt in block pattern
This commit is contained in:
parent
22c89ce33a
commit
ea637dbbfd
@ -17,12 +17,15 @@ public abstract class FaweParser<T> extends InputParser<T> {
|
||||
public List<String> split(String input, char delim) {
|
||||
List<String> result = new ArrayList<String>();
|
||||
int start = 0;
|
||||
int bracket = 0;
|
||||
boolean inQuotes = false;
|
||||
for (int current = 0; current < input.length(); current++) {
|
||||
if (input.charAt(current) == '\"') inQuotes = !inQuotes; // toggle state
|
||||
char currentChar = input.charAt(current);
|
||||
boolean atLastChar = (current == input.length() - 1);
|
||||
if (!atLastChar && (bracket > 0 || (currentChar == '{' && ++bracket > 0) || (current == '}' && --bracket <= 0))) continue;
|
||||
if (currentChar == '\"') inQuotes = !inQuotes; // toggle state
|
||||
if(atLastChar) result.add(input.substring(start));
|
||||
else if (input.charAt(current) == delim && !inQuotes) {
|
||||
else if (currentChar == delim && !inQuotes) {
|
||||
String toAdd = input.substring(start, current);
|
||||
if (toAdd.startsWith("\"")) {
|
||||
toAdd = toAdd.substring(1, toAdd.length() - 1);
|
||||
|
429
core/src/main/java/com/boydti/fawe/jnbt/JSON2NBT.java
Normal file
429
core/src/main/java/com/boydti/fawe/jnbt/JSON2NBT.java
Normal file
@ -0,0 +1,429 @@
|
||||
package com.boydti.fawe.jnbt;
|
||||
|
||||
import com.google.common.base.Splitter;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.sk89q.jnbt.ByteTag;
|
||||
import com.sk89q.jnbt.CompoundTag;
|
||||
import com.sk89q.jnbt.DoubleTag;
|
||||
import com.sk89q.jnbt.FloatTag;
|
||||
import com.sk89q.jnbt.IntArrayTag;
|
||||
import com.sk89q.jnbt.IntTag;
|
||||
import com.sk89q.jnbt.ListTag;
|
||||
import com.sk89q.jnbt.LongTag;
|
||||
import com.sk89q.jnbt.ShortTag;
|
||||
import com.sk89q.jnbt.StringTag;
|
||||
import com.sk89q.jnbt.Tag;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.Stack;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public class JSON2NBT {
|
||||
private static final Pattern INT_ARRAY_MATCHER = Pattern.compile("\\[[-+\\d|,\\s]+\\]");
|
||||
|
||||
private JSON2NBT() {
|
||||
}
|
||||
|
||||
public static CompoundTag getTagFromJson(String jsonString) throws NBTException {
|
||||
jsonString = jsonString.trim();
|
||||
if(!jsonString.startsWith("{")) {
|
||||
throw new NBTException("Invalid tag encountered, expected \'{\' as first char.");
|
||||
} else if(topTagsCount(jsonString) != 1) {
|
||||
throw new NBTException("Encountered multiple top tags, only one expected");
|
||||
} else {
|
||||
return (CompoundTag)nameValueToNBT("tag", jsonString).parse();
|
||||
}
|
||||
}
|
||||
|
||||
public static int topTagsCount(String str) throws NBTException {
|
||||
int i = 0;
|
||||
boolean flag = false;
|
||||
Stack 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 NBTException("Illegal use of \\\": " + str);
|
||||
}
|
||||
} else {
|
||||
flag = !flag;
|
||||
}
|
||||
} else if(!flag) {
|
||||
if(c0 != 123 && c0 != 91) {
|
||||
if(c0 == 125 && (stack.isEmpty() || ((Character)stack.pop()).charValue() != 123)) {
|
||||
throw new NBTException("Unbalanced curly brackets {}: " + str);
|
||||
}
|
||||
|
||||
if(c0 == 93 && (stack.isEmpty() || ((Character)stack.pop()).charValue() != 91)) {
|
||||
throw new NBTException("Unbalanced square brackets []: " + str);
|
||||
}
|
||||
} else {
|
||||
if(stack.isEmpty()) {
|
||||
++i;
|
||||
}
|
||||
|
||||
stack.push(Character.valueOf(c0));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(flag) {
|
||||
throw new NBTException("Unbalanced quotation: " + str);
|
||||
} else if(!stack.isEmpty()) {
|
||||
throw new NBTException("Unbalanced brackets: " + str);
|
||||
} else {
|
||||
if(i == 0 && !str.isEmpty()) {
|
||||
i = 1;
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
private static JSON2NBT.Any joinStrToNBT(String... args) throws NBTException {
|
||||
return nameValueToNBT(args[0], args[1]);
|
||||
}
|
||||
|
||||
private static JSON2NBT.Any nameValueToNBT(String key, String value) throws NBTException {
|
||||
value = value.trim();
|
||||
String s;
|
||||
boolean c0;
|
||||
char c01;
|
||||
if(value.startsWith("{")) {
|
||||
value = value.substring(1, value.length() - 1);
|
||||
|
||||
JSON2NBT.Compound JSON2NBT$list1;
|
||||
for(JSON2NBT$list1 = new JSON2NBT.Compound(key); value.length() > 0; value = value.substring(s.length() + 1)) {
|
||||
s = nextNameValuePair(value, true);
|
||||
if(s.length() > 0) {
|
||||
c0 = false;
|
||||
JSON2NBT$list1.tagList.add(getTagFromNameValue(s, false));
|
||||
}
|
||||
|
||||
if(value.length() < s.length() + 1) {
|
||||
break;
|
||||
}
|
||||
|
||||
c01 = value.charAt(s.length());
|
||||
if(c01 != 44 && c01 != 123 && c01 != 125 && c01 != 91 && c01 != 93) {
|
||||
throw new NBTException("Unexpected token \'" + c01 + "\' at: " + value.substring(s.length()));
|
||||
}
|
||||
}
|
||||
|
||||
return JSON2NBT$list1;
|
||||
} else if(value.startsWith("[") && !INT_ARRAY_MATCHER.matcher(value).matches()) {
|
||||
value = value.substring(1, value.length() - 1);
|
||||
|
||||
JSON2NBT.List JSON2NBT$list;
|
||||
for(JSON2NBT$list = new JSON2NBT.List(key); value.length() > 0; value = value.substring(s.length() + 1)) {
|
||||
s = nextNameValuePair(value, false);
|
||||
if(s.length() > 0) {
|
||||
c0 = true;
|
||||
JSON2NBT$list.tagList.add(getTagFromNameValue(s, true));
|
||||
}
|
||||
|
||||
if(value.length() < s.length() + 1) {
|
||||
break;
|
||||
}
|
||||
|
||||
c01 = value.charAt(s.length());
|
||||
if(c01 != 44 && c01 != 123 && c01 != 125 && c01 != 91 && c01 != 93) {
|
||||
throw new NBTException("Unexpected token \'" + c01 + "\' at: " + value.substring(s.length()));
|
||||
}
|
||||
}
|
||||
|
||||
return JSON2NBT$list;
|
||||
} else {
|
||||
return new JSON2NBT.Primitive(key, value);
|
||||
}
|
||||
}
|
||||
|
||||
private static JSON2NBT.Any getTagFromNameValue(String str, boolean isArray) throws NBTException {
|
||||
String s = locateName(str, isArray);
|
||||
String s1 = locateValue(str, isArray);
|
||||
return joinStrToNBT(new String[]{s, s1});
|
||||
}
|
||||
|
||||
private static String nextNameValuePair(String str, boolean isCompound) throws NBTException {
|
||||
int i = getNextCharIndex(str, ':');
|
||||
int j = getNextCharIndex(str, ',');
|
||||
if(isCompound) {
|
||||
if(i == -1) {
|
||||
throw new NBTException("Unable to locate name/value separator for string: " + str);
|
||||
}
|
||||
|
||||
if(j != -1 && j < i) {
|
||||
throw new NBTException("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 NBTException {
|
||||
Stack 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 NBTException("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() || ((Character)stack.pop()).charValue() != 123)) {
|
||||
throw new NBTException("Unbalanced curly brackets {}: " + str);
|
||||
}
|
||||
|
||||
if(c0 == 93 && (stack.isEmpty() || ((Character)stack.pop()).charValue() != 91)) {
|
||||
throw new NBTException("Unbalanced square brackets []: " + str);
|
||||
}
|
||||
|
||||
if(c0 == 44 && stack.isEmpty()) {
|
||||
return str.substring(0, i);
|
||||
}
|
||||
} else {
|
||||
stack.push(Character.valueOf(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 NBTException {
|
||||
if(isArray) {
|
||||
str = str.trim();
|
||||
if(str.startsWith("{") || str.startsWith("[")) {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
int i = getNextCharIndex(str, ':');
|
||||
if(i == -1) {
|
||||
if(isArray) {
|
||||
return "";
|
||||
} else {
|
||||
throw new NBTException("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 NBTException {
|
||||
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 NBTException("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);
|
||||
}
|
||||
|
||||
private static class Primitive extends JSON2NBT.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 NBTException {
|
||||
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 var7 = this.jsonValue.substring(1, this.jsonValue.length() - 1);
|
||||
String[] var8 = (String[])((String[]) Iterables.toArray(SPLITTER.split(var7), String.class));
|
||||
|
||||
try {
|
||||
int[] var5 = new int[var8.length];
|
||||
|
||||
for(int j = 0; j < var8.length; ++j) {
|
||||
var5[j] = Integer.parseInt(var8[j].trim());
|
||||
}
|
||||
|
||||
return new IntArrayTag(var5);
|
||||
} catch (NumberFormatException var51) {
|
||||
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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static class List extends JSON2NBT.Any {
|
||||
protected java.util.List<JSON2NBT.Any> tagList = Lists.newArrayList();
|
||||
|
||||
public List(String json) {
|
||||
this.json = json;
|
||||
}
|
||||
|
||||
public Tag parse() throws NBTException {
|
||||
ArrayList<Tag> list = new ArrayList<>();
|
||||
Iterator var2 = this.tagList.iterator();
|
||||
|
||||
while(var2.hasNext()) {
|
||||
JSON2NBT.Any JSON2NBT$any = (JSON2NBT.Any)var2.next();
|
||||
list.add(JSON2NBT$any.parse());
|
||||
}
|
||||
Class<? extends Tag> tagType = list.isEmpty() ? CompoundTag.class : list.get(0).getClass();
|
||||
return new ListTag(tagType, list);
|
||||
}
|
||||
}
|
||||
|
||||
private static class Compound extends JSON2NBT.Any {
|
||||
protected java.util.List<JSON2NBT.Any> tagList = Lists.newArrayList();
|
||||
|
||||
public Compound(String jsonIn) {
|
||||
this.json = jsonIn;
|
||||
}
|
||||
|
||||
public Tag parse() throws NBTException {
|
||||
HashMap<String, Tag> map = new HashMap<String, Tag>();
|
||||
Iterator var2 = this.tagList.iterator();
|
||||
|
||||
while(var2.hasNext()) {
|
||||
JSON2NBT.Any JSON2NBT$any = (JSON2NBT.Any)var2.next();
|
||||
map.put(JSON2NBT$any.json, JSON2NBT$any.parse());
|
||||
}
|
||||
|
||||
return new CompoundTag(map);
|
||||
}
|
||||
}
|
||||
|
||||
private abstract static class Any {
|
||||
protected String json;
|
||||
|
||||
Any() {
|
||||
}
|
||||
|
||||
public abstract Tag parse() throws NBTException;
|
||||
}
|
||||
}
|
15
core/src/main/java/com/boydti/fawe/jnbt/NBTException.java
Normal file
15
core/src/main/java/com/boydti/fawe/jnbt/NBTException.java
Normal file
@ -0,0 +1,15 @@
|
||||
package com.boydti.fawe.jnbt;
|
||||
|
||||
public class NBTException extends RuntimeException{
|
||||
public NBTException(String message) {
|
||||
super(message);
|
||||
}
|
||||
/**
|
||||
* Faster exception throwing if you don't fill the stacktrace
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public Throwable fillInStackTrace() {
|
||||
return this;
|
||||
}
|
||||
}
|
@ -19,7 +19,10 @@
|
||||
|
||||
package com.sk89q.worldedit.extension.factory;
|
||||
|
||||
import com.boydti.fawe.jnbt.JSON2NBT;
|
||||
import com.boydti.fawe.jnbt.NBTException;
|
||||
import com.boydti.fawe.util.MathMan;
|
||||
import com.intellectualcrafters.plot.util.StringMan;
|
||||
import com.sk89q.jnbt.CompoundTag;
|
||||
import com.sk89q.jnbt.Tag;
|
||||
import com.sk89q.worldedit.BlockVector;
|
||||
@ -44,6 +47,7 @@ import com.sk89q.worldedit.extension.platform.Actor;
|
||||
import com.sk89q.worldedit.internal.registry.InputParser;
|
||||
import com.sk89q.worldedit.world.World;
|
||||
import com.sk89q.worldedit.world.registry.BundledBlockData;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@ -77,8 +81,8 @@ public class DefaultBlockParser extends InputParser<BaseBlock> {
|
||||
// BlockType, as well as to properly handle mod:name IDs
|
||||
|
||||
String originalInput = input;
|
||||
input = input.replace("_", " ");
|
||||
input = input.replace(";", "|");
|
||||
// input = input.replace("_", " ");
|
||||
// input = input.replace(";", "|");
|
||||
Exception suppressed = null;
|
||||
try {
|
||||
BaseBlock modified = parseLogic(input, context);
|
||||
@ -222,17 +226,13 @@ public class DefaultBlockParser extends InputParser<BaseBlock> {
|
||||
for (Map.Entry<String, BundledBlockData.FaweState> stateEntry : block.states.entrySet()) {
|
||||
for (Map.Entry<String, BundledBlockData.FaweStateValue> valueEntry : stateEntry.getValue().valueMap().entrySet()) {
|
||||
String key = valueEntry.getKey();
|
||||
System.out.println("Key " + key + " " + typeAndData[1]);
|
||||
if (key.equalsIgnoreCase(typeAndData[1])) {
|
||||
data = valueEntry.getValue().data;
|
||||
System.out.println("Foudn! " + data);
|
||||
break loop;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
} else {
|
||||
System.out.println("No states found for " + blockId);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -317,6 +317,18 @@ public class DefaultBlockParser extends InputParser<BaseBlock> {
|
||||
return new BaseBlock(blockId, data);
|
||||
}
|
||||
|
||||
if (blockAndExtraData.length > 1 && blockAndExtraData[1].startsWith("{")) {
|
||||
String joined = StringMan.join(Arrays.copyOfRange(blockAndExtraData, 1, blockAndExtraData.length), "|");
|
||||
try {
|
||||
CompoundTag nbt = JSON2NBT.getTagFromJson(joined);
|
||||
if (nbt != null) {
|
||||
return new BaseBlock(blockId, data, nbt);
|
||||
}
|
||||
} catch (NBTException e) {
|
||||
throw new NoMatchException(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
switch (blockType) {
|
||||
case SIGN_POST:
|
||||
case WALL_SIGN:
|
||||
|
Loading…
Reference in New Issue
Block a user