From 83a8f350947e429a19a84a83e145b1b9a5aa650b Mon Sep 17 00:00:00 2001 From: gnembon Date: Sat, 29 Jun 2019 20:00:15 -0300 Subject: [PATCH] better inventory and nbt support. control flow statements default to nulls --- .../java/carpet/script/CarpetExpression.java | 61 +++++++++++++++++-- src/main/java/carpet/script/Expression.java | 12 ++-- .../java/carpet/script/value/BlockValue.java | 41 ++++++++++++- .../carpet/script/value/LazyListValue.java | 6 ++ .../java/carpet/script/value/ListValue.java | 34 +++++++---- .../script/value/NBTSerializableValue.java | 59 +++++++++++++++--- .../carpet/script/value/NumericValue.java | 2 +- 7 files changed, 182 insertions(+), 33 deletions(-) diff --git a/src/main/java/carpet/script/CarpetExpression.java b/src/main/java/carpet/script/CarpetExpression.java index 434430cb..e3b19e40 100644 --- a/src/main/java/carpet/script/CarpetExpression.java +++ b/src/main/java/carpet/script/CarpetExpression.java @@ -40,6 +40,7 @@ import net.minecraft.entity.player.PlayerEntity; import net.minecraft.item.BlockItem; import net.minecraft.item.ItemStack; import net.minecraft.item.Items; +import net.minecraft.nbt.CompoundTag; import net.minecraft.particle.ParticleEffect; import net.minecraft.predicate.entity.EntityPredicates; import net.minecraft.server.MinecraftServer; @@ -547,6 +548,20 @@ public class CarpetExpression return (c_, t_) -> retval; }); + this.expr.addLazyFunction("block_data", -1, (c, t, lv) -> + { + CarpetContext cc = (CarpetContext) c; + if (lv.size() == 0) + { + throw new InternalExpressionException("Block requires at least one parameter"); + } + CompoundTag tag = BlockValue.fromParams(cc, lv, 0, true).block.getData(); + if (tag.isEmpty()) + return (c_, t_) -> Value.NULL; + Value retval = new NBTSerializableValue(tag); + return (c_, t_) -> retval; + }); + this.expr.addLazyFunction("pos", 1, (c, t, lv) -> { Value arg = lv.get(0).evalValue(c); @@ -718,10 +733,29 @@ public class CarpetExpression sourceBlockState = setProperty(property, paramString, paramValue, sourceBlockState); } } - if (sourceBlockState == targetBlockState) + + CompoundTag data = sourceLocator.block.getData(); + + if (sourceBlockState == targetBlockState && data == null) return (c_, t_) -> Value.FALSE; CarpetSettings.impendingFillSkipUpdates = !CarpetSettings.fillUpdates; - cc.s.getWorld().setBlockState(targetLocator.block.getPos(), sourceBlockState, 2); + BlockPos targetPos = targetLocator.block.getPos(); + cc.s.getWorld().setBlockState(targetPos, sourceBlockState, 2); + + if ( data != null) + { + BlockEntity be = world.getBlockEntity(targetPos); + if (be != null) + { + CompoundTag destTag = data.method_10553(); + destTag.putInt("x", targetPos.getX()); + destTag.putInt("y", targetPos.getY()); + destTag.putInt("z", targetPos.getZ()); + be.fromTag(destTag); + be.markDirty(); + } + } + CarpetSettings.impendingFillSkipUpdates = false; Value retval = new BlockValue(sourceBlockState, world, targetLocator.block.getPos()); return (c_, t_) -> retval; @@ -873,6 +907,12 @@ public class CarpetExpression public void API_InventoryManipulation() { + this.expr.addLazyFunction("stack_limit", 1, (c, t, lv) -> { + ItemStackArgument item = NBTSerializableValue.parseItem(lv.get(0).evalValue(c).getString()); + Value res = new NumericValue(item.getItem().getMaxCount()); + return (_c, _t) -> res; + }); + this.expr.addLazyFunction("inventory_size", -1, (c, t, lv) -> { CarpetContext cc = (CarpetContext) c; NBTSerializableValue.InventoryLocator inventoryLocator = NBTSerializableValue.locateInventory(cc, lv, 0); @@ -990,7 +1030,7 @@ public class CarpetExpression return (_c, _t) -> Value.NULL; }); - //inventory_set(, , , ) + //inventory_set(, , , , ) this.expr.addLazyFunction("inventory_set", -1, (c, t, lv) -> { CarpetContext cc = (CarpetContext) c; NBTSerializableValue.InventoryLocator inventoryLocator = NBTSerializableValue.locateInventory(cc, lv, 0); @@ -1018,7 +1058,20 @@ public class CarpetExpression inventoryLocator.inventory.setInvStack(slot, newStack); return (_c, _t) -> ListValue.fromItemStack(previousStack); } - ItemStackArgument newitem = NBTSerializableValue.parseItem(lv.get(inventoryLocator.offset+2).evalValue(c).getString()); + CompoundTag nbt = null; + if (lv.size() >= inventoryLocator.offset+3) + { + Value nbtValue = lv.get(inventoryLocator.offset+3).evalValue(c); + if (nbtValue instanceof NBTSerializableValue) + nbt = ((NBTSerializableValue)nbtValue).getTag(); + else + nbt = new NBTSerializableValue(nbtValue.getString()).getTag(); + } + ItemStackArgument newitem = NBTSerializableValue.parseItem( + lv.get(inventoryLocator.offset+2).evalValue(c).getString(), + nbt + ); + ItemStack previousStack = inventoryLocator.inventory.getInvStack(slot); try { diff --git a/src/main/java/carpet/script/Expression.java b/src/main/java/carpet/script/Expression.java index 2eec66ac..5cb5c750 100644 --- a/src/main/java/carpet/script/Expression.java +++ b/src/main/java/carpet/script/Expression.java @@ -964,12 +964,14 @@ public class Expression implements Cloneable return (cc, tt) -> new StringValue("OK"); }); - addUnaryFunction("exit", (v) -> { throw new ExitStatement(v); }); - addUnaryFunction("return", (v) -> { throw new ReturnStatement(v); }); - addUnaryFunction("throw", (v)-> {throw new ThrowStatement(v); }); + addFunction("exit", (lv) -> { throw new ExitStatement(lv.size()==0?Value.NULL:lv.get(0)); }); + addFunction("return", (lv) -> { throw new ReturnStatement(lv.size()==0?Value.NULL:lv.get(0));} ); + addFunction("throw", (lv)-> {throw new ThrowStatement(lv.size()==0?Value.NULL:lv.get(0)); }); - addLazyFunction("try", 2, (c, t, lv) -> + addLazyFunction("try", -1, (c, t, lv) -> { + if (lv.size()==0) + throw new InternalExpressionException("try needs at least an expression block"); try { Value retval = lv.get(0).evalValue(c, t); @@ -977,6 +979,8 @@ public class Expression implements Cloneable } catch (ThrowStatement ret) { + if (lv.size() == 1) + return (c_, t_) -> Value.NULL; LazyValue __ = c.getVariable("_"); c.setVariable("_", (__c, __t) -> ret.retval.reboundedTo("_")); Value val = lv.get(1).evalValue(c, t); diff --git a/src/main/java/carpet/script/value/BlockValue.java b/src/main/java/carpet/script/value/BlockValue.java index 3ba7f719..2fa1dee6 100644 --- a/src/main/java/carpet/script/value/BlockValue.java +++ b/src/main/java/carpet/script/value/BlockValue.java @@ -6,10 +6,12 @@ import carpet.script.exception.InternalExpressionException; import com.mojang.brigadier.StringReader; import com.mojang.brigadier.exceptions.CommandSyntaxException; import net.minecraft.block.BlockState; +import net.minecraft.block.entity.BlockEntity; import net.minecraft.command.arguments.BlockArgumentParser; import net.minecraft.block.Blocks; import net.minecraft.item.ItemPlacementContext; import net.minecraft.item.ItemStack; +import net.minecraft.nbt.CompoundTag; import net.minecraft.util.Hand; import net.minecraft.util.hit.BlockHitResult; import net.minecraft.util.math.BlockPos; @@ -31,6 +33,7 @@ public class BlockValue extends Value private BlockState blockState; private BlockPos pos; private World world; + private CompoundTag data; public static BlockValue fromCoords(CarpetContext c, int x, int y, int z) { @@ -48,7 +51,10 @@ public class BlockValue extends Value BlockArgumentParser blockstateparser = (new BlockArgumentParser(new StringReader(str), false)).parse(true); if (blockstateparser.getBlockState() != null) { - bv = new BlockValue(blockstateparser.getBlockState(), null, null); + CompoundTag bd = blockstateparser.getNbtData(); + if (bd == null) + bd = new CompoundTag(); + bv = new BlockValue(blockstateparser.getBlockState(), null, null, bd ); if (bvCache.size()>10000) bvCache.clear(); bvCache.put(str, bv); @@ -182,11 +188,44 @@ public class BlockValue extends Value throw new InternalExpressionException("Attemted to fetch blockstate without world or stored blockstate"); } + public CompoundTag getData() + { + if (data != null) + { + if (data.isEmpty()) + return null; + return data; + } + if (world != null && pos != null) + { + BlockEntity be = world.getBlockEntity(pos); + CompoundTag tag = new CompoundTag(); + if (be == null) + { + data = tag; + return null; + } + data = be.toTag(tag); + return data; + } + throw new InternalExpressionException("Attemted to fetch block data without world or stored block data"); + } + + public BlockValue(BlockState state, World world, BlockPos position) { this.world = world; blockState = state; pos = position; + data = null; + } + + public BlockValue(BlockState state, World world, BlockPos position, CompoundTag nbt) + { + this.world = world; + blockState = state; + pos = position; + data = nbt; } diff --git a/src/main/java/carpet/script/value/LazyListValue.java b/src/main/java/carpet/script/value/LazyListValue.java index 2f1af01e..be416f18 100644 --- a/src/main/java/carpet/script/value/LazyListValue.java +++ b/src/main/java/carpet/script/value/LazyListValue.java @@ -100,4 +100,10 @@ public abstract class LazyListValue extends ListValue implements Iterator throw new InternalExpressionException("Cannot add to iterators"); } + @Override + public boolean equals(final Value o) + { + return false; + } + } diff --git a/src/main/java/carpet/script/value/ListValue.java b/src/main/java/carpet/script/value/ListValue.java index a8b20d72..fefb8a7f 100644 --- a/src/main/java/carpet/script/value/ListValue.java +++ b/src/main/java/carpet/script/value/ListValue.java @@ -203,25 +203,33 @@ public class ListValue extends Value ListValue ol = (ListValue)o; int this_size = this.getItems().size(); int o_size = ol.getItems().size(); - if (this_size != o_size) - { - return this_size - o_size; - } - if (this_size == 0) - { - return 0; - } + if (this_size != o_size) return this_size - o_size; + if (this_size == 0) return 0; for (int i = 0; i < this_size; i++) { int res = this.items.get(i).compareTo(ol.items.get(i)); - if (res != 0) - { - return res; - } + if (res != 0) return res; } return 0; } - return super.compareTo(o); + return getString().compareTo(o.getString()); + } + + @Override + public boolean equals(final Value o) + { + if (o instanceof ListValue) + { + ListValue ol = (ListValue)o; + int this_size = this.getItems().size(); + int o_size = ol.getItems().size(); + if (this_size != o_size) return false; + if (this_size == 0) return true; + for (int i = 0; i < this_size; i++) + if (!this.items.get(i).equals(ol.items.get(i))) return false; + return true; + } + return false; } public List getItems() diff --git a/src/main/java/carpet/script/value/NBTSerializableValue.java b/src/main/java/carpet/script/value/NBTSerializableValue.java index 282364be..2423539b 100644 --- a/src/main/java/carpet/script/value/NBTSerializableValue.java +++ b/src/main/java/carpet/script/value/NBTSerializableValue.java @@ -7,17 +7,15 @@ import com.mojang.brigadier.StringReader; import com.mojang.brigadier.exceptions.CommandSyntaxException; import net.minecraft.block.entity.HopperBlockEntity; import net.minecraft.command.arguments.ItemStackArgument; -import net.minecraft.command.arguments.ItemStackArgumentType; import net.minecraft.command.arguments.ItemStringReader; import net.minecraft.entity.Entity; -import net.minecraft.entity.passive.AbstractTraderEntity; import net.minecraft.entity.passive.VillagerEntity; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.inventory.Inventory; import net.minecraft.item.ItemStack; import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.StringNbtReader; import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.MathHelper; import java.util.HashMap; import java.util.List; @@ -26,15 +24,33 @@ import java.util.function.Supplier; public class NBTSerializableValue extends Value { - private Object what; private String nbtString = null; private CompoundTag nbtTag = null; - private Supplier nbtSupplier; + private Supplier nbtSupplier = null; public NBTSerializableValue(ItemStack stack) { - what = stack; - nbtSupplier = () -> ((ItemStack) what).toTag(new CompoundTag()); + nbtSupplier = () -> stack.hasTag() ? stack.getTag(): new CompoundTag(); + } + + public NBTSerializableValue(String nbtString) + { + nbtSupplier = () -> + { + try + { + return (new StringNbtReader(new StringReader(nbtString))).parseCompoundTag(); + } + catch (CommandSyntaxException e) + { + throw new InternalExpressionException("Incorrect nbt data: "+nbtString); + } + }; + } + + public NBTSerializableValue(CompoundTag tag) + { + nbtTag = tag; } public static InventoryLocator locateInventory(CarpetContext c, List params, int offset) @@ -93,19 +109,32 @@ public class NBTSerializableValue extends Value } private static Map itemCache = new HashMap<>(); + public static ItemStackArgument parseItem(String itemString) + { + return parseItem(itemString, null); + } + + public static ItemStackArgument parseItem(String itemString, CompoundTag customTag) { try { ItemStackArgument res = itemCache.get(itemString); if (res != null) - return res; + if (customTag == null) + return res; + else + return new ItemStackArgument(res.getItem(), customTag); + ItemStringReader parser = (new ItemStringReader(new StringReader(itemString), false)).consume(); res = new ItemStackArgument(parser.getItem(), parser.getTag()); itemCache.put(itemString, res); if (itemCache.size()>64000) itemCache.clear(); - return res; + if (customTag == null) + return res; + else + return new ItemStackArgument(res.getItem(), customTag); } catch (CommandSyntaxException e) { @@ -123,13 +152,23 @@ public class NBTSerializableValue extends Value return slot; } - private CompoundTag getTag() + public CompoundTag getTag() { if (nbtTag == null) nbtTag = nbtSupplier.get(); return nbtTag; } + @Override + public boolean equals(final Value o) + { + if (o instanceof NBTSerializableValue) + { + return getTag().equals(((NBTSerializableValue) o).getTag()); + } + return super.equals(o); + } + @Override public String getString() diff --git a/src/main/java/carpet/script/value/NumericValue.java b/src/main/java/carpet/script/value/NumericValue.java index 2a87b334..ec7bc9b2 100644 --- a/src/main/java/carpet/script/value/NumericValue.java +++ b/src/main/java/carpet/script/value/NumericValue.java @@ -116,7 +116,7 @@ public class NumericValue extends Value { return value.compareTo(((NumericValue) o).getDouble()); } - return super.compareTo(o); + return getString().compareTo(o.getString()); } @Override public boolean equals(Value o)