@gwigz/slua

yield

Coroutine wrappers that flatten callback APIs into sequential code

Work in Progress

This module is under active development and has not been battle-tested in production. The API may change between releases.

@gwigz/slua-modules/yield uses Lua coroutines to flatten SLua's callback-based APIs into sequential code. Call spawn() to start a coroutine, then use the wrapper functions inside it, they yield the coroutine until the result is ready, then return [ok, value] where ok is false if the request timed out.

import { spawn, requestAgentData, sleep } from "@gwigz/slua-modules/yield"

spawn(() => {
  const [ok, name] = requestAgentData(ll.GetOwner(), DATA_NAME, 10)

  if (ok) {
    ll.Say(0, `Hello, ${name}!`)

    // note that this will not pause your script
    // it will only pause this spawned coroutine
    sleep(2)

    ll.Say(0, "Done waiting.")
  }
})

Compile-time flags

Each wrapper category is gated by a compile-time flag set via the define option on @gwigz/slua-tstl-plugin in your tsconfig. When a flag is false (or omitted), the wrapper code is stripped from the Lua output via dead code elimination.

tsconfig.json
{
  "tstl": {
    "luaPlugins": [
      {
        "name": "@gwigz/slua-tstl-plugin",
        "define": {
          "YIELD_DATASERVER_AGENT": true,
          "YIELD_HTTP": true,
          // omitted flags default to false, code is stripped
        },
      },
    ],
  },
}

API

Prop

Type

Examples

waitFor

spawn(() => {
  const [channel, name, id, message] = waitFor("listen", (ch) => ch === -123)

  ll.Say(0, `${name} said: ${message}`)
})

dialog

spawn(() => {
  const [ok, choice] = dialog(-99001, ll.GetOwner(), "Pick one:", ["Yes", "No"], 60)

  if (ok) {
    ll.Say(0, `You chose: ${choice}`)
  }
})

fetch

spawn(() => {
  const [ok, res] = fetch("https://example.com/api", {
    method: "GET",
    timeout: 30,
  })

  if (ok) {
    if (res.status === 200) {
      ll.Say(0, res.body)
    }
  }
})

sensor

spawn(() => {
  const [ok, detected] = sensor("", NULL_KEY, AGENT, 20.0, PI, 10)

  if (ok) {
    if (detected) {
      for (const d of detected) {
        ll.Say(0, `Found: ${d.name}`)
      }
    } else {
      ll.Say(0, "Nobody nearby.")
    }
  }
})

On this page