Operations and benchmarks¶
Admin commands (/fastscript, alias /fs, permission fastscript.admin)¶
| Command | Action |
|---|---|
/fastscript reload |
Recompile all scripts (old listeners are removed first) |
/fastscript scripts |
List scripts: triggers/commands/functions |
/fastscript variables |
Persistent variable count |
/fastscript bench [N] |
Benchmark the first function of the first script (warmup + N calls, ns/call) |
plugin.yml: duplicating commands¶
Bukkit only sees commands from plugin.yml. Every script command xxx
needs an entry:
commands:
heal:
description: Declared by a script
usage: /heal <player>
kit:
description: Declared by a script
usage: /kit
Without it the log says: script command '/xxx' is not declared in plugin.yml.
Benchmarks¶
BenchRunner <script.fs> <iterations> is a self-test plus a comparison
of compiled bytecode against a tree-walking interpreter of the same AST
(bench/Interpreter): one script (bench/scripts/Arithmetic.fs: fib,
sum-range, countdown, echo-number, sum-count), identical inputs,
warmup before measuring. Rule of thumb: fib ~4x, sum-range ~12–20x
(drifts between machines — by design). Honest scope: single process,
basic warmup, no JMH harness or confidence intervals — it shows the
approach pays off on the chosen operations, not a whole-server speedup.
Comparing against Skript is done on your own server following
bench/skript/README-skript.md (with benchmark.sk and benchmark.fs):
same algorithm on both sides, warmup, 5 runs, median.
Reading errors¶
file.fs:13:5: expected ':'— that'sScriptException.render(), line:column.unknown function 'x'— no builtin and no own function with that name/arity.unknown variable 'x'— local not declared (or a shadowed builtin — seeplayer).unsupported event '...'— no such event in the table.division by zero— instead ofNaN, deliberately loud.- ASM
NegativeArraySizeExceptionwhile packing argument arrays is fixed (dupbeforeaastore); if you see it again, it's a packer bug, not your script.
Known limitations¶
- Globals and per-player variables (
$name,#name) are saved tovariables.yml(players under__players__) when the plugin is disabled, not on every change. A failed/fastscript reloadkeeps the previous working set instead of wiping it. - The scheduler (
Host.runLater) exists in the runtime but is not exposed in the DSL. - The
wherefilter (on damage where ...) parses as a plain expression. - Indexing and
forgo through dynamic dispatch, not primitives;forrequires a list. is===;#namewith no space is a variable,# textis a comment.- ASM relocation uses an explicit class map (
SimpleRemappercan't do prefixes).