reworked destroy

This commit is contained in:
gnembon committed 2020-02-06 21:00:02 -04:00
1 parent 67d71e26c1
commit c3137203b2
1 file changed
+73 -17
@@ -44,6 +44,7 @@ import net.minecraft.block.JigsawBlock;
import net.minecraft.block.StructureBlock;
import net.minecraft.block.entity.BlockEntity;
import net.minecraft.enchantment.EnchantmentHelper;
import net.minecraft.entity.FallingBlockEntity;
import net.minecraft.item.BlockItem;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
@@ -154,6 +155,7 @@ public class CarpetExpression
private final Expression expr;
Expression getExpr() {return expr;}
private static long tickStart = 0L;
private static FallingBlockEntity DUMMY_ENTITY = new FallingBlockEntity(EntityType.FALLING_BLOCK, null);
private static boolean stopAll = false;
@@ -521,9 +523,45 @@ public class CarpetExpression
* <p>Causes a block to tick at position.</p>
* <h3><code>random_tick(pos)</code></h3>
* <p>Causes a random tick at position.</p>
* <h3><code>destroy(pos), destroy(pos, -1), destroy(pos, &lt;N&gt;)</code></h3>
* <h3><code>destroy(pos), destroy(pos, -1), destroy(pos, &lt;N&gt;), destroy(pos, tool, nbt?)</code></h3>
* <p>Destroys the block like it was mined by a player. Add -1 for silk touch, and positive number for fortune level.
* This function, unlike harvest, will affect all kinds of blocks</p>
* If tool is specified, and optionally its nbt, it will use that tool and will attempt to mine the block with this tool.
* If called without item context, this function, unlike harvest, will affect all kinds of blocks. If called with item in context,
* it will fail to break blocks that cannot be broken by a survival player.</p>
* <p>Without item context it returns <code>false</code> if failed to destroy the block and <code>true</code> if block breaking was
* successful. In item context, <code>true</code> means that breaking item has no nbt to use, <code>null</code> indicating that
* the tool should be considered broken in process, and <code>nbt</code> type value, for a resulting NBT tag on a hypothetical tool.
* Its up to the programmer to use that nbt to apply it where it belong
* </p>
* <p>Here is a sample code that can be used to mine blocks using items in player inventory, without using player context for mining.
* Obviously, in this case the use of <code>harvest</code> would be much more applicable:</p>
* <pre>
* mine(x,y,z) -&gt;
* (
* p = player();
* slot = p~'selected_slot';
* item_tuple = inventory_get(p, slot);
* if (!item_tuple, destroy(x,y,z,'air'); return()); // empty hand, just break with 'air'
* l(item, count, tag) = item_tuple;
* tag_back = destroy(x,y,z, item, tag);
* if (tag_back == false, // failed to break the item
* return(tag_back)
* );
* if (tag_back == true, // block broke, tool has no tag
* return(tag_back)
* );
* if (tag_back == null, //item broke
* delete(tag:'Damage');
* inventory_set(p, slot, count-1, item, tag);
* return(tag_back)
* );
* if (type(tag_back) == 'nbt', // item didn't break, here is the effective nbt
* inventory_set(p, slot, count, item, tag_back);
* return(tag_back)
* );
* print('How did we get here?');
* )
* </pre>
* <h3><code>harvest(player, pos)</code></h3>
* <p>Causes a block to be harvested by a specified player entity. Honors player item enchantments, as well as damages the
* tool if applicable. If the entity is not a valid player, no block gets destroyed. If a player is not allowed to
@@ -1243,25 +1281,40 @@ public class CarpetExpression
BlockPos where = locator.block.getPos();
BlockEntity be = world.getBlockEntity(where);
long how = 0;
if (lv.size() > locator.offset)
how = NumericValue.asNumber(lv.get(locator.offset).evalValue(cc)).getLong();
Item item = Items.DIAMOND_PICKAXE;
boolean playerBreak = false;
if (lv.size() > locator.offset+1)
if (lv.size() > locator.offset)
{
playerBreak = true;
String itemString = lv.get(locator.offset+1).evalValue(c).getString();
item = Registry.ITEM.get(new Identifier(itemString));
if (item == Items.AIR && !itemString.equals("air")) throw new InternalExpressionException("Incorrect item: "+itemString);
Value val = lv.get(locator.offset).evalValue(c);
if (val instanceof NumericValue)
{
how = ((NumericValue) val).getLong();
}
else
{
playerBreak = true;
String itemString = val.getString();
item = Registry.ITEM.get(new Identifier(itemString));
if (item == Items.AIR && !itemString.equals("air"))
throw new InternalExpressionException("Incorrect item: " + itemString);
}
}
CompoundTag tag = null;
if (lv.size() > locator.offset+2)
if (lv.size() > locator.offset+1)
{
Value tagValue = lv.get(locator.offset+2).evalValue(c);
if (tagValue instanceof NBTSerializableValue)
if (!playerBreak) throw new InternalExpressionException("tag is not necessary with 'destroy' with no item");
Value tagValue = lv.get(locator.offset+1).evalValue(c);
if (tagValue instanceof NullValue)
tag = null;
else if (tagValue instanceof NBTSerializableValue)
tag = ((NBTSerializableValue) tagValue).getCompoundTag();
else
tag = NBTSerializableValue.parseString(tagValue.getString()).getCompoundTag();
{
NBTSerializableValue readTag = NBTSerializableValue.parseString(tagValue.getString());
if (readTag == null)
throw new InternalExpressionException("Incorrect tag: "+tagValue.getString());
tag = readTag.getCompoundTag();
}
}
ItemStack tool = new ItemStack(item, 1);
@@ -1277,7 +1330,7 @@ public class CarpetExpression
if (playerBreak)
{
boolean isUsingEffectiveTool = state.getMaterial().canBreakByHand() || tool.isEffectiveOn(state);
//postMine durability
//postMine() durability from item classes
float hardness = state.getHardness(world, where);
int damageAmount = 0;
if ((item instanceof MiningToolItem && hardness > 0.0) || item instanceof ShearsItem)
@@ -1303,14 +1356,17 @@ public class CarpetExpression
{
if (how > 0)
tool.addEnchantment(Enchantments.FORTUNE, (int) how);
Block.dropStacks(state, world, where, be, null, tool);
Block.dropStacks(state, world, where, be, DUMMY_ENTITY, tool);
}
}
if (!playerBreak)
if (!playerBreak) // no tool info - block brokwn
return (c_, t_) -> Value.TRUE;
if (toolBroke)
return LazyValue.NULL;
Value ret = new NBTSerializableValue(tool.getTag());
Tag outtag = tool.getTag();
if (outtag == null)
return LazyValue.TRUE;
Value ret = new NBTSerializableValue(outtag);
return (_c, _t) -> ret;
});