touchups and docs
This commit is contained in:
1 parent
5bb813be76
commit
dca72f603b
5 files changed
+234
-108
No files matched your search
@@ -5,6 +5,7 @@ build/
|
|||||||
out/
|
out/
|
||||||
classes/
|
classes/
|
||||||
publish/
|
publish/
|
||||||
|
docs/
|
||||||
|
|
||||||
# idea
|
# idea
|
||||||
|
|
||||||
|
|||||||
@@ -281,12 +281,13 @@ public class CarpetExpression
|
|||||||
* <h2>Specifying blocks</h2>
|
* <h2>Specifying blocks</h2>
|
||||||
* <h3><code>block(x, y, z), block(state)</code></h3>
|
* <h3><code>block(x, y, z), block(state)</code></h3>
|
||||||
* <p>Returns either a block from specified location, or block with a specific state
|
* <p>Returns either a block from specified location, or block with a specific state
|
||||||
* (as used by <code>/setblock</code> command), so allowing for block properties etc.
|
* (as used by <code>/setblock</code> command), so allowing for block properties, block entity data etc.
|
||||||
* Blocks can be referenced everywhere by its simple name, but its only used in its default state</p>
|
* Blocks otherwise can be referenced everywhere by its simple string name, but its only used in its default state</p>
|
||||||
* <pre>
|
* <pre>
|
||||||
* block('air') => air
|
* block('air') => air
|
||||||
* block('iron_trapdoor[half=top]') => iron_trapdoor
|
* block('iron_trapdoor[half=top]') => iron_trapdoor
|
||||||
* block(0,0,0) == block('bedrock') => 1
|
* block(0,0,0) == block('bedrock') => 1
|
||||||
|
* block('hopper[facing=north]{Items:[{Slot:1b,id:"minecraft:slime_ball",Count:16b}]}') => hopper
|
||||||
* </pre>
|
* </pre>
|
||||||
* <h2>World Manipulation</h2>
|
* <h2>World Manipulation</h2>
|
||||||
* <p>All the functions below can be used with block value, queried with coord triple, or 3-long list.
|
* <p>All the functions below can be used with block value, queried with coord triple, or 3-long list.
|
||||||
@@ -315,6 +316,21 @@ public class CarpetExpression
|
|||||||
* set(x,y,z,'iron_trapdoor[half=top]') // Incorrect. sets bottom iron trapdoor - no parsing of properties
|
* set(x,y,z,'iron_trapdoor[half=top]') // Incorrect. sets bottom iron trapdoor - no parsing of properties
|
||||||
* set(x,y,z,'iron_trapdoor','half','top') // correct - top 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,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
|
||||||
|
* </pre>
|
||||||
|
* <h3><code>place_item(item, pos, facing?, sneak?)</code></h3>
|
||||||
|
* <p>Places a given item in the world like it was placed by a player. Item names are default minecraft item name,
|
||||||
|
* less the minecraft prefix. Default facing is 'up', but there are other options: 'down', 'north', 'east',
|
||||||
|
* 'south', 'west', but also there are other secondary directions important for placement of blocks like stairs, doors, etc.
|
||||||
|
* Try experiment with options like 'north-up' which is placed facing north with cursor pointing to the upper part of the block,
|
||||||
|
* or 'up-north', which means a block placed facing up (player looking down) and placed smidge away of the block center
|
||||||
|
* towards north. Optional sneak is a boolean indicating if a player would be sneaking while placing the block -
|
||||||
|
* this option only affects placement of chests and scaffolding at the moment.
|
||||||
|
* Returns true if placement was successful, false otherwise.</p>
|
||||||
|
* <pre>
|
||||||
|
* place_item('stone',x,y,z) // places a stone block on x,y,z block
|
||||||
|
* place_item('piston,x,y,z,'down') // places a piston facing down
|
||||||
|
* place_item('carrot',x,y,z) // attempts to plant a carrot plant. Returns true if could place carrots at that position.
|
||||||
* </pre>
|
* </pre>
|
||||||
* <h3><code>update(pos)</code></h3>
|
* <h3><code>update(pos)</code></h3>
|
||||||
* <p>Causes a block update at position.</p>
|
* <p>Causes a block update at position.</p>
|
||||||
@@ -352,7 +368,12 @@ public class CarpetExpression
|
|||||||
* property(block('iron_trapdoor[half=top]'),'powered') => false
|
* property(block('iron_trapdoor[half=top]'),'powered') => false
|
||||||
* bool(property(block('iron_trapdoor[half=top]'),'powered')) => 0
|
* bool(property(block('iron_trapdoor[half=top]'),'powered')) => 0
|
||||||
* </pre>
|
* </pre>
|
||||||
*
|
* <h3><code>block_data(pos)</code></h3>
|
||||||
|
* <p>Return NBT string associated with specific location, or null if the block does not carry block data.
|
||||||
|
* Can be currently used to match specific information from it, or use it to copy to another block</p>
|
||||||
|
* <pre>
|
||||||
|
* block_data(x,y,z) => '{TransferCooldown:0,x:450,y:68, ... }'
|
||||||
|
* </pre>
|
||||||
* <h3><code>solid(pos)</code></h3>
|
* <h3><code>solid(pos)</code></h3>
|
||||||
* <p>Boolean function, true if the block is solid</p>
|
* <p>Boolean function, true if the block is solid</p>
|
||||||
* <h3> <code>air(pos)</code></h3>
|
* <h3> <code>air(pos)</code></h3>
|
||||||
@@ -904,6 +925,87 @@ public class CarpetExpression
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <h1>Inventory and Items API</h1>
|
||||||
|
* <div style="padding-left: 20px; border-radius: 5px 45px; border:1px solid grey;">
|
||||||
|
* <h2>Manipulating inventories of blocks and entities</h2>
|
||||||
|
* <p>Most functions in this category require inventory as the first argument. Inventory could be specified by
|
||||||
|
* an entity, or a block, or position (three coordinates) of a potential block with inventory.
|
||||||
|
* If the entity or a block doesn't
|
||||||
|
* have an inventory, they typically do nothing and return null.</p>
|
||||||
|
* <p>Most items returned are in the form of
|
||||||
|
* a triple of item name, count, and nbt or the extra data associated with an item.
|
||||||
|
* Manipulating of the nbt data can be costly, but retrieving them from the tuple to match other aspects is cheap</p>
|
||||||
|
* <h3><code>stack_limit(item)</code></h3>
|
||||||
|
* <p>Returns number indicating what is the stack limit for the item. Its typically 1 (non-stackable),
|
||||||
|
* 16 (like buckets), or 64 - rest. It is recommended to consult this, as other inventory API functions
|
||||||
|
* ignore normal stack limits, and it is up to the programmer to keep it at bay. As of 1.13, game checks for negative
|
||||||
|
* numbers and setting an item to negative is the same as empty.</p>
|
||||||
|
* <pre>
|
||||||
|
* stack_limit('wooden_axe') => 1
|
||||||
|
* stack_limit('ender_pearl') => 16
|
||||||
|
* stack_limit('stone') => 64
|
||||||
|
* </pre>
|
||||||
|
* <h3><code>inventory_size(inventory)</code></h3>
|
||||||
|
* <p>Returns the size of the inventory for the entity or block in question. Returns null if the block or entity
|
||||||
|
* don't have an inventory</p>
|
||||||
|
* <pre>
|
||||||
|
* inventory_size(player()) => 41
|
||||||
|
* inventory_size(x,y,z) => 27 // chest
|
||||||
|
* inventory_size(block(pos)) => 5 // hopper
|
||||||
|
* </pre>
|
||||||
|
* <h3><code>inventory_get(inventory, slot)</code></h3>
|
||||||
|
* <p>Returns the item in the corresponding inventory slot, or null if slot empty or inventory is invalid.
|
||||||
|
* You can use negative numbers to indicate slots counted from 'the back'.</p>
|
||||||
|
* <pre>
|
||||||
|
* inventory_get(player(), 0) => null // nothing in first hotbar slot
|
||||||
|
* inventory_get(x,y,z, 5) => ['stone', 1, {}]
|
||||||
|
* inventory_get(player(), -1) => ['diamond_pickaxe', 1, {Damage:4}] // slightly damaged diamond pick in the offhand
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* <h3><code>inventory_set(inventory, slot, count, item?, nbt?) </code></h3>
|
||||||
|
* <p>Modifies or sets a stack in inventory. specify count 0 to empty the slot.
|
||||||
|
* If item is not specified, keeps existing item, just modifies the count. If item is provided - replaces current item.
|
||||||
|
* If nbt is provided - adds a tag to the stack at slot. Returns previous stack in that slot.</p>
|
||||||
|
* <pre>
|
||||||
|
* inventory_set(player(), 0, 0) => ['stone', 64, {}] // player had a stack of stone in first hotbar slot
|
||||||
|
* inventory_set(player(), 0, 6) => ['diamond', 64, {}] // changed stack of diamonds in player slot to 6
|
||||||
|
* inventory_set(player(), 0, 1, 'diamond_axe','{Damage:5}') => null //added slightly damaged pick to first player slot
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* <h3><code>inventory_find(inventory, item, start_slot?, ), inventory_find(inventory, null, start_slot?) </code></h3>
|
||||||
|
* <p>Finds the first slot with a corresponding item in the inventory, or if queried with null: the first empty slot.
|
||||||
|
* Returns slot number if found, or null otherwise. Optional start_slot argument allows to skip all preceeding slots
|
||||||
|
* allowing for efficient (so not slot-by-slot) inventory search for items.</p>
|
||||||
|
* <pre>
|
||||||
|
* inventory_find(player(), 'stone') => 0 // player has stone in first hotbar slot
|
||||||
|
* inventory_find(player(), null) => null // player's inventory has no empty spot
|
||||||
|
* while( (slot = inventory_find(p, 'diamond', slot)) != null, 41, drop_item(p, slot) )
|
||||||
|
* // spits all diamonds from player inventory wherever they are
|
||||||
|
* inventory_drop(x,y,z, 0) => 64 // removed and spawned in the world a full stack of items
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* <h3><code>inventory_remove(inventory, item, amount?) </code></h3>
|
||||||
|
* <p>Removes amount (defaults to 1) of item from inventory. If the inventory doesn't have the defined amount, nothing
|
||||||
|
* happens, otherwise the given amount of items is removed wherever they are in the inventory. Returns boolean whether
|
||||||
|
* the removal operation was successful. Easiest way to remove a specific item from player inventory without specifying
|
||||||
|
* the slot.</p>
|
||||||
|
* <pre>
|
||||||
|
* inventory_remove(player(), 'diamond') => 1 // removed diamond from player inventory
|
||||||
|
* inventory_remove(player(), 'diamond', 100) => 0 // player doesn't have 100 diamonds, nothing happened
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* <h3><code>drop_item(inventory, slot, amount?, )</code></h3>
|
||||||
|
* <p>Drops the items from indicated inventory slot, like player that Q's an item or villager, that exchanges food.
|
||||||
|
* You can Q items from block inventories as well. default amount is 0 - which is all from the slot. NOTE: hoppers are quick
|
||||||
|
* enough to pick all the queued items from their inventory anyways.
|
||||||
|
* Returns size of the actual dropped items.</p>
|
||||||
|
* <pre>
|
||||||
|
* inventory_drop(player(), 0, 1) => 1 // Q's one item on the ground
|
||||||
|
* inventory_drop(x,y,z, 0) => 64 // removed and spawned in the world a full stack of items
|
||||||
|
* </pre>
|
||||||
|
* </div>
|
||||||
|
*/
|
||||||
public void API_InventoryManipulation()
|
public void API_InventoryManipulation()
|
||||||
{
|
{
|
||||||
this.expr.addLazyFunction("stack_limit", 1, (c, t, lv) ->
|
this.expr.addLazyFunction("stack_limit", 1, (c, t, lv) ->
|
||||||
@@ -948,58 +1050,59 @@ public class CarpetExpression
|
|||||||
return (_c, _t) -> res;
|
return (_c, _t) -> res;
|
||||||
});
|
});
|
||||||
|
|
||||||
//inventory_drop(<b, e>, <n>, <amount=1, 0-whatever's there>) -> entity_item (and sets slot) or null if cannot
|
//inventory_set(<b,e>, <n>, <count>, <item>, <nbt>)
|
||||||
this.expr.addLazyFunction("inventory_drop", -1, (c, t, lv) ->
|
this.expr.addLazyFunction("inventory_set", -1, (c, t, lv) ->
|
||||||
{
|
{
|
||||||
CarpetContext cc = (CarpetContext) c;
|
CarpetContext cc = (CarpetContext) c;
|
||||||
NBTSerializableValue.InventoryLocator inventoryLocator = NBTSerializableValue.locateInventory(cc, lv, 0);
|
NBTSerializableValue.InventoryLocator inventoryLocator = NBTSerializableValue.locateInventory(cc, lv, 0);
|
||||||
if (inventoryLocator == null)
|
if (inventoryLocator == null)
|
||||||
return (_c, _t) -> Value.NULL;
|
return (_c, _t) -> Value.NULL;
|
||||||
if (lv.size() == inventoryLocator.offset)
|
if (lv.size() < inventoryLocator.offset+2)
|
||||||
throw new InternalExpressionException("slot number is required for inventory_drop");
|
throw new InternalExpressionException("inventory_set requires at least slot number and new stack size, and optional new item");
|
||||||
int slot = (int)NumericValue.asNumber(lv.get(inventoryLocator.offset).evalValue(c)).getLong();
|
int slot = (int) NumericValue.asNumber(lv.get(inventoryLocator.offset+0).evalValue(c)).getLong();
|
||||||
slot = NBTSerializableValue.validateSlot(slot, inventoryLocator.inventory);
|
slot = NBTSerializableValue.validateSlot(slot, inventoryLocator.inventory);
|
||||||
if (slot == inventoryLocator.inventory.getInvSize())
|
if (slot == inventoryLocator.inventory.getInvSize())
|
||||||
return (_c, _t) -> Value.NULL;
|
return (_c, _t) -> Value.NULL;
|
||||||
int amount = 0;
|
int count = (int) NumericValue.asNumber(lv.get(inventoryLocator.offset+1).evalValue(c)).getLong();
|
||||||
if (lv.size() > inventoryLocator.offset+1)
|
if (count == 0)
|
||||||
amount = (int)NumericValue.asNumber(lv.get(inventoryLocator.offset+1).evalValue(c)).getLong();
|
|
||||||
if (amount < 0)
|
|
||||||
throw new InternalExpressionException("Cannot throw negative number of items");
|
|
||||||
ItemStack stack = inventoryLocator.inventory.getInvStack(slot);
|
|
||||||
if (stack == null || stack.isEmpty())
|
|
||||||
return (_c, _t) -> Value.ZERO;
|
|
||||||
if (amount == 0)
|
|
||||||
amount = stack.getCount();
|
|
||||||
ItemStack droppedStack = inventoryLocator.inventory.takeInvStack(slot, amount);
|
|
||||||
if (droppedStack.isEmpty())
|
|
||||||
{
|
{
|
||||||
return (_c, _t) -> Value.ZERO;
|
// clear slot
|
||||||
|
ItemStack removedStack = inventoryLocator.inventory.removeInvStack(slot);
|
||||||
|
//Value res = ListValue.fromItemStack(removedStack); // that tuple will be read only but cheaper if noone cares
|
||||||
|
return (_c, _t) -> ListValue.fromItemStack(removedStack);
|
||||||
}
|
}
|
||||||
Object owner = inventoryLocator.owner;
|
if (lv.size() < inventoryLocator.offset+3)
|
||||||
ItemEntity item;
|
|
||||||
if (owner instanceof PlayerEntity)
|
|
||||||
item = ((PlayerEntity) owner).dropItem(droppedStack, false, true);
|
|
||||||
else if (owner instanceof LivingEntity)
|
|
||||||
{
|
{
|
||||||
LivingEntity villager = (LivingEntity)owner;
|
ItemStack previousStack = inventoryLocator.inventory.getInvStack(slot);
|
||||||
// stolen from LookTargetUtil.give((VillagerEntity)owner, droppedStack, (LivingEntity) owner);
|
ItemStack newStack = previousStack.copy();
|
||||||
double double_1 = villager.y - 0.30000001192092896D + (double)villager.getStandingEyeHeight();
|
newStack.setCount(count);
|
||||||
item = new ItemEntity(villager.world, villager.x, double_1, villager.z, droppedStack);
|
inventoryLocator.inventory.setInvStack(slot, newStack);
|
||||||
Vec3d vec3d_1 = villager.getRotationVec(1.0F).normalize().multiply(0.3);// new Vec3d(0, 0.3, 0);
|
return (_c, _t) -> ListValue.fromItemStack(previousStack);
|
||||||
item.setVelocity(vec3d_1);
|
|
||||||
item.setToDefaultPickupDelay();
|
|
||||||
}
|
}
|
||||||
else
|
CompoundTag nbt = null; // skipping one argument
|
||||||
|
if (lv.size() > inventoryLocator.offset+3)
|
||||||
{
|
{
|
||||||
Vec3d point = new Vec3d(inventoryLocator.position);
|
Value nbtValue = lv.get(inventoryLocator.offset+3).evalValue(c);
|
||||||
item = new ItemEntity(cc.s.getWorld(), point.x+0.5, point.y+0.5, point.z+0.5, droppedStack);
|
if (nbtValue instanceof NBTSerializableValue)
|
||||||
item.setToDefaultPickupDelay();
|
nbt = ((NBTSerializableValue)nbtValue).getTag();
|
||||||
|
else
|
||||||
|
nbt = new NBTSerializableValue(nbtValue.getString()).getTag();
|
||||||
}
|
}
|
||||||
inventoryLocator.inventory.markDirty();
|
ItemStackArgument newitem = NBTSerializableValue.parseItem(
|
||||||
cc.s.getWorld().spawnEntity(item);
|
lv.get(inventoryLocator.offset+2).evalValue(c).getString(),
|
||||||
Value res = new NumericValue(item.getStack().getCount());
|
nbt
|
||||||
return (_c, _t) -> res;
|
);
|
||||||
|
|
||||||
|
ItemStack previousStack = inventoryLocator.inventory.getInvStack(slot);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
inventoryLocator.inventory.setInvStack(slot, newitem.createStack(count, false));
|
||||||
|
}
|
||||||
|
catch (CommandSyntaxException e)
|
||||||
|
{
|
||||||
|
throw new InternalExpressionException(e.getMessage());
|
||||||
|
}
|
||||||
|
return (_c, _t) -> ListValue.fromItemStack(previousStack);
|
||||||
});
|
});
|
||||||
|
|
||||||
//inventory_find(<b, e>, <item> or null (first empty slot), <start_from=0> ) -> <N> or null
|
//inventory_find(<b, e>, <item> or null (first empty slot), <start_from=0> ) -> <N> or null
|
||||||
@@ -1034,60 +1137,7 @@ public class CarpetExpression
|
|||||||
return (_c, _t) -> Value.NULL;
|
return (_c, _t) -> Value.NULL;
|
||||||
});
|
});
|
||||||
|
|
||||||
//inventory_set(<b,e>, <n>, <count>, <item>, <nbt>)
|
|
||||||
this.expr.addLazyFunction("inventory_set", -1, (c, t, lv) ->
|
|
||||||
{
|
|
||||||
CarpetContext cc = (CarpetContext) c;
|
|
||||||
NBTSerializableValue.InventoryLocator inventoryLocator = NBTSerializableValue.locateInventory(cc, lv, 0);
|
|
||||||
if (inventoryLocator == null)
|
|
||||||
return (_c, _t) -> Value.NULL;
|
|
||||||
if (lv.size() < inventoryLocator.offset+2)
|
|
||||||
throw new InternalExpressionException("inventory_set requires at least slot number and new stack size, and optional new item");
|
|
||||||
int slot = (int) NumericValue.asNumber(lv.get(inventoryLocator.offset+0).evalValue(c)).getLong();
|
|
||||||
slot = NBTSerializableValue.validateSlot(slot, inventoryLocator.inventory);
|
|
||||||
if (slot == inventoryLocator.inventory.getInvSize())
|
|
||||||
return (_c, _t) -> Value.NULL;
|
|
||||||
int count = (int) NumericValue.asNumber(lv.get(inventoryLocator.offset+1).evalValue(c)).getLong();
|
|
||||||
if (count == 0)
|
|
||||||
{
|
|
||||||
// clear slot
|
|
||||||
ItemStack removedStack = inventoryLocator.inventory.removeInvStack(slot);
|
|
||||||
//Value res = ListValue.fromItemStack(removedStack); // that tuple will be read only but cheaper if noone cares
|
|
||||||
return (_c, _t) -> ListValue.fromItemStack(removedStack);
|
|
||||||
}
|
|
||||||
if (lv.size() < inventoryLocator.offset+3)
|
|
||||||
{
|
|
||||||
ItemStack previousStack = inventoryLocator.inventory.getInvStack(slot);
|
|
||||||
ItemStack newStack = previousStack.copy();
|
|
||||||
newStack.setCount(count);
|
|
||||||
inventoryLocator.inventory.setInvStack(slot, newStack);
|
|
||||||
return (_c, _t) -> ListValue.fromItemStack(previousStack);
|
|
||||||
}
|
|
||||||
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
|
|
||||||
{
|
|
||||||
inventoryLocator.inventory.setInvStack(slot, newitem.createStack(count, false));
|
|
||||||
}
|
|
||||||
catch (CommandSyntaxException e)
|
|
||||||
{
|
|
||||||
throw new InternalExpressionException(e.getMessage());
|
|
||||||
}
|
|
||||||
return (_c, _t) -> ListValue.fromItemStack(previousStack);
|
|
||||||
});
|
|
||||||
|
|
||||||
//inventory_remove(<b, e>, <item>, <amount=1>) -> bool
|
//inventory_remove(<b, e>, <item>, <amount=1>) -> bool
|
||||||
|
|
||||||
@@ -1134,6 +1184,63 @@ public class CarpetExpression
|
|||||||
throw new InternalExpressionException("Something bad happened - cannot pull all items from inventory");
|
throw new InternalExpressionException("Something bad happened - cannot pull all items from inventory");
|
||||||
return (_c, _t) -> Value.TRUE;
|
return (_c, _t) -> Value.TRUE;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
//inventory_drop(<b, e>, <n>, <amount=1, 0-whatever's there>) -> entity_item (and sets slot) or null if cannot
|
||||||
|
this.expr.addLazyFunction("drop_item", -1, (c, t, lv) ->
|
||||||
|
{
|
||||||
|
CarpetContext cc = (CarpetContext) c;
|
||||||
|
NBTSerializableValue.InventoryLocator inventoryLocator = NBTSerializableValue.locateInventory(cc, lv, 0);
|
||||||
|
if (inventoryLocator == null)
|
||||||
|
return (_c, _t) -> Value.NULL;
|
||||||
|
if (lv.size() == inventoryLocator.offset)
|
||||||
|
throw new InternalExpressionException("slot number is required for inventory_drop");
|
||||||
|
int slot = (int)NumericValue.asNumber(lv.get(inventoryLocator.offset).evalValue(c)).getLong();
|
||||||
|
slot = NBTSerializableValue.validateSlot(slot, inventoryLocator.inventory);
|
||||||
|
if (slot == inventoryLocator.inventory.getInvSize())
|
||||||
|
return (_c, _t) -> Value.NULL;
|
||||||
|
int amount = 0;
|
||||||
|
if (lv.size() > inventoryLocator.offset+1)
|
||||||
|
amount = (int)NumericValue.asNumber(lv.get(inventoryLocator.offset+1).evalValue(c)).getLong();
|
||||||
|
if (amount < 0)
|
||||||
|
throw new InternalExpressionException("Cannot throw negative number of items");
|
||||||
|
ItemStack stack = inventoryLocator.inventory.getInvStack(slot);
|
||||||
|
if (stack == null || stack.isEmpty())
|
||||||
|
return (_c, _t) -> Value.ZERO;
|
||||||
|
if (amount == 0)
|
||||||
|
amount = stack.getCount();
|
||||||
|
ItemStack droppedStack = inventoryLocator.inventory.takeInvStack(slot, amount);
|
||||||
|
if (droppedStack.isEmpty())
|
||||||
|
{
|
||||||
|
return (_c, _t) -> Value.ZERO;
|
||||||
|
}
|
||||||
|
Object owner = inventoryLocator.owner;
|
||||||
|
ItemEntity item;
|
||||||
|
if (owner instanceof PlayerEntity)
|
||||||
|
{
|
||||||
|
item = ((PlayerEntity) owner).dropItem(droppedStack, false, true);
|
||||||
|
}
|
||||||
|
else if (owner instanceof LivingEntity)
|
||||||
|
{
|
||||||
|
LivingEntity villager = (LivingEntity)owner;
|
||||||
|
// stolen from LookTargetUtil.give((VillagerEntity)owner, droppedStack, (LivingEntity) owner);
|
||||||
|
double double_1 = villager.y - 0.30000001192092896D + (double)villager.getStandingEyeHeight();
|
||||||
|
item = new ItemEntity(villager.world, villager.x, double_1, villager.z, droppedStack);
|
||||||
|
Vec3d vec3d_1 = villager.getRotationVec(1.0F).normalize().multiply(0.3);// new Vec3d(0, 0.3, 0);
|
||||||
|
item.setVelocity(vec3d_1);
|
||||||
|
item.setToDefaultPickupDelay();
|
||||||
|
cc.s.getWorld().spawnEntity(item);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Vec3d point = new Vec3d(inventoryLocator.position);
|
||||||
|
item = new ItemEntity(cc.s.getWorld(), point.x+0.5, point.y+0.5, point.z+0.5, droppedStack);
|
||||||
|
item.setToDefaultPickupDelay();
|
||||||
|
cc.s.getWorld().spawnEntity(item);
|
||||||
|
}
|
||||||
|
inventoryLocator.inventory.markDirty();
|
||||||
|
Value res = new NumericValue(item.getStack().getCount());
|
||||||
|
return (_c, _t) -> res;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1185,6 +1292,12 @@ public class CarpetExpression
|
|||||||
* <p>Unlike with blocks, that use plethora of vastly different querying functions, entities are queried with
|
* <p>Unlike with blocks, that use plethora of vastly different querying functions, entities are queried with
|
||||||
* <code>query</code> function and altered via <code>modify</code> function. Type of information needed or
|
* <code>query</code> function and altered via <code>modify</code> function. Type of information needed or
|
||||||
* values to be modified are different for each call</p>
|
* values to be modified are different for each call</p>
|
||||||
|
* <p>Using <code>~</code> (in) operator is an alias for <code>query</code>. Especially useful if a statement has
|
||||||
|
* no arguments, which in this case can be radically simplified</p>
|
||||||
|
* <pre>
|
||||||
|
* query(p, 'name') <=> p ~ 'name' // much shorter and cleaner
|
||||||
|
* query(p, 'holds', 'offhand') <=> p ~ l('holds', 'offhand') // not really but can be done
|
||||||
|
* </pre>
|
||||||
* <h3><code>query(e,'removed')</code></h3>
|
* <h3><code>query(e,'removed')</code></h3>
|
||||||
* <p>Boolean. True if the entity is removed</p>
|
* <p>Boolean. True if the entity is removed</p>
|
||||||
* <h3><code>query(e,'id')</code></h3>
|
* <h3><code>query(e,'id')</code></h3>
|
||||||
@@ -1295,6 +1408,12 @@ public class CarpetExpression
|
|||||||
* <li><code>feet</code></li>
|
* <li><code>feet</code></li>
|
||||||
* </ul>
|
* </ul>
|
||||||
* <p>If <code>slot</code> is not specified, it defaults to the main hand.</p>
|
* <p>If <code>slot</code> is not specified, it defaults to the main hand.</p>
|
||||||
|
* <h3><code>query(e,'selected_slot')</code></h3>
|
||||||
|
* <p>Number indicating the selected slot of entity inventory. Currently only applicable to players.</p>
|
||||||
|
* <h3><code>query(e,'facing', order?)</code></h3>
|
||||||
|
* <p>Returns where the entity is facing. optional order (number from 0 to 5, and negative), indicating
|
||||||
|
* primary directions where entity is looking at. From most prominent (order 0) to opposite (order 5, or -1)</p>
|
||||||
|
*
|
||||||
* <h3><code>query(e,'nbt',path?)</code></h3>
|
* <h3><code>query(e,'nbt',path?)</code></h3>
|
||||||
* <p>Returns full NBT of the entity. If path is specified, it fetches only that portion of the NBT,
|
* <p>Returns full NBT of the entity. If path is specified, it fetches only that portion of the NBT,
|
||||||
* that corresponds to the path. For specification of <code>path</code> attribute, consult
|
* that corresponds to the path. For specification of <code>path</code> attribute, consult
|
||||||
@@ -2419,6 +2538,7 @@ public class CarpetExpression
|
|||||||
* <p>The last method is the one that world edit is using (part of carpet mod). It turns out that the outline method with <code>32.5</code> radius,
|
* <p>The last method is the one that world edit is using (part of carpet mod). It turns out that the outline method with <code>32.5</code> radius,
|
||||||
* fill method with <code>round</code> function and draw command are equivalent</p>
|
* fill method with <code>round</code> function and draw command are equivalent</p>
|
||||||
* </div>
|
* </div>
|
||||||
|
* @param host .
|
||||||
* @param x .
|
* @param x .
|
||||||
* @param y .
|
* @param y .
|
||||||
* @param z .
|
* @param z .
|
||||||
@@ -2461,12 +2581,14 @@ public class CarpetExpression
|
|||||||
/**
|
/**
|
||||||
* <h1><code>/script run</code> command</h1>
|
* <h1><code>/script run</code> command</h1>
|
||||||
* <div style="padding-left: 20px; border-radius: 5px 45px; border:1px solid grey;">
|
* <div style="padding-left: 20px; border-radius: 5px 45px; border:1px solid grey;">
|
||||||
* <p>primary way to input commands. The command executes in the context, position, and dimension of the executing
|
* <p>Primary way to input commands. The command executes in the context, position, and dimension of the executing
|
||||||
* player, commandblock, etc... The command receives 4 variables, <code>x</code>, <code>y</code>, <code>z</code>
|
* player, commandblock, etc... The command receives 4 variables, <code>x</code>, <code>y</code>, <code>z</code>
|
||||||
* and <code>p</code> indicating position and the executing entity of the command.
|
* and <code>p</code> indicating position and the executing entity of the command.
|
||||||
|
* You will receive tab completion suggestions as you type your code suggesting functions and global variables.
|
||||||
* It is advisable to use <code>/execute in ... at ... as ... run script run ...</code> or similar, to simulate running
|
* It is advisable to use <code>/execute in ... at ... as ... run script run ...</code> or similar, to simulate running
|
||||||
* commands in a different scope</p>
|
* commands in a different scope</p>
|
||||||
* </div>
|
* </div>
|
||||||
|
* @param host .
|
||||||
* @param pos .
|
* @param pos .
|
||||||
* @return .
|
* @return .
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -859,9 +859,10 @@ public class Expression implements Cloneable
|
|||||||
* <p>Ability to combine more statements into one expression, with functions, passing parameters, and global and outer
|
* <p>Ability to combine more statements into one expression, with functions, passing parameters, and global and outer
|
||||||
* scoping allow to organize even larger scripts</p>
|
* scoping allow to organize even larger scripts</p>
|
||||||
* <h2>Control flow</h2>
|
* <h2>Control flow</h2>
|
||||||
* <h3><code>return(expr)</code></h3>
|
* <h3><code>return(expr?)</code></h3>
|
||||||
* <p>Sometimes its convenient to break the organized control flow, or it is not practical to pass
|
* <p>Sometimes its convenient to break the organized control flow, or it is not practical to pass
|
||||||
* the final result value of a function to the last statement, in this case a return statement can be used</p>
|
* the final result value of a function to the last statement, in this case a return statement can be used</p>
|
||||||
|
* <p>If no argument is provided - returns null value.</p>
|
||||||
* <pre>
|
* <pre>
|
||||||
* def() -> (
|
* def() -> (
|
||||||
* expr1;
|
* expr1;
|
||||||
@@ -873,12 +874,14 @@ public class Expression implements Cloneable
|
|||||||
* </pre>
|
* </pre>
|
||||||
* <p>In general its cheaper to leave the last expression as a return value, rather than calling returns everywhere,
|
* <p>In general its cheaper to leave the last expression as a return value, rather than calling returns everywhere,
|
||||||
* but it would often lead to a messy code.</p>
|
* but it would often lead to a messy code.</p>
|
||||||
* <h3><code>exit(expr)</code></h3>
|
* <h3><code>exit(expr?)</code></h3>
|
||||||
* <p>It terminates entire program passing <code>expr</code> as the result of the program execution.</p>
|
* <p>It terminates entire program passing <code>expr</code> as the result of the program execution, or null if omitted.</p>
|
||||||
* <h3><code>try(expr, catch_expr(_)) ... throw(value)</code></h3>
|
* <h3><code>try(expr, catch_expr(_)?) ... throw(value?)</code></h3>
|
||||||
* <p><code>try</code> function evaluates expression, and continues further unless <code>throw</code> function is called
|
* <p><code>try</code> function evaluates expression, and continues further unless <code>throw</code> function is called
|
||||||
* anywhere inside <code>expr</code>. In that case the <code>catch_expr</code> is evaluates with <code>_</code> set
|
* anywhere inside <code>expr</code>. In that case the <code>catch_expr</code> is evaluates with <code>_</code> set
|
||||||
* to the argument <code>throw</code> was called with. This mechanism allows to terminate large portion of a convoluted
|
* to the argument <code>throw</code> was called with.
|
||||||
|
* This mechanic accepts skipping thrown value - it throws null instead, and catch expression - then try returns null as well
|
||||||
|
* This mechanism allows to terminate large portion of a convoluted
|
||||||
* call stack and continue program execution. There is only one level of exceptions currently in carpet, so if the inner
|
* call stack and continue program execution. There is only one level of exceptions currently in carpet, so if the inner
|
||||||
* function also defines the <code>try</code> catchment area, it will received the exception first, but it can technically
|
* function also defines the <code>try</code> catchment area, it will received the exception first, but it can technically
|
||||||
* rethrow the value its getting for the outer scope. Unhandled throw acts like an exit statement.</p>
|
* rethrow the value its getting for the outer scope. Unhandled throw acts like an exit statement.</p>
|
||||||
@@ -1620,15 +1623,15 @@ public class Expression implements Cloneable
|
|||||||
* range(20, 10, -2) => [20, 18, 16, 14, 12]
|
* range(20, 10, -2) => [20, 18, 16, 14, 12]
|
||||||
* </pre>
|
* </pre>
|
||||||
*
|
*
|
||||||
* <h3><code>element(list, index)</code></h3>
|
* <h3><code>get(list, index), element(list, index)(deprecated)</code></h3>
|
||||||
* <p>Returns the value at <code>index</code> element from the <code>list</code>.
|
* <p>Returns the value at <code>index</code> element from the <code>list</code>.
|
||||||
* use negative numbers to reach elements from the end of the list. <code>element</code>
|
* use negative numbers to reach elements from the end of the list. <code>get</code>
|
||||||
* call will always be able to find the index. In case there is few items, it will loop over </p>
|
* call will always be able to find the index. In case there is few items, it will loop over </p>
|
||||||
* <pre>
|
* <pre>
|
||||||
* element(l(range(10)), 5) => 5
|
* get(l(range(10)), 5) => 5
|
||||||
* element(l(range(10)), -1) => 9
|
* get(l(range(10)), -1) => 9
|
||||||
* element(l(range(10)), 10) => 0
|
* get(l(range(10)), 10) => 0
|
||||||
* element(l(range(10)), 93) => 3
|
* get(l(range(10)), 93) => 3
|
||||||
* </pre>
|
* </pre>
|
||||||
*
|
*
|
||||||
* <h3><code>put(list, index, values ...), put(list, null, values ...)</code></h3>
|
* <h3><code>put(list, index, values ...), put(list, null, values ...)</code></h3>
|
||||||
|
|||||||
@@ -298,7 +298,7 @@ public class BlockValue extends Value
|
|||||||
|
|
||||||
DOWNNORTH ("down-north", 0.5, 1.0, 0.4, Direction.DOWN),
|
DOWNNORTH ("down-north", 0.5, 1.0, 0.4, Direction.DOWN),
|
||||||
DOWNSOUTH ("down-south", 0.5, 1.0, 0.6, Direction.DOWN),
|
DOWNSOUTH ("down-south", 0.5, 1.0, 0.6, Direction.DOWN),
|
||||||
DOWNEAST("dow-neast", 0.6, 1.0, 0.5, Direction.DOWN),
|
DOWNEAST("down-east", 0.6, 1.0, 0.5, Direction.DOWN),
|
||||||
DOWNWEST("down-west", 0.4, 1.0, 0.5, Direction.DOWN),
|
DOWNWEST("down-west", 0.4, 1.0, 0.5, Direction.DOWN),
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ public abstract class Validator<T>
|
|||||||
if (source != null)
|
if (source != null)
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Messenger.m(source, "r "+currentRule.name+" not yet fully implemented - we are still working on it.");
|
Messenger.m(source, "r "+currentRule.name+" is not yet fully implemented - we are still working on it.");
|
||||||
}
|
}
|
||||||
catch (NullPointerException ignored) { }
|
catch (NullPointerException ignored) { }
|
||||||
return newValue;
|
return newValue;
|
||||||
|
|||||||
Reference in new issue
Block a user