Description
Preface: these features are based on things available in similar "beginner" programming tools (like Scratch and action-workflow systems), they're designed to make it simple to do tasks that, while already possible, are either very complicated or currently dangerous if done wrongly.
The do
section
The do
section is (in simplest terms) a section of executable code, and the user is able to control how and when it is run.
This is designed to be similar to Java's CompletableFuture
system, allowing control of how and when sections are executed.
This is designed to be simple and clear, easy to use and understand. It should look a bit like an if/else if/else
block.
The main parts
Syntax | Explanation |
---|---|
do [async]: |
Runs the code inside. If specified async, this is not run on the main thread. |
and do [async]: |
Starts running at the same time as the do block before it if possible, requiring one to be a do async block. If neither are async, it runs one and then the other. |
then do [async]: |
Starts running after the previous block completes, allowing for easy execution of code upon completion of a delayed task. |
finally: |
This is run once all previous blocks have completed. |
Examples
This allows you to make slow, otherwise-blocking requests in the background.
An addon developer doesn't have to worry about getting their expression or effect to work asynchronously because the Skript user can handle this for them.
on join:
do async:
set {_location} to # retrieve player location from database
set {_name} to # retrieve nickname from web URL
# other slow tasks
then do: # run normally on the main thread once the previous block has completed
teleport player to {_location}
set player's display name to {_name}
This allows you to compute and execute things efficiently.
In this example, doing the two async requests sequentially would take longer than doing them both at the same time, and the finally
block allows you to continue your code as soon as both are done.
on join:
do async:
set {_a} to # async web request syntax
and do async: # done at same time as previous
set {_b} to # async web request syntax
finally: # done once both are completed
if {_a} is true:
if {_b} is true:
kick player
This example shows how the user can do extensive or repeated calculations or slow loops without risking lag spikes or TPS drops.
on join:
do async:
loop 10000 times:
# imagine a slow maths expression here :)
finally:
# do something with the result
This is a full example of all the possible sections. Their usage should be fairly obvious, but just to make it explicit:
do: # starts first, on main thread
do async: # starts first, on another thread
then do: # starts after previous, on main thread
and do: # starts at same time as previous, as normal. If neither are async, this would be done after
then do async: # starts after previous, on another thread
and do async: # starts at same time as previous, on another thread
finally: # starts after ALL blocks have completed (not just previous) on main thread
Caveats
Obviously, some things cannot be run safely on other threads. For example, a lot of world-altering syntaxes couldn't be run in an async block.
To cope with this, I have two solutions:
- Run these parts through the Bukkit scheduler on the main thread where possible - though this might cause extra problems
- Warn the user that these syntaxes cannot be used here, and that the block will run on the main thread
These would require you specify in syntaxes whether they are async-safe or not, which might require a lot of minor edits initially but would future-proof this (and possibly give some useful benefits for any other async stuff in future.)
There might also be some concern over syntax.
The term async
is a programming term, and understandably might not fit with Skript's aesthetic. To beginner users it would just be a meaningless term, and could easily be misunderstood. Lots of people get the idea that 'async' means 'faster' or 'without lag' or something similar, and so might misuse this.
If this is a problem, then I can suggest in [the] background
as an alternative - simpler for users to understand and pretty much explains what's going to happen. It doesn't imply the task will be done faster or better, just that it will be done in the background.
Activity