From 4f52a04d84b846c37b4f866d27e19b2d8dd97487 Mon Sep 17 00:00:00 2001
From: gnembon String with gamemode, or Good'ol gamemode id, or null if not a player. Player's permission level, or 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. If called with Sets if the entity obeys any collisions, including collisions with the terrain and basic physics.
+ * Not affecting players, since they are controlled client side Applies status effect to the living entity. Takes several optional parameters, which default to Sets AI to stay around the home position, within 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.null if not a player.
* query(e,'gamemode_id')
+ * query(e,'permission_level')null if not applicable for this entity.
* query(e,'effect',name?)
* modify(e, 'ai', boolean)false value, it will disable AI in the mob. true will enable it again.
+ * modify(e, 'no_clip', boolean)
+ * modify(e, 'effect', name, duration, amplifier?, show_particles?, show_icon?)0,
+ * true and true.
* modify(e, 'home', null), modify(e, 'home', block, distance?), modify(e, 'home', x, y, z, distance?)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)
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)