diff --git a/src/main/java/carpet/script/CarpetExpression.java b/src/main/java/carpet/script/CarpetExpression.java index 49467223..2ea87de9 100644 --- a/src/main/java/carpet/script/CarpetExpression.java +++ b/src/main/java/carpet/script/CarpetExpression.java @@ -1745,6 +1745,9 @@ public class CarpetExpression *
String with gamemode, or null if not a player.
query(e,'gamemode_id')Good'ol gamemode id, or null if not a player.
+ *query(e,'permission_level')Player's permission level, or null if not applicable for this entity.
query(e,'effect',name?)Without extra arguments, it returns list of effect active on a living entity. * Each entry is a triple of short effect name, amplifier, and remaining duration. @@ -1836,6 +1839,12 @@ public class CarpetExpression *
Make noises.
*modify(e, 'ai', boolean)If called with false value, it will disable AI in the mob. true will enable it again.
modify(e, 'no_clip', boolean)Sets if the entity obeys any collisions, including collisions with the terrain and basic physics. + * Not affecting players, since they are controlled client side
+ *modify(e, 'effect', name, duration, amplifier?, show_particles?, show_icon?)Applies status effect to the living entity. Takes several optional parameters, which default to 0,
+ * true and true.
modify(e, 'home', null), modify(e, 'home', block, distance?), modify(e, 'home', x, y, z, distance?)Sets AI to stay around the home position, within distance blocks from it. distance
* defaults to 16 blocks. null removes it. May not work fully with mobs that have this AI built in, like
@@ -2640,7 +2649,7 @@ public class CarpetExpression
*
load_app_data(), load_app_data(file)Loads the app data associated with the app from the world /scripts folder. Without argument returns the memory * managed and buffered / throttled NBT tag. With a file name - reads explicitly a file with that name from the scripts - * floder.
+ * folder. *You can use app data to save non-vanilla information separately from the world and other scripts.
*store_app_data(tag), store_app_data(tag, file)Stores the app data associated with the app from the world /scripts folder. With the file parameter
@@ -2665,6 +2674,25 @@ public class CarpetExpression
*
schedule(delay, function, args...)Schedules a user defined function to run with a specified delay ticks of delay.
* Scheduled functions run at the end of the tick, and they will run in order they were scheduled.
statistic(player, category, entry)Queries in-game statistics for certain values. Categories include:
+ *mined: blocks minedcrafted: items craftedused: items usedbroken: items brokenpicked_up: items picked updropped: items droppedkilled: mobs killedkilled_by: blocks minedcustom: various random statsFor the options of entry, consult your statistics page, or give it a guess.
The call will return null if the statistics options are incorrect, or player didn't get these
+ * in their history. If the player encountered the statisitic, or game created for him empty one, it will
+ * return a number. Scarpet will not affect the entries of the statistics, even if it is just creating empty ones.
+ * With null response it could either mean your input is wrone, or statistic has effectively
+ * a value of 0.
plop(pos, what)Plops a structure or a feature at a given pos, so block, triple position coordinates
* or a list of coordinates. To what gets plopped and exactly where it often depends on the
@@ -3010,12 +3038,12 @@ public class CarpetExpression
});
//"overidden" native call to cancel if on main thread
- this.expr.addLazyFunction("join_task", 1, (c, t, lv) -> {
+ this.expr.addLazyFunction("task_join", 1, (c, t, lv) -> {
if (((CarpetContext)c).s.getMinecraftServer().isOnThread())
- throw new InternalExpressionException("'join_task' cannot be called from main thread to avoid deadlocks");
+ throw new InternalExpressionException("'task_join' cannot be called from main thread to avoid deadlocks");
Value v = lv.get(0).evalValue(c);
if (!(v instanceof ThreadValue))
- throw new InternalExpressionException("'join_task' could only be used with a task value");
+ throw new InternalExpressionException("'task_join' could only be used with a task value");
Value ret = ((ThreadValue) v).join();
return (_c, _t) -> ret;
});
@@ -3483,7 +3511,11 @@ public class CarpetExpression
* should be running at startup. WARNING: all apps will run once at startup anyways, so be aware that their actions
* that are called statically, will be performed once anyways.
*
- *
Unloading an app removes all of its state from the game, disables commands, and removes bounded events
+ *Unloading an app removes all of its state from the game, disables commands, and removes bounded events,
+ * and saves its global state. If more
+ * cleanup is needed, one can define an __on_close() function which will be executed when the module is unloaded,
+ * or server is closing, or crashing. However, there is no need to do that explicitly for the things mentioned
+ * in the previous statement.
Scripts can be loaded in shared(global) and player mode. Default is player, so all globals and stored functions are * individual for each player, meaning scripts don't need to worry about making sure they store some intermittent data * for each player independently. In global mode - all global values and stored functions are shared among all players. @@ -3523,8 +3555,10 @@ public class CarpetExpression * __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_right_clicks_block(player, item_tuple, hand, block, face, hitvec) // player right clicks block with anything + * __on_player_interacts_with_block(player, hand, block, face, hitvec) //right click on a block resulted in activation of said block + * __on_player_places_block(player, item_tuple, hand, block) // player have just placed the block. * __on_player_interacts_with_entity(player, entity, hand) * __on_player_attacks_entity(player, entity) * __on_player_rides(player, forward, strafe, jumping, sneaking) @@ -3537,6 +3571,8 @@ public class CarpetExpression * __on_player_stops_sprinting(player) * __on_player_drops_item(player) * __on_player_drops_stack(player) + * + * __on_statistic(player, category, event, value) // player statistic changes * *
/script event commandused to display current events and bounded functions. use add_to ro register new event, or remove_from
diff --git a/src/main/java/carpet/script/Expression.java b/src/main/java/carpet/script/Expression.java
index 0bc27604..1aecd2a9 100644
--- a/src/main/java/carpet/script/Expression.java
+++ b/src/main/java/carpet/script/Expression.java
@@ -60,7 +60,7 @@ import static java.lang.Math.min;
/**
- *
scarpet programming language (version 1.6).scarpet programming language (towards version 1.7).Scarpet (a.k.a. Carpet Script, or Script for Carpet) is a programming language designed to provide * the ability to write custom programs to run within Minecraft and @@ -2613,6 +2613,59 @@ public class Expression implements Cloneable * * *
Scarpet allows to run threads of execution in parallel to the main script execution thread. In Minecraft, the main
+ * thread scripts are executed on the main server thread. Since Minecraft is inherently NOT thread safe, it is not that
+ * beneficial to parallel execution in order to access world resources faster. Both
+ * GetBlockState and setBlockState are not thread safe and require the execution to park on the server thread,
+ * where these requests can be executed in the off-tick time in between ticks that didn't take 50ms. There are however
+ * benefits of running things in parallel, like fine time control not relying on the tick clock, or running things independent
+ * on each other. You can still run your actions on tick-by-tick basis, either taking control of the execution using
+ * game_tick() API function (nasty solution), or scheduling tick using schedule() function (much nicer solution),
+ * but threading often gives the neatest solution to solve problems in parallel (see scarpet camera).
+ *
Due to limitations with the game, there are some limits to the threading as well. You cannot for instance join_task() at all
+ * from the main script and server thread, because any use of Minecraft specific function that require any world access, will
+ * require to park and join on the main thread to get world access, meaning that calling join on that task would inevitably lead to a
+ * typical deadlock. You can still join tasks from other threads, just because the only possibility of a deadlock in this case would
+ * come explicitly from your bad code, not the internal world access behaviour. Some things tough like player or entity manipulation,
+ * can be effectively parallelized.
task(function, ?args...., ?executor)Creates and runs a parallel task, returning the handle to the task object. Task will return the return value of the function
+ * when its completed, or will return null immediately if task is still in progress, so grabbing a value of
+ * a task object is non-blocking. Function can be either function value, or function lambda, or a name of an existing defined function.
+ * In case function needs arguments to be called with, they should be supplied after the function name, or value.
+ * Optional executor identifier is to place the task in a specific queue identified by this value. The default
+ * thread value is the null thread. There is no limits on number of parallel tasks for any executor, so using different queues is solely
+ * for synchronization purposes. Also, since task function knows how many extra arguments it requires, the use of
+ * tailing optional parameter for the custom executor thread pool is not ambiguous.
+ *
+ * task( _() -> print('Hello Other World') ) => Runs print command on a separate thread
+ * foo(a, b) -> print(a+b); task('foo',2,2) => Uses existing function definition to start a task
+ * task('foo',3,5,'temp'); => runs function foo with a different thread executor, identified as 'temp'
+ * a = 3; task( _(outer(a), b) -> foo(a,b), 5, 'temp') => Another example of running the same thing passing arguments using closure over anonymous function as well as passing a parameter.
+ *
+ * task_count(executor?)If no argument provided, returns total number of tasks being executed in parallel at this moment using scarpet threading system.
+ * If the executor is provided, returns number of active tasks for that provider. Use task_count(null) to
+ * get the task count of the default executor only.
task_value(task)Returns the task return value, or null if task hasn't finished yet. Its a non-blocking operation.
+ * Unlike join_task, can be called on any task at any point
task_join(task)Waits for the task completion and returns its computed value. If the task has already finished returns it immediately.
+ * Unless taking the task value directly, i.e. via task_value, this operation is blocking. Since Minecraft has
+ * a limitation that all world access operations have to be performed on the main game thread in the off-tick time, joining any tasks that use
+ * Minecraft API from the main thread would mean automatic lock, so joining from the main thread is not allowed.
+ * Join tasks from other threads, if you really need to, or communicate asynchronously with the task via globals or
+ * function data / arguments to monitor its progress, communicate, get partial results, or signal termination.
task_completed(task)Returns true if task has completed, or false otherwise.
+ * *lower(expr), upper(expr), title(expr)