skLambda

Addon skLambda 2026-06-15

  • Welcome to skUnity!

    Welcome to skUnity! This is a forum where members of the Skript community can communicate and interact. Skript Resource Creators can post their Resources for all to see and use.

    If you haven't done so already, feel free to join our official Discord server to expand your level of interaction with the community!

    Now, what are you waiting for? Join the community now!

skLambda 1.3.0
Supports: Paper 1.21.1+ · Skript 2.15+

This release is about async. A lambda can run off the main thread, a trigger can wait for something without freezing the server, and a new watcher polls values and conditions for you so you don't have to write a loop.

New sections
  • Wait for a future: wait for %future% [within %timespan%]: suspends the trigger until the future resolves, then runs the body, where result of %future% is ready to read. The server keeps ticking while it waits, it doesn't block. Use wait for all of %futures% to join several (when-all) or wait for any of %futures% for the first to finish. An optional on timeout: block runs instead if the time runs out, and locals from either branch carry on to the code after the block.
  • Wait for the next event: wait for next <event> [where <condition>] [within %timespan%]: pauses a trigger until that event fires, with the event's values in scope in the body (so message works for chat). Filter with a trailing where, cap the wait with within, and handle the no-show with on timeout:. The event has already dispatched by the time the body runs, so you can't cancel or change it there.
  • Watch a value: watch %value% every %timespan%: re-reads the expression on a timer and runs on change: only when it differs from last time, with old value and new value in scope. Pass within %timespan% for an on timeout:, add on end: for teardown, and tie it to an owner: so it stops itself when the owner goes away. It's a normal listener, so pause, resume, unregister and /sklambda listeners all work on it.
  • Watch a condition: watch when <condition> every %timespan%: is edge-triggered. on rising: fires the moment the condition goes false to true, on falling: fires on true to false. The state at the first poll is the baseline, so a condition that's already true won't fire on rising until it goes false and back. This is "do X the first time Y becomes true" without a poll loop.

New expressions
  • Future of a lambda: future of calling lambda %lambda% [with %objects%] starts the lambda on a background thread right away and hands you a future for its result. The body must be pure computation or I/O with no Bukkit API (no blocks, entities, inventories, or players), since touching the server off-thread will throw. Arguments are read on the main thread before it starts.
  • New future: a new future is an empty promise you resolve yourself later with complete. Good for bridging a callback or another thread back into a waiting trigger.
  • Future result: result of %future% is the resolved value, or nothing for a future that isn't done yet or that failed. Read it after a wait for, when the future is guaranteed resolved.
  • Old and new value: old value and new value hold the previous and current readings inside a watcher's on change: block.

New condition
  • Future state: %future% is done (also resolved or completed), %future% is pending, and %future% has failed, each with a negated form. Check a future before reading its result, or branch on whether a background job blew up.

New effect
  • Complete a future: complete %future% with %object% resolves one or more futures with a value and wakes any trigger waiting on them. complete %future% with no value resolves it with nothing. A future that's already resolved is left alone.
I've decided to keep working on skLambda, so I'm maintaining the project again. Here's 1.2.0.

skLambda 1.2.0

Supports: Paper 1.21.1+ · Skript 2.15+



New expressions
  • Scanned (%objects% scanned with %lambda%): like reduced, but keeps every running result instead of only the last one. Give it 3, 5, 2 and an adding lambda and you get 3, 8, 10. Add from %value% to start from a seed, which comes out first, so 3, 5, 2 from 100 gives 100, 103, 108, 110. Handy for running balances and cumulative totals.
  • Zipped (%objects% zipped with %objects% using %lambda%): walks two lists side by side and combines each pair with a two-argument lambda. (1, 2, 3) zipped with (10, 20, 30) and an adding lambda gives 11, 22, 33. It stops at the shorter list.
  • Piped (pipe %object% through %lambdas%): runs a value through a chain of one-argument lambdas, left to right, feeding each result into the next one. pipe 5 through {_inc}, {_double} is the same as calling double on the result of inc. Anything in the list that isn't a lambda is skipped.
  • Page / Window (page N of %objects% by S): cuts a list into chunks of S and hands you the Nth one (1-based). The last page can be shorter, and a page past the end is empty. window N of %objects% by S slides one element at a time instead, so window 1 is items 1 to S and window 2 is items 2 to S+1. Good for paging a list into a GUI.
  • Page count / Window count (page count of %objects% by S): how many pages the list splits into, rounded up so a partial last page still counts. window count of %objects% by S is length - S + 1. Loop over the count to fill a menu.
  • Listener cooldown (cooldown of %listener% or %listener%'s cooldown): reads the cooldown: you set on a listener, and you can change it from outside with set, add, and remove. Set it to zero to turn the cooldown off.
  • Listener owner (owner of %listener% or %listener%'s owner): gives back the owner you tied a listener to with owner:, or nothing if it has none.

New conditions
  • Counting quantifiers (at least N of, at most N of, exactly N of %objects% passes): check how many predicates in a list pass, not just all of them or none. if at least 2 of {requirements::*} passes for {_p}: is true when two or more hold. They sit right next to the existing all of / any of / none of forms.

New effect
  • Pause / resume by owner (pause all listeners owned by %object%): freezes every listener tied to that owner in one line, and resume all listeners owned by %object% brings them back. Same idea as unregister all listeners owned by, except it only pauses instead of stopping them for good.

Improvements
  • Default parameters: a lambda parameter can carry a default, lambda (n: number = 1) -> number:. When the caller leaves that argument off, the default fills in. Only trailing arguments can be skipped, so call {_f} with 10 on a two-parameter lambda uses the default for the second one.
  • Options work inside listen entries: script options: like {@grace} now expand inside a listen section, so you can write countdown: {@grace} or cooldown: {@debounce} and reuse one value across listeners. They used to be left as raw text and fail to parse.
This addon is no longer maintained. As of 1.1.1, skLambda will not receive further updates. The source stays available, but there are no planned releases, fixes, or support going forward. Feel free to fork it.

skLambda 1.1.1
Supports: Paper 1.21.1+ · Skript 2.15+

Removed
  • Duplicate list expressions: %objects% filtered where %objects% passes, count of %objects% where %objects% passes, and first of %objects% where %objects% passes have been removed. Skript core already ships its own filtered, count, and first list operations, so these were redundant and only added overlap. The lambda forms (filtered, count of … where, and the %lambda%-based expressions) still work as before.

Improvements
  • Listener internals cleaned up: listener tracking, owner cleanup, and the active-listener registry were pulled out of one large class into focused pieces. No behavior change, just easier to maintain.
skLambda 1.1.0
Supports: Paper 1.21.1+ · Skript 2.15+

New expressions
  • Highest / Lowest By: highest of %objects% by %lambda% and lowest of %objects% by %lambda% give you back the one item with the biggest or smallest value. You write a small lambda that scores each item, and it hands you the winning item itself. Ties keep the first one; an empty list gives nothing. You can also say min or max.
  • Bound: %lambda% with %objects% bound fills in the first argument(s) ahead of time. An "add two numbers" lambda can become "add 5 to whatever you give me." Fill in every argument and you get a lambda that takes nothing and just returns the answer.
  • Negated: negated %lambda% (or negation of %lambda%) flips a yes/no check so it passes when the original would fail. Handy with filtered where and count of … where.
  • Active Listeners: all active listeners gives you every listener running right now (the same ones /sklambda listeners shows). listeners owned by %object% gives you just the ones tied to one owner. You can loop over them and shut them down.

New listener options
  • on register:: runs once, right when the listener starts up. It's the partner to on end:, so you can set things up and clean them up in one place.

Improvements
  • One-line lambdas can return a value: before, a one-line lambda could only check something or do something. Now it can also give back a value, lambda (a, b): return {_a} + {_b}, or even shorter, lambda (n): {_n} * 2.
  • Lambdas remember nearby variables: a lambda keeps a copy of the local variables ({_x}) from where you wrote it, so it can still read them when it runs later. It's a snapshot from that moment, changing those variables afterward won't affect it, and changes inside won't leak out. If a parameter shares a name with one of them, the parameter wins.
  • Reduce with a starting value: %objects% reduced with %lambda% from %object% lets you set what the total starts at. An empty list just gives back the starting value, and the start can be a different type than the items (like joining a list of items into one piece of text).
  • More owner types: owner: used to really only work for players. Now an entity, chunk, or world can own a listener too. It cleans itself up automatically when the owner goes away, a player logging off, an entity dying or despawning, or a chunk/world unloading. (Teleporting between worlds no longer wrongly kills a player's listeners.)
  • Use lambdas from Java: developers can turn a Skript lambda straight into a normal Java function with asPredicate(), asFunction(), asBiFunction(), asConsumer(), and asSupplier().
skLambda 1.0.0
Supports: Paper 1.21.1+ · Skript 2.15+

New expressions
List loops can now be written as one-line operations instead of Skript loop blocks. Each one runs a lambda or predicate over a list.
  • Mapped: %objects% mapped with %lambda% turns every element into something new.
  • Filtered: %objects% filtered where %predicate% passes keeps only the elements that pass.
  • Reduced: %objects% reduced with %lambda% folds the whole list down to a single value.
  • Sorted: %objects% sorted by %lambda% sorts the list using a key pulled from each element.
  • Count Where: count of %objects% where %predicate% passes counts how many elements pass.
  • First Where: first element of %objects% where %predicate% passes returns the first element that passes.
  • End Reason: end reason reports why a listener stopped, so you can branch on it. Comes with its own type.

New functions
  • Constant predicates: always() and never() are drop-in predicates. always() always passes and never() never passes.

New listener options
These go inside a listen section.
  • owner: ties a listener to an owner (for example a player). When the owner disconnects, the listener unregisters itself.
  • on end: a callback that always runs no matter how the listener stops (completion, timeout, cancel, unregister, or owner disconnect). One single cleanup path.
  • cooldown: %timespan% debounces rapid re-triggers. A debounced event does not run on trigger and does not count toward triggers:.
  • every %timespan%: a repeating timer callback that runs while the listener is active. It pauses and stops along with the listener.

New effect
  • Unregister owned listeners: unregister all listeners owned by %object% stops only the listeners tied to that owner, for scoped cleanup.

Update checker
  • Startup check: update-notifications now actually works (it used to be a reserved toggle that did nothing). On startup the plugin checks for newer releases and notifies op players when they join.

Improvements
  • /sklambda command: now has tab-completion, and /sklambda listeners shows owner info for each listener. The plugin link now points to Modrinth instead of GitHub.
  • Internal refactor: element registration was split into LambdaModule and ListenerModule, trimming the main SkLambda class by about 90 lines.
  • Examples: example.sk gained 5 new showcases (10 to 14) covering the features above.
  • Build: version bumped to 1.0.0.

Full Changelog: git... 1.0.0
Supports: Paper 1.21.1+ · Skript 2.15+

New expressions
  • Inline Lambda: write a lambda on one line: lambda (p: player): {_p} is op. The body is either a condition, which acts as a predicate returning true/false, or an effect, which runs and returns nothing. Parameters become locals like {_p}.
  • Function Lambda: function lambda "name" wraps an existing Skript function in a lambda you can store, pass around, and call like any other lambda.
  • Call Lambda new forms: alongside call/invoke lambda, you can now write calling lambda %lambda% [with ...] and the result of calling lambda %lambda% [with ...].
New condition
  • Predicate Passes: treat a lambda as a yes/no test: %lambdas% pass[es] [for %values%], also readable as matches or holds. With a list of lambdas, a quantifier decides how many must pass: all of, which is the default, any of, or none of. Negate with doesn't pass or a leading not. Works inside listen ... where, too.

New effects
  • Unregister All Listeners: unregister all listeners stops every active listener on the server, across all scripts.
  • Unregister Last Listener: unregister the last created listener stops the most recently created one that is still active. Neither fires on completion or on timeout.
New command
  • /sklambda: shows the version and GitHub link. /sklambda listeners lists every active listener, including where it was created, the event it watches, and how long it has been alive. Alias: /skl. Guarded by the sklambda.admin permission, defaulting to op.
Configuration
  • config.yml added. Toggle features with lambda and listener. A disabled feature registers no syntax at all. Both default to true.
  • Listener leak detector (notifier): optional console warnings about listeners that stay registered longer than warn-after, repeated every warn-every, with a customizable message. Supported placeholders: {location}, {event}, {duration}. Off by default.
  • update-notifications toggle reserved for a future update check.

Improvements
  • Type hints: lambda and saved-listener variables now register a Skript type hint, so misuse is caught at parse time when a script opts into Skript's experimental using type hints.
  • Listener effects and conditions, including register, unregister, pause, resume, and the registered/paused/running checks, now take a %listener% instead of %object%, giving clearer errors.
  • remaining triggers and remaining countdown share a common base and now report 0 correctly once a listener has finished.
  • Website link now points to GitHub.