Allow specifying nbt in block pattern

This commit is contained in:
Jesse Boyd 2017-01-09 04:34:31 +11:00
parent 22c89ce33a
commit ea637dbbfd
No known key found for this signature in database
GPG Key ID: 59F1DE6293AF6E1F
4 changed files with 467 additions and 8 deletions

View File

@ -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);

View 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;
}
}

View 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;
}
}

View File

@ -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: