diff --git a/src/main/java/carpet/script/value/NBTSerializableValue.java b/src/main/java/carpet/script/value/NBTSerializableValue.java index b4ce70b5..b6d9e6fc 100644 --- a/src/main/java/carpet/script/value/NBTSerializableValue.java +++ b/src/main/java/carpet/script/value/NBTSerializableValue.java @@ -33,6 +33,7 @@ import net.minecraft.util.Identifier; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Box; +import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.List; @@ -48,6 +49,7 @@ public class NBTSerializableValue extends Value implements ContainerValueInterfa private String nbtString = null; private Tag nbtTag = null; private Supplier nbtSupplier = null; + private boolean owned = false; private NBTSerializableValue() {} @@ -64,11 +66,18 @@ public class NBTSerializableValue extends Value implements ContainerValueInterfa throw new InternalExpressionException("Incorrect NBT data: "+nbtString); } }; + owned = true; } public NBTSerializableValue(Tag tag) { nbtTag = tag; + owned = true; + } + + public NBTSerializableValue(Supplier tagSupplier) + { + nbtSupplier = tagSupplier; } public static Value fromStack(ItemStack stack) @@ -115,6 +124,7 @@ public class NBTSerializableValue extends Value implements ContainerValueInterfa NBTSerializableValue copy = new NBTSerializableValue(nbtTag); copy.nbtSupplier = this.nbtSupplier; copy.nbtString = this.nbtString; + copy.owned = this.owned; return copy; } @@ -122,9 +132,8 @@ public class NBTSerializableValue extends Value implements ContainerValueInterfa public Value deepcopy() { NBTSerializableValue copy = (NBTSerializableValue) clone(); - // same fields except when tag is set - need to copy it. - if (copy.nbtTag != null) - copy.nbtTag = copy.getTag().copy(); + copy.owned = false; + ensureOwnership(); return copy; } @@ -290,7 +299,53 @@ public class NBTSerializableValue extends Value implements ContainerValueInterfa private static Value decodeTag(Tag t) { if (t instanceof CompoundTag) - return new NBTSerializableValue(t); + return new NBTSerializableValue(() -> t); + if (t instanceof AbstractNumberTag) + return new NumericValue(((AbstractNumberTag) t).getDouble()); + // more can be done here + return new StringValue(t.asString()); + } + + public Value toValue() + { + return decodeTagDeep(this.getTag()); + } + + public static Value fromValue(Value v) + { + if (v instanceof NBTSerializableValue) + return v; + if (v instanceof NullValue) + return Value.NULL; + Value ret = NBTSerializableValue.parseString(v.getString()); + if (ret == null) + return Value.NULL; + return ret; + } + + + private static Value decodeTagDeep(Tag t) + { + if (t instanceof CompoundTag) + { + Map pairs = new HashMap<>(); + CompoundTag ctag = (CompoundTag)t; + for (String key: ctag.getKeys()) + { + pairs.put(new StringValue(key), decodeTagDeep(ctag.get(key))); + } + return MapValue.wrap(pairs); + } + if (t instanceof AbstractListTag) + { + List elems = new ArrayList<>(); + AbstractListTag ltag = (AbstractListTag)t; + for (Tag elem: ltag) + { + elems.add(decodeTagDeep(elem)); + } + return ListValue.wrap(elems); + } if (t instanceof AbstractNumberTag) return new NumericValue(((AbstractNumberTag) t).getDouble()); // more can be done here @@ -304,13 +359,6 @@ public class NBTSerializableValue extends Value implements ContainerValueInterfa return nbtTag; } - private void replaceTag(Tag newTag) - { - nbtTag = newTag; - nbtString = null; - nbtSupplier = null; // just to be sure - } - @Override public boolean equals(final Object o) { @@ -346,6 +394,7 @@ public class NBTSerializableValue extends Value implements ContainerValueInterfa { try { + ensureOwnership(); return (CompoundTag) getTag(); } catch (ClassCastException e) @@ -364,12 +413,12 @@ public class NBTSerializableValue extends Value implements ContainerValueInterfa public boolean put(Value where, Value value, Value conditions) { /// WIP - + ensureOwnership(); NbtPathArgumentType.NbtPath path = cachePath(where.getString()); Tag tagToInsert = value instanceof NBTSerializableValue ? ((NBTSerializableValue) value).getTag() : new NBTSerializableValue(value.getString()).getTag(); - Tag modifiedTag; + boolean modifiedTag; if (conditions instanceof NumericValue) { modifiedTag = modify_insert((int)((NumericValue) conditions).getLong(), path, tagToInsert); @@ -390,22 +439,17 @@ public class NBTSerializableValue extends Value implements ContainerValueInterfa return false; } } - if (modifiedTag != null) - { - replaceTag(modifiedTag); - return true; - } - return false; + return modifiedTag; } - private Tag modify_insert(int index, NbtPathArgumentType.NbtPath nbtPath, Tag newElement) + private boolean modify_insert(int index, NbtPathArgumentType.NbtPath nbtPath, Tag newElement) { - return modify_insert(index, nbtPath, newElement, this.getTag().copy()); + return modify_insert(index, nbtPath, newElement, this.getTag()); } - private Tag modify_insert(int index, NbtPathArgumentType.NbtPath nbtPath, Tag newElement, Tag currentTag) + private boolean modify_insert(int index, NbtPathArgumentType.NbtPath nbtPath, Tag newElement, Tag currentTag) { Collection targets; try @@ -414,7 +458,7 @@ public class NBTSerializableValue extends Value implements ContainerValueInterfa } catch (CommandSyntaxException e) { - return null; + return false; } boolean modified = false; @@ -428,27 +472,27 @@ public class NBTSerializableValue extends Value implements ContainerValueInterfa { AbstractListTag targetList = (AbstractListTag) target; if (!targetList.addTag(index < 0 ? targetList.size() + index + 1 : index, newElement.copy())) - return null; + return false; modified = true; } catch (IndexOutOfBoundsException ignored) { } } - return modified?currentTag:null; + return modified; } - private Tag modify_merge(NbtPathArgumentType.NbtPath nbtPath, Tag replacement) //nbtPathArgumentType$NbtPath_1, list_1) + private boolean modify_merge(NbtPathArgumentType.NbtPath nbtPath, Tag replacement) //nbtPathArgumentType$NbtPath_1, list_1) { if (!(replacement instanceof CompoundTag)) { - return getTag(); + return false; } - Tag originalTag = getTag().copy(); + Tag ownTag = getTag(); try { - for (Tag target : nbtPath.getOrInit(originalTag, CompoundTag::new)) + for (Tag target : nbtPath.getOrInit(ownTag, CompoundTag::new)) { if (!(target instanceof CompoundTag)) { @@ -457,23 +501,26 @@ public class NBTSerializableValue extends Value implements ContainerValueInterfa ((CompoundTag) target).copyFrom((CompoundTag) replacement); } } - catch (CommandSyntaxException ignored) { } - return originalTag; + catch (CommandSyntaxException ignored) + { + return false; + } + return true; } - private Tag modify_replace(NbtPathArgumentType.NbtPath nbtPath, Tag replacement) //nbtPathArgumentType$NbtPath_1, list_1) + private boolean modify_replace(NbtPathArgumentType.NbtPath nbtPath, Tag replacement) //nbtPathArgumentType$NbtPath_1, list_1) { - Tag originalTag = getTag().copy(); + Tag tag = getTag(); String pathText = nbtPath.toString(); if (pathText.endsWith("]")) // workaround for array replacement or item in the array replacement { - if (nbtPath.remove(originalTag)==0) - return null; + if (nbtPath.remove(tag)==0) + return false; Pattern pattern = Pattern.compile("\\[[^\\[]*]$"); Matcher matcher = pattern.matcher(pathText); if (!matcher.find()) // malformed path { - return null; + return false; } String arrAccess = matcher.group(); int pos; @@ -487,21 +534,21 @@ public class NBTSerializableValue extends Value implements ContainerValueInterfa } catch (NumberFormatException e) { - return null; + return false; } } NbtPathArgumentType.NbtPath newPath = cachePath(pathText.substring(0, pathText.length()-arrAccess.length())); - return modify_insert(pos,newPath,replacement, originalTag); + return modify_insert(pos,newPath,replacement, tag); } try { - nbtPath.put(originalTag, () -> replacement); + nbtPath.put(tag, () -> replacement); } catch (CommandSyntaxException e) { - return null; + return false; } - return originalTag; + return true; } @Override @@ -527,13 +574,23 @@ public class NBTSerializableValue extends Value implements ContainerValueInterfa return cachePath(where.getString()).count(getTag()) > 0; } + private void ensureOwnership() + { + if (!owned) + { + nbtTag = getTag().copy(); + nbtString = null; + nbtSupplier = null; // just to be sure + owned = true; + } + } + @Override public boolean delete(Value where) { NbtPathArgumentType.NbtPath path = cachePath(where.getString()); - Tag tag = getTag().copy(); - int removed = path.remove(tag); - if (removed > 0) replaceTag(tag); + ensureOwnership(); + int removed = path.remove(getTag()); return removed > 0; }