From 4145280bcda5162e844f5a5a0a8d444007ab164b Mon Sep 17 00:00:00 2001 From: gnembon Date: Thu, 18 Jun 2020 17:15:07 -0300 Subject: [PATCH] added parse_nbt and ability for set to submit params in list, and block data. --- docs/scarpet/api/BlocksAndWorldAccess.md | 8 +- .../java/carpet/script/CarpetExpression.java | 79 +++++++++++++------ .../script/value/NBTSerializableValue.java | 7 +- 3 files changed, 65 insertions(+), 29 deletions(-) diff --git a/docs/scarpet/api/BlocksAndWorldAccess.md b/docs/scarpet/api/BlocksAndWorldAccess.md index 522faff2..6ef5f75b 100644 --- a/docs/scarpet/api/BlocksAndWorldAccess.md +++ b/docs/scarpet/api/BlocksAndWorldAccess.md @@ -36,11 +36,14 @@ print(b); // 'stone', block was evaluated 'eagerly' but call to `block` All the functions below can be used with block value, queried with coord triple, or 3-long list. All `pos` in the functions referenced below refer to either method of passing block position. -### `set(pos, block, property?, value?, ...)` +### `set(pos, block, property?, value?, ..., block_data?)`, `set(pos, block, l(property?, value?, ...), block_data?)` First part of the `set` function is either a coord triple, list of three numbers, or other block with coordinates. Second part, `block` is either block value as a result of `block()` function string value indicating the block name, -and optional `property - value` pairs for extra block properties. If `block` is specified only by name, then if a +and optional `property - value` pairs for extra block properties. Optional `block_data` include the block data to +be set for the target block. + +If `block` is specified only by name, then if a destination block is the same the `set` operation is skipped, otherwise is executed, for other potential extra properties. @@ -64,6 +67,7 @@ set(x,y,z,'iron_trapdoor[half=top]') // Incorrect. sets bottom iron trapdoor - set(x,y,z,'iron_trapdoor','half','top') // correct - top trapdoor set(x,y,z, block('iron_trapdoor[half=top]')) // also correct, block() provides extra parsing set(x,y,z,'hopper[facing=north]{Items:[{Slot:1b,id:"minecraft:slime_ball",Count:16b}]}') // extra block data +set(x,y,z,'hopper', l('facing', 'north'), nbt('{Items:[{Slot:1b,id:"minecraft:slime_ball",Count:16b}]}') ) // same ### `without_updates(expr)` diff --git a/src/main/java/carpet/script/CarpetExpression.java b/src/main/java/carpet/script/CarpetExpression.java index 8eb1397b..54894ce9 100644 --- a/src/main/java/carpet/script/CarpetExpression.java +++ b/src/main/java/carpet/script/CarpetExpression.java @@ -764,27 +764,55 @@ public class CarpetExpression { CarpetContext cc = (CarpetContext)c; ServerWorld world = cc.s.getWorld(); - if (lv.size() < 2 || lv.size() % 2 == 1) - throw new InternalExpressionException("'set' should have at least 2 params and odd attributes"); BlockArgument targetLocator = BlockArgument.findIn(cc, lv, 0); BlockArgument sourceLocator = BlockArgument.findIn(cc, lv, targetLocator.offset, true); BlockState sourceBlockState = sourceLocator.block.getBlockState(); BlockState targetBlockState = world.getBlockState(targetLocator.block.getPos()); - if (sourceLocator.offset < lv.size()) + List args = new ArrayList<>(); + for (int i = sourceLocator.offset, m = lv.size(); i < m; i++) { - StateManager states = sourceBlockState.getBlock().getStateManager(); - for (int i = sourceLocator.offset; i < lv.size(); i += 2) + args.add(lv.get(i).evalValue(c)); + } + CompoundTag data = null; + if (!args.isEmpty()) + { + if (args.get(0) instanceof ListValue) { - String paramString = lv.get(i).evalValue(c).getString(); + if (args.size() == 2) + { + Value dataValue = NBTSerializableValue.fromValue( args.get(1)); + if (dataValue instanceof NBTSerializableValue) + { + data = ((NBTSerializableValue) dataValue).getCompoundTag(); + } + } + args = ((ListValue) args.get(0)).getItems(); + } + else + { + if ((args.size() & 1) == 1) + { + Value dataValue = NBTSerializableValue.fromValue( args.get(args.size()-1)); + if (dataValue instanceof NBTSerializableValue) + { + data = ((NBTSerializableValue) dataValue).getCompoundTag(); + } + } + } + StateManager states = sourceBlockState.getBlock().getStateManager(); + for (int i = 0; i < args.size()-1; i += 2) + { + String paramString = args.get(i).getString(); Property property = states.getProperty(paramString); if (property == null) throw new InternalExpressionException("Property " + paramString + " doesn't apply to " + sourceLocator.block.getString()); - String paramValue = lv.get(i + 1).evalValue(c).getString(); + String paramValue = args.get(i + 1).getString(); sourceBlockState = setProperty(property, paramString, paramValue, sourceBlockState); } } - CompoundTag data = sourceLocator.block.getData(); + if (data == null) data = sourceLocator.block.getData(); + CompoundTag finalData = data; if (sourceBlockState == targetBlockState && data == null) return (c_, t_) -> Value.FALSE; @@ -794,12 +822,12 @@ public class CarpetExpression { Clearable.clear(world.getBlockEntity(targetPos)); world.setBlockState(targetPos, finalSourceBlockState, 2); - if (data != null) + if (finalData != null) { BlockEntity be = world.getBlockEntity(targetPos); if (be != null) { - CompoundTag destTag = data.copy(); + CompoundTag destTag = finalData.copy(); destTag.putInt("x", targetPos.getX()); destTag.putInt("y", targetPos.getY()); destTag.putInt("z", targetPos.getZ()); @@ -908,7 +936,7 @@ public class CarpetExpression Tag outtag = tool.getTag(); if (outtag == null) return LazyValue.TRUE; - Value ret = new NBTSerializableValue(outtag); + Value ret = new NBTSerializableValue(() -> outtag); return (_c, _t) -> ret; }); @@ -1951,11 +1979,9 @@ public class CarpetExpression Value nbt = lv.get(position.offset).evalValue(c); NBTSerializableValue v = (nbt instanceof NBTSerializableValue) ? (NBTSerializableValue) nbt : NBTSerializableValue.parseString(nbt.getString()); - if (v != null) - { - hasTag = true; - tag = v.getCompoundTag(); - } + hasTag = true; + tag = v.getCompoundTag(); + } tag.putString("id", entityId.toString()); Vec3d vec3d = position.vec; @@ -2898,12 +2924,7 @@ public class CarpetExpression }); this.expr.addLazyFunction("nbt", 1, (c, t, lv) -> { - Value v = lv.get(0).evalValue(c); - if (v instanceof NBTSerializableValue) - return (cc, tt) -> v; - Value ret = NBTSerializableValue.parseString(v.getString()); - if (ret == null) - return LazyValue.NULL; + Value ret = NBTSerializableValue.fromValue(lv.get(0).evalValue(c)); return (cc, tt) -> ret; }); @@ -2914,6 +2935,20 @@ public class CarpetExpression return (cc, tt) -> ret; }); + this.expr.addLazyFunction("parse_nbt", 1, (c, t, lv) -> { + Value v = lv.get(0).evalValue(c); + if (v instanceof NBTSerializableValue) + { + Value parsed = ((NBTSerializableValue) v).toValue(); + return (cc, tt) -> parsed; + } + NBTSerializableValue ret = NBTSerializableValue.parseString(v.getString()); + if (ret == null) + return LazyValue.NULL; + Value parsed = ret.toValue(); + return (cc, tt) -> parsed; + }); + //"overridden" native call that prints to stderr this.expr.addLazyFunction("print", -1, (c, t, lv) -> { diff --git a/src/main/java/carpet/script/value/NBTSerializableValue.java b/src/main/java/carpet/script/value/NBTSerializableValue.java index b6d9e6fc..63461472 100644 --- a/src/main/java/carpet/script/value/NBTSerializableValue.java +++ b/src/main/java/carpet/script/value/NBTSerializableValue.java @@ -109,7 +109,7 @@ public class NBTSerializableValue extends Value implements ContainerValueInterfa } catch (CommandSyntaxException e) { - return null; + throw new InternalExpressionException("Incorrect NBT tag: nbtString"); } NBTSerializableValue value = new NBTSerializableValue(tag); value.nbtString = nbtString; @@ -317,10 +317,7 @@ public class NBTSerializableValue extends Value implements ContainerValueInterfa return v; if (v instanceof NullValue) return Value.NULL; - Value ret = NBTSerializableValue.parseString(v.getString()); - if (ret == null) - return Value.NULL; - return ret; + return NBTSerializableValue.parseString(v.getString()); }