diff --git a/src/main/java/carpet/script/CarpetEventServer.java b/src/main/java/carpet/script/CarpetEventServer.java
index c68e9960..b1f0016c 100644
--- a/src/main/java/carpet/script/CarpetEventServer.java
+++ b/src/main/java/carpet/script/CarpetEventServer.java
@@ -327,7 +327,7 @@ public class CarpetEventServer
}
},
- PLAYER_RELEASED_ITEM("player_released_item",new CallbackList(3))
+ PLAYER_RELEASED_ITEM("player_releases_item",new CallbackList(3))
{
@Override
public void onItemAction(ServerPlayerEntity player, Hand enumhand, ItemStack itemstack)
@@ -343,7 +343,7 @@ public class CarpetEventServer
}, player::getCommandSource);
}
},
- PLAYER_FINISHED_USING_ITEM("player_finished_using_item",new CallbackList(3))
+ PLAYER_FINISHED_USING_ITEM("player_finishes_using_item",new CallbackList(3))
{
public void onItemAction(ServerPlayerEntity player, Hand enumhand, ItemStack itemstack)
{
diff --git a/src/main/java/carpet/script/CarpetExpression.java b/src/main/java/carpet/script/CarpetExpression.java
index dacd3d24..db6a5a70 100644
--- a/src/main/java/carpet/script/CarpetExpression.java
+++ b/src/main/java/carpet/script/CarpetExpression.java
@@ -1542,9 +1542,9 @@ public class CarpetExpression
* that corresponds to the path. For specification of path attribute, consult
* vanilla /data get entity command.
Note that calls to nbt are considerably more expensive comparing to other
- * calls in Minecraft API, and should only be used when there is no other option.A returned value is of type nbt,
+ * calls in Minecraft API, and should only be used when there is no other option. Returned value is of type nbt,
* which can be further manipulated with nbt type objects via get, put, has, delete, so try to use API calls
- * first
Like with entity querying, entity modifications happen through one function. Most position and movements * modifications don't work currently on players as their position is controlled by clients.
@@ -3080,22 +3080,25 @@ public class CarpetExpression * *Here is a list of events that can be handled by scarpet. This list includes prefixes required by modules to - * autoload them, but you can add any function to any event if it had required parameters:
+ * autoload them, but you can add any function to any event if it accepts required number of parameters: *
* __on_tick() // can access blocks and entities in the overworld
* __on_tick_nether() // can access blocks and entities in the nether
* __on_tick_ender() // can access blocks and entities in the end
+ *
* // player specific callbacks
+ * __on_player_uses_item(player, item_tuple, hand) // right click action
+ * __on_player_releases_item(player, item_tuple, hand) // client action (e.g. bow)
+ * __on_player_finishes_using_item(player, item_tuple, hand)) // server action (e.g. food), called item is from before it is used.
+ * __on_player_clicks_block(player, block, face) // left click attack on a block
+ * __on_player_right_clicks_block(player, item_tuple, hand, block, face, hitvec)
+ * __on_player_breaks_block(player, block) // called after block is broken (the caller receives previous blockstate)
+ * __on_player_interacts_with_entity(player, entity, hand)
+ * __on_player_attacks_entity(player, entity)
+ * __on_player_rides(player, forward, strafe, jumping, sneaking)
* __on_player_jumps(player)
* __on_player_deploys_elytra(player)
* __on_player_wakes_up(player)
- * __on_player_rides(player, forward, strafe, jumping, sneaking)
- * __on_player_uses_item(player, item_tuple, hand)
- * __on_player_clicks_block(player, block, face)
- * __on_player_right_clicks_block(player, item_tuple, hand, block, face, hitvec)
- * __on_player_breaks_block(player, block)
- * __on_player_interacts_with_entity(player, entity, hand)
- * __on_player_attacks_entity(player, entity)
* __on_player_starts_sneaking(player)
* __on_player_stops_sneaking(player)
* __on_player_starts_sprinting(player)
@@ -3103,7 +3106,10 @@ public class CarpetExpression
*
* /script event commandused to display current events and bounded functions. use add_to ro register new event, or remove_from
- * to unbind a specific function from an event.
/script load that have functions listed above will be automatically bounded and unbounded when
+ * script is unloaded.
*
*/
public void gameEventsSystem()
diff --git a/src/main/java/carpet/script/Expression.java b/src/main/java/carpet/script/Expression.java
index e1d3ce48..44fb59a3 100644
--- a/src/main/java/carpet/script/Expression.java
+++ b/src/main/java/carpet/script/Expression.java
@@ -366,29 +366,6 @@ public class Expression implements Cloneable
private Map
- * Here is the complete list of operators in scarpet including control flow operators.
- * note, that commas and brackets are not operators, but behave like them:
- *
~ .+ - !^* / %+ -== != > >= <= <&&||= += <>->;,( )scarpet including control flow operators.
+ * Note, that commas and brackets are not technically operators, but part of the language,
+ * even if they look like them:
+ *
+ * ~ .+ - !^* / %+ -== != > >= <= <&&||= += <>->;,( )Get, Accessor Operator .Operator version of the get(...) function to access elements of lists, maps, and potentially other
+ * containers (i.e. NBTs). It is important to distinguish from ~ operator, which is a matching operator,
+ * which is expected to perform some extra computations to retrieve the result, while . should be
+ * straightforward and immediate, and the source object should behave like a container and support full container
+ * API, meaning get(...), put(...), delete(...),
+ * and has(...) functions
Matching Operator ~This operator should be understood as 'matches', 'contains', 'is_in',
+ * or 'find me some stuff about something else. For strings it matches the right operand as a regular
+ * expression to the left, returning the first match. This can be used to extract information from unparsed nbt's
+ * in a more convoluted way (use get(...) for more appropriate way of doing it).
+ * For lists it checks if an element is in the list, and returns the index of that element,
+ * or null if no such element was found, especially that the use of first(...) function will not
+ * return the index. Currently it doesn't have any special behaviour for numbers - it checks for existence of characters
+ * in string representation of the left operand with respect of the regular expression on the right hand side.
+ * string
in Minecraft API portion entity ~ feature is a shortcode for query(entity,feature)
+ * for queries that do not take any extra arguments.
+ * l(1,2,3) ~ 2 => 1
+ * l(1,2,3) ~ 4 => null
+ * 'foobar' ~ '.b' => 'ob'
+ * player('*') ~ 'gnembon' // null unless player gnembon is logged in (better to use player('gnembon') instead
+ * p ~ 'sneaking' // if p is an entity returns whether p is sneaking
+ *
+ * Or a longer example of an ineffective way to searching for a squid
+ *
+ * entities = entities_area('all',x,y,z,100,10,100);
+ * sid = entities ~ 'Squid';
+ * if(sid != null, run('execute as '+query(get(entities,sid),'id')+' run say I am here '+query(get(entities,sid),'pos') ) )
+ *
+ * Or an example to find if a player has specific enchantment on a held axe (either hand) and get its level
+ * (not using proper NBTs query support via get(...)):
+ * global_get_enchantment(p, ench) -> (
+ * $ for(l('main','offhand'),
+ * $ holds = query(p, 'holds', _);
+ * $ if( holds,
+ * $ l(what, count, nbt) = holds;
+ * $ if( what ~ '_axe' && nbt ~ ench,
+ * $ lvl = max(lvl, number(nbt ~ '(?<=lvl:)\\d') )
+ * $ )
+ * $ )
+ * $ );
+ * $ lvl
+ * $);
+ * /script run global_get_enchantment(players(), 'sharpness')
+ *
*
* Basic Arithmetic Operators + - * /Allows to add the results of two expressions. If the operands resolve to numbers, the result is @@ -1145,52 +1175,7 @@ public class Expression implements Cloneable * null != false && run('kill gnembon') => 1 // gnembon dies, cheats allowed * * - *
Get, Accessor Operator .Operator version of the get(...) function to access elements of lists, nbts, and potentially other
- * containers. It is important to distinguish from ~ operator, which is a matching operator, meaning it
- * is expected to perform some extra computations to retrieve the result, while . should be
- * straightforward and immediate.
Matching Operator ~This operator should be understood as 'matches', 'contains' or 'is_in'. For strings it matches the right operand as a regular
- * expression to the left one, returning the first match. This can be used to extract information from unparsed nbt's
- * in a more efficient way. For lists it checks if an element is in the list, and returns the index of that element,
- * or null if no such element was found, especially that the use of first function will not
- * return the index. Currently it doesn't have any special behaviour for numbers - it checks for existence of characters
- * in string representation of the left operand with respect of the regular expression on the right hand side.
- * string
in Minecraft API portion entity ~ feature is a shortcode for query(entity,feature)
- * for queries that do not take any extra arguments.
- * l(1,2,3) ~ 2 => 1
- * l(1,2,3) ~ 4 => null
- * 'foobar' ~ '.b' => 'ob'
- * player('*') ~ 'gnembon' // null unless player gnembon is logged in (better to use player('gnembon') instead
- * p ~ 'sneaking' // if p is an entity returns whether p is sneaking
- *
- * Or a longer example of an ineffective way to searching for a squid
- *
- * entities = entities_area('all',x,y,z,100,10,100);
- * sid = entities ~ 'Squid';
- * if(sid != null, run('execute as '+query(get(entities,sid),'id')+' run say I am here '+query(get(entities,sid),'pos') ) )
- *
- * Or an example to find if a player has specific enchantment on a held axe (either hand) and get its level - * (despite obvious lack of support for json NBT's):
- *
- * global_get_enchantment(p, ench) -> (
- * $ for(l('main','offhand'),
- * $ holds = query(p, 'holds', _);
- * $ if( holds,
- * $ l(what, count, nbt) = holds;
- * $ if( what ~ '_axe' && nbt ~ ench,
- * $ lvl = max(lvl, number(nbt ~ '(?<=lvl:)\\d') )
- * $ )
- * $ )
- * $ );
- * $ lvl
- * $);
- * /script run global_get_enchantment(players(), 'sharpness')
- *
+
* Assignment Operators = <> +=A set of assignment operators. All require bounded variable on the LHS, <> requires
* bounded arguments on the right hand side as well (bounded, meaning being variables). Additionally they can also
@@ -1569,118 +1554,22 @@ public class Expression implements Cloneable
}
/**
- *
Efficient use of these functions cangreatly simplify your programs and speed them up, as these functions - * will internalize most of the operations that need to be applied on multiple values at the same time
- *l(values ...), l(iterator) Creates a list of values of the expressions passed as parameters. It can be used as an L-value and if all
- * elements are variables, you coujld use it to return multiple results from one function call, if that function returns
- * a list of results with the same size as the l call uses. In case there is only one argument and it is
- * an iterator (vanilla expression specification has range, but Minecraft API implements
- * a bunch of them, like diamond), it will convert it to a proper list. Iterators can only be used in
- * high order functions, and are treated as empty lists, unless unrolled with l
Efficient use of these functions can greatly simplify your programs and speed them up, as these functions + * will internalize most of the operations that need to be applied on multiple values at the same time
+ *for(list,expr(_,_i),exit(_,_i)?)Evaluates expression over list of items from the list, and can optionally stop early if
+ * exit expression is specified and evaluates true for a given iteration. Supplies
+ * _(value) and _i(iteration number) to both expr and exit.
+ * Returns the number of times expr was successful
- * l(1,2,'foo') => [1, 2, foo] - * l() => [] (empty list) - * l(range(10)) => [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] - * l(1, 2) = l(3, 4) => Error: l is not a variable - * l(foo, bar) = l(3,4); foo==3 && bar==4 => 1 - * l(foo, bar, baz) = l(2, 4, 6); l(min(foo, bar), baz) = l(3, 5); l(foo, bar, baz) => [3, 4, 5] - *- *
In the last example l(min(foo, bar), baz) creates a valid L-value, as min(foo, bar) finds the
- * lower of the variables (in this case foo) creating a valid assignable L-list of [foo, baz], and these
- * values will be assigned new values
join(delim, list), join(delim, values ...) Returns a string that contains joined elements of the list, iterator, or all values, concatenated with delim delimiter
- * join('-',range(10)) => 0-1-2-3-4-5-6-7-8-9
- * join('-','foo') => foo
- * join('-', 'foo', 'bar') => foo-bar
- *
- *
- * split(delim, expr)Splits a string undr expr by delim which can be a regular expression
- * split('',foo) => [f, o, o]
- * split('.','foo.bar') => []
- * split('\\.','foo.bar') => [foo, bar]
- *
- *
- * slice(expr, from, to?)extracts a substring, or sublist (based on the type of the result of the expression under expr with starting index
- * of from, and ending at to if provided, or the end, if omitted
- * slice(l(0,1,2,3,4,5), 1, 3) => [1, 2, 3]
- * slice('foobar', 0, 1) => 'f'
- * slice('foobar', 3) => 'bar'
- * slice(range(10), 3, 5) => [3, 4, 5]
- * slice(range(10), 5) => [5, 6, 7, 8, 9]
- *
- *
- *
- *
- * sort(list), sort(values ...) Sorts in the default sortographical order either all arguments, or a list if its the only argument. It returns a new - * sorted list, not affecting the list passed to the argument
- *
- * sort(3,2,1) => [1, 2, 3]
- * sort('a',3,11,1) => [1, 3, 11, 'a']
- * list = l(4,3,2,1); sort(list) => [1, 2, 3, 4]
- *
- *
- * sort_key(list, key_expr)Sorts a copy of the list in the order or keys as defined by the key_expr for each element
- * sort_key([1,3,2],_) => [1, 2, 3] - * sort_key([1,3,2],-_) => [3, 2, 1] - * sort_key(l(range(10)),rand(1)) => [1, 0, 9, 6, 8, 2, 4, 5, 7, 3] - * sort_key(l(range(20)),str(_)) => [0, 1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 2, 3, 4, 5, 6, 7, 8, 9] - *- * - *
range(to), range(from, to), range(from, to, step)Creates a range of numbers from from, no greater/larger than to.
- * The step parameter dictates not only the increment size, but also direction (can be negative).
- * The returned value is not a proper list, just the iterator
- * but if for whatever reason you need a proper list with all items evaluated, use l(range(to)).
- * Primarily to be used in higher order functions
- * range(10) => [...] - * l(range(10)) => [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] - * map(range(10),_*_) => [0, 1, 4, 9, 16, 25, 36, 49, 64, 81] - * reduce(range(10),_a+_, 0) => 45 - * range(5,10) => [5, 6, 7, 8, 9] - * range(20, 10, -2) => [20, 18, 16, 14, 12] - *- * - *
get(value, address), element(value, address)(deprecated)Returns the value at address element from the value.
- * For lists it indicates an index, use negative numbers to reach elements from the end of the list. get
- * call will always be able to find the index. In case there is few items, it will loop over
[Minecraft specific usecase]: In case value is of nbt type, uses addess as the nbt path to query,
- * returning null, if path is not found, one value if there was one match, or list of values if result is a list.
- * Returned elements can be of numerical type, string texts, or another compound nbt tags
- * get(l(range(10)), 5) => 5 - * get(l(range(10)), -1) => 9 - * get(l(range(10)), 10) => 0 - * get(l(range(10)), 93) => 3 - * get(player() ~ 'nbt', 'Health') => 20 // inefficient way to get player health - *- * - *
put(list, index, values ...), put(list, null, values ...)Modifies the list by replacing values starting from index with values.
- * use negative numbers to reach elements from the end of the list. put
- * call will always be able to find the index. In case there is few items, it will loop over. In case end
- * of the list is reached before values run out, list is extended to accomodate for more values. in case you
- * want to append at the end of the list, use null as index. returns number of elements inserted.
- * a = l(1, 2, 3); put(a, 1, 4); a => [1, 4, 3]
- * a = l(1, 2, 3); put(a, null, 4, 5, 6); a => [1, 2, 3, 4, 5, 6]
- * a = l(l(0,0,0),l(0,0,0),l(0,0,0)); put(element(a, 1), 1, 1); a => [[0, 0, 0], [0, 1, 0], [0, 0, 0]]
+ * check_prime(n) -> !first( range(2, sqrt(n)+1), !(n % _) );
+ * for(range(1000000,1100000),check_prime(_)) => 7216
*
+ * From which we can learn that there is 7216 primes between 1M and 1.1M
*while(cond, limit, expr)Evaluates expression expr repeatedly until condition cond becomes false,
* but not more than limit times. Returns the result of the last expr evaluation,
@@ -1710,6 +1599,7 @@ public class Expression implements Cloneable
*
* // outputs: [0, 1, 2, 3, 5, 7, 11, 13, 17, 19]
*
+ *
map(list,expr(_,_i), exit(_,_i)?)Converts a list of values, to another list where each value is result of an expression
* v = expr(_, _i) where _ is passed as each element of the list, and _i is
@@ -1754,17 +1644,6 @@ public class Expression implements Cloneable
* // ditto, but requiring at most 7 bedrock block in the 18 blocks below them
*
*
- *
- *
for(list,expr(_,_i),exit(_,_i)?)Evaluates expression over list of items from the list, and can optionally stop early if
- * exit expression is specified and evaluates true for a given iteration. Supplies
- * _(value) and _i(iteration number) to both expr and exit.
- * Returns the number of times expr was successful
- * check_prime(n) -> !first( range(2, sqrt(n)+1), !(n % _) ); - * for(range(1000000,1100000),check_prime(_)) => 7216 - *- *
From which we can learn that there is 7216 primes between 1M and 1.1M
*reduce(list,expr(_a,_,_i), initial)Applies expr for each element of the list and saves the result in _a accumulator.
* Consecutive calls to expr can access that value to apply more values. You also need to specify
@@ -1775,196 +1654,9 @@ public class Expression implements Cloneable
*
*
Scarpet supports basic container types: lists and maps (aka hashmaps, dicts etc..)
+ *Here is a list of operations that work on all types of containers: lists, maps, as well as other Minecraft + * specific modifyable containers, like NBTs
+ * + *get(container, address), '.' operatorReturns the value at address element from the value.
+ * For lists it indicates an index, use negative numbers to reach elements from the end of the list. get
+ * call will always be able to find the index. In case there is few items, it will loop over
for maps, retrieves the value under the key specified in the address or null otherwise
[Minecraft specific usecase]: In case value is of nbt type, uses address as the
+ * nbt path to query,
+ * returning null, if path is not found, one value if there was one match, or list of values if result is a list.
+ * Returned elements can be of numerical type, string texts, or another compound nbt tags
+ * get(l(range(10)), 5) => 5
+ * get(l(range(10)), -1) => 9
+ * get(l(range(10)), 10) => 0
+ * l(range(10)).93 => 3
+ *
+ * get(player() ~ 'nbt', 'Health') => 20 // inefficient way to get player health, use player() ~ 'health' instead
+ *
+ * get(m( l('foo',2), l('bar',3), l('baz',4) ), 'bar') => 3
+ *
+ *
+ * has(container, address)Similar to get, but returns boolean value indicating if the given index / key / path is in the
+ * container. Can be used to determine if get(...)==null means the element doesn't exist, or the stored value
+ * for this address is null.
delete(container, address)Removes specific entry from the container. For the lists - removes the element and shrinks it. For maps, it + * removes the key from the map, and for nbt - removes content from a given path. For lists and maps returns previous + * entry at the address, for nbt's - number of removed objects.
+ * + * + *put(list, index, values ...), put(list, null, values ...)Modifies the list by replacing values starting from index with values.
+ * use negative numbers to reach elements from the end of the list. put
+ * call will always be able to find the index. In case there is few items, it will loop over. In case end
+ * of the list is reached before values run out, list is extended to accomodate for more values. in case you
+ * want to append at the end of the list, use null as index. returns number of elements inserted.
+ * a = l(1, 2, 3); put(a, 1, 4); a => [1, 4, 3] + * a = l(1, 2, 3); put(a, null, 4, 5, 6); a => [1, 2, 3, 4, 5, 6] + * a = l(l(0,0,0),l(0,0,0),l(0,0,0)); put(element(a, 1), 1, 1); a => [[0, 0, 0], [0, 1, 0], [0, 0, 0]] + *+ * + *
l(values ...), l(iterator) Creates a list of values of the expressions passed as parameters. It can be used as an L-value and if all
+ * elements are variables, you coujld use it to return multiple results from one function call, if that function returns
+ * a list of results with the same size as the l call uses. In case there is only one argument and it is
+ * an iterator (vanilla expression specification has range, but Minecraft API implements
+ * a bunch of them, like diamond), it will convert it to a proper list. Iterators can only be used in
+ * high order functions, and are treated as empty lists, unless unrolled with l
+ * l(1,2,'foo') => [1, 2, foo] + * l() => [] (empty list) + * l(range(10)) => [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] + * l(1, 2) = l(3, 4) => Error: l is not a variable + * l(foo, bar) = l(3,4); foo==3 && bar==4 => 1 + * l(foo, bar, baz) = l(2, 4, 6); l(min(foo, bar), baz) = l(3, 5); l(foo, bar, baz) => [3, 4, 5] + *+ *
In the last example l(min(foo, bar), baz) creates a valid L-value, as min(foo, bar) finds the
+ * lower of the variables (in this case foo) creating a valid assignable L-list of [foo, baz], and these
+ * values will be assigned new values
join(delim, list), join(delim, values ...) Returns a string that contains joined elements of the list, iterator, or all values, concatenated with delim delimiter
+ * join('-',range(10)) => 0-1-2-3-4-5-6-7-8-9
+ * join('-','foo') => foo
+ * join('-', 'foo', 'bar') => foo-bar
+ *
+ *
+ * split(delim, expr)Splits a string undr expr by delim which can be a regular expression
+ * split('',foo) => [f, o, o]
+ * split('.','foo.bar') => []
+ * split('\\.','foo.bar') => [foo, bar]
+ *
+ *
+ * slice(expr, from, to?)extracts a substring, or sublist (based on the type of the result of the expression under expr with starting index
+ * of from, and ending at to if provided, or the end, if omitted
+ * slice(l(0,1,2,3,4,5), 1, 3) => [1, 2, 3]
+ * slice('foobar', 0, 1) => 'f'
+ * slice('foobar', 3) => 'bar'
+ * slice(range(10), 3, 5) => [3, 4, 5]
+ * slice(range(10), 5) => [5, 6, 7, 8, 9]
+ *
+ *
+ * sort(list), sort(values ...) Sorts in the default sortographical order either all arguments, or a list if its the only argument. It returns a new + * sorted list, not affecting the list passed to the argument
+ *
+ * sort(3,2,1) => [1, 2, 3]
+ * sort('a',3,11,1) => [1, 3, 11, 'a']
+ * list = l(4,3,2,1); sort(list) => [1, 2, 3, 4]
+ *
+ *
+ * sort_key(list, key_expr)Sorts a copy of the list in the order or keys as defined by the key_expr for each element
+ * sort_key([1,3,2],_) => [1, 2, 3] + * sort_key([1,3,2],-_) => [3, 2, 1] + * sort_key(l(range(10)),rand(1)) => [1, 0, 9, 6, 8, 2, 4, 5, 7, 3] + * sort_key(l(range(20)),str(_)) => [0, 1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 2, 3, 4, 5, 6, 7, 8, 9] + *+ * + *
range(to), range(from, to), range(from, to, step)Creates a range of numbers from from, no greater/larger than to.
+ * The step parameter dictates not only the increment size, but also direction (can be negative).
+ * The returned value is not a proper list, just the iterator
+ * but if for whatever reason you need a proper list with all items evaluated, use l(range(to)).
+ * Primarily to be used in higher order functions
+ * range(10) => [...] + * l(range(10)) => [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] + * map(range(10),_*_) => [0, 1, 4, 9, 16, 25, 36, 49, 64, 81] + * reduce(range(10),_a+_, 0) => 45 + * range(5,10) => [5, 6, 7, 8, 9] + * range(20, 10, -2) => [20, 18, 16, 14, 12] + *+ * + *
element(list, index)(deprecated)Legacy support for older method that worked only on lists. Please use get(...) for equivalent
+ * support, or . operator. Also previous unique behaviours with put on lists has been
+ * removed to support all type of container types.
Scarpet supports map structures, aka hashmaps, dicts etc. Map structure can also be used, with null
+ * values as sets. Apart from container access functions, (. , get, put, has, delete),
+ * the following functions: