touchups and docs

This commit is contained in:
gnembon committed 2019-06-30 00:51:12 -03:00
1 parent 5bb813be76
commit dca72f603b
5 files changed
+234 -108

No files matched your search

+1
View File
@@ -5,6 +5,7 @@ build/
out/ out/
classes/ classes/
publish/ publish/
docs/
# idea # idea
+217 -95
View File
@@ -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') =&gt; air * block('air') =&gt; air
* block('iron_trapdoor[half=top]') =&gt; iron_trapdoor * block('iron_trapdoor[half=top]') =&gt; iron_trapdoor
* block(0,0,0) == block('bedrock') =&gt; 1 * block(0,0,0) == block('bedrock') =&gt; 1
* block('hopper[facing=north]{Items:[{Slot:1b,id:"minecraft:slime_ball",Count:16b}]}') =&gt; 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') =&gt; false * property(block('iron_trapdoor[half=top]'),'powered') =&gt; false
* bool(property(block('iron_trapdoor[half=top]'),'powered')) =&gt; 0 * bool(property(block('iron_trapdoor[half=top]'),'powered')) =&gt; 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) =&gt; '{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') =&gt; 1
* stack_limit('ender_pearl') =&gt; 16
* stack_limit('stone') =&gt; 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()) =&gt; 41
* inventory_size(x,y,z) =&gt; 27 // chest
* inventory_size(block(pos)) =&gt; 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) =&gt; null // nothing in first hotbar slot
* inventory_get(x,y,z, 5) =&gt; ['stone', 1, {}]
* inventory_get(player(), -1) =&gt; ['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) =&gt; ['stone', 64, {}] // player had a stack of stone in first hotbar slot
* inventory_set(player(), 0, 6) =&gt; ['diamond', 64, {}] // changed stack of diamonds in player slot to 6
* inventory_set(player(), 0, 1, 'diamond_axe','{Damage:5}') =&gt; 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') =&gt; 0 // player has stone in first hotbar slot
* inventory_find(player(), null) =&gt; 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) =&gt; 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') =&gt; 1 // removed diamond from player inventory
* inventory_remove(player(), 'diamond', 100) =&gt; 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) =&gt; 1 // Q's one item on the ground
* inventory_drop(x,y,z, 0) =&gt; 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') &lt;=&gt; p ~ 'name' // much shorter and cleaner
* query(p, 'holds', 'offhand') &lt;=&gt; 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 .
*/ */
+14 -11
View File
@@ -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() -&gt; ( * def() -&gt; (
* 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) =&gt; [20, 18, 16, 14, 12] * range(20, 10, -2) =&gt; [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) =&gt; 5 * get(l(range(10)), 5) =&gt; 5
* element(l(range(10)), -1) =&gt; 9 * get(l(range(10)), -1) =&gt; 9
* element(l(range(10)), 10) =&gt; 0 * get(l(range(10)), 10) =&gt; 0
* element(l(range(10)), 93) =&gt; 3 * get(l(range(10)), 93) =&gt; 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),
+1 -1
View File
@@ -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;