diff --git a/docs/scarpet/Full.md b/docs/scarpet/Full.md index 97fccb91..c07aaba4 100644 --- a/docs/scarpet/Full.md +++ b/docs/scarpet/Full.md @@ -790,6 +790,18 @@ Returns true if task has completed, or false otherwise. Evaluates `expression` synchronized with respect to the lock `lock`. Returns the value of the expression. +### `task_dock(expr)` + +In a not-task (running regular code on the main game thread) it is a pass-through command. In tasks - it docks +the current thread on the main server thread and executes expression as one server offline server task. +This is especially helpful in case a task has several docking operations to perform, such as setting a block, and +it would be much more efficient to do them all at once rather then packing each block access in each own call. + +Be mindful, that docking the task means that the tick execution will be delayed until the expression is evaluated. +This will synchronize your task with other tasks using `task_dock`, but if you should be using `synchronize` to +synchronize tasks without locking the main thread. + + * * * ## Auxiliary functions diff --git a/docs/scarpet/language/SystemFunctions.md b/docs/scarpet/language/SystemFunctions.md index 611057d2..7c506921 100644 --- a/docs/scarpet/language/SystemFunctions.md +++ b/docs/scarpet/language/SystemFunctions.md @@ -147,6 +147,18 @@ Returns true if task has completed, or false otherwise. Evaluates `expression` synchronized with respect to the lock `lock`. Returns the value of the expression. +### `task_dock(expr)` + +In a not-task (running regular code on the main game thread) it is a pass-through command. In tasks - it docks +the current thread on the main server thread and executes expression as one server offline server task. +This is especially helpful in case a task has several docking operations to perform, such as setting a block, and +it would be much more efficient to do them all at once rather then packing each block access in each own call. + +Be mindful, that docking the task means that the tick execution will be delayed until the expression is evaluated. +This will synchronize your task with other tasks using `task_dock`, but if you should be using `synchronize` to +synchronize tasks without locking the main thread. + + * * * ## Auxiliary functions diff --git a/docs/scarpet/resources/editors/idea/1.txt b/docs/scarpet/resources/editors/idea/1.txt index fcab9dfb..8780d3f9 100644 --- a/docs/scarpet/resources/editors/idea/1.txt +++ b/docs/scarpet/resources/editors/idea/1.txt @@ -85,6 +85,7 @@ tanh task task_completed task_count +task_dock task_join task_value throw diff --git a/docs/scarpet/resources/editors/npp/scarpet.xml b/docs/scarpet/resources/editors/npp/scarpet.xml index 3994ced4..cfcde776 100644 --- a/docs/scarpet/resources/editors/npp/scarpet.xml +++ b/docs/scarpet/resources/editors/npp/scarpet.xml @@ -36,7 +36,7 @@ print return exit throw try - task task_count task_value task_join task_completed synchronize + task task_count task_value task_join task_completed synchronize task_dock system_variable_get system_variable_set diff --git a/src/main/java/carpet/script/CarpetExpression.java b/src/main/java/carpet/script/CarpetExpression.java index 76c19de9..06bded9a 100644 --- a/src/main/java/carpet/script/CarpetExpression.java +++ b/src/main/java/carpet/script/CarpetExpression.java @@ -2791,6 +2791,18 @@ public class CarpetExpression return (_c, _t) -> ret; }); + this.expr.addLazyFunction("task_dock", 1, (c, t, lv) -> { + CarpetContext cc = (CarpetContext)c; + MinecraftServer server = cc.s.getMinecraftServer(); + if (server.isOnThread()) return lv.get(1); // pass through for on thread tasks + Value[] result = new Value[]{Value.NULL}; + ((CarpetContext) c).s.getMinecraftServer().submitAndJoin(() -> result[0] = lv.get(0).evalValue(c, t)); + Value ret = result[0]; // preventing from lazy evaluating of the result in case a future completes later + return (_c, _t) -> ret; + // pass through placeholder + // implmenetation should dock the task on the main thread. + }); + this.expr.addLazyFunction("logger", 1, (c, t, lv) -> { Value res = lv.get(0).evalValue(c); @@ -2976,29 +2988,6 @@ public class CarpetExpression delay ); return (c_, t_) -> Value.TRUE; - /* - Value functionValue = lv.get(1).evalValue(c); - if (!(functionValue instanceof FunctionValue)) - { - String name = functionValue.getString(); - functionValue = c.host.getAssertFunction(this.expr.module, name); - } - FunctionValue function = (FunctionValue)functionValue; - - CarpetContext cc = (CarpetContext)c; - List args = new ArrayList<>(); - for (int i=2; i < lv.size(); i++) - { - Value arg = lv.get(i).evalValue(cc); - args.add(arg); - } - if (function.getArguments().size() != args.size()) - throw new InternalExpressionException("Function "+function.getString()+" takes "+ - function.getArguments().size()+" arguments, "+args.size()+" provided."); - CarpetServer.scriptServer.events.scheduleCall(cc, function, args, delay); - return (c_, t_) -> Value.TRUE; - */ - }); this.expr.addLazyFunction("load_app_data", -1, (c, t, lv) -> diff --git a/src/main/java/carpet/script/Expression.java b/src/main/java/carpet/script/Expression.java index 17e5d331..83e607fe 100644 --- a/src/main/java/carpet/script/Expression.java +++ b/src/main/java/carpet/script/Expression.java @@ -444,23 +444,6 @@ public class Expression FunctionValue fun = functionArgument.function; Value retval = fun.callInContext(expr, c, t, fun.getExpression(), fun.getToken(), functionArgument.args).evalValue(c); return (cc, tt) -> retval; ///!!!! dono might need to store expr and token in statics? (e? t?) - - /* - Value functionValue = lv.get(0).evalValue(c); - if (!(functionValue instanceof FunctionValue)) - { - String name = functionValue.getString(); - functionValue = c.host.getAssertFunction(module, name); - } - List lvargs = new ArrayList<>(lv.size()-1); - for (int i=1; i< lv.size(); i++) - { - lvargs.add(lv.get(i)); - } - FunctionValue fun = (FunctionValue)functionValue; - Value retval = fun.callInContext(expr, c, t, fun.getExpression(), fun.getToken(), lvargs).evalValue(c); - return (cc, tt) -> retval; ///!!!! dono might need to store expr and token in statics? (e? t?) - */ } // gimme signature String name = lv.get(0).evalValue(c).getString(); @@ -1884,29 +1867,6 @@ public class Expression ThreadValue thread = new ThreadValue(queue, functionArgument.function, expr, tok, c, functionArgument.args); Thread.yield(); return (cc, tt) -> thread; - /* - Value funcDesc = lv.get(0).evalValue(c); - if (!(funcDesc instanceof FunctionValue)) - { - String name = funcDesc.getString(); - funcDesc = c.host.getAssertFunction(module, name); - } - FunctionValue fun = (FunctionValue)funcDesc; - int extraargs = lv.size() - fun.getArguments().size(); - if (extraargs != 1 && extraargs != 2) - { - throw new InternalExpressionException("Function takes "+fun.getArguments().size()+" arguments."); - } - List lvargs = new ArrayList<>(); - for (int i=0; i< fun.getArguments().size(); i++) - { - lvargs.add(lv.get(i+1)); - } - Value queue = Value.NULL; - if (extraargs == 2) queue = lv.get(lv.size()-1).evalValue(c); - ThreadValue thread = new ThreadValue(queue, fun, expr, tok, c, lvargs); - Thread.yield(); - return (cc, tt) -> thread;*/ }); addFunction("task_count", (lv) -> @@ -1930,6 +1890,12 @@ public class Expression return ((ThreadValue) v).join(); }); + addLazyFunction("task_dock", 1, (c, t, lv) -> { + // pass through placeholder + // implmenetation should dock the task on the main thread. + return lv.get(0); + }); + addUnaryFunction("task_completed", (v) -> { if (!(v instanceof ThreadValue)) throw new InternalExpressionException("'task_completed' could only be used with a task value");