FluxWareScripting
Back to site

Getting started

How to install a script, and how to write one. Both go through the marketplace: there is no scripts folder.

Installing a script

Open Scripts in the portal, find something you want, and read it. Every listing shows the full Lua source before you install, and that is there to be used. Press Install and it is yours.

The script reaches your game the next time the client syncs, which happens on launch and whenever you press Sync on the Scripts tab in the menu. After that it is a module like any other: it sits in the list under whatever category its author chose, takes a keybind, shows in the ArrayList, and its settings are saved into your config alongside everything else.

Installing pins you to the version you installed. When the author publishes a newer one you get a badge, not a silent swap. A script is code, and an update is a new thing to trust.

Your library is the only source

Scripts come from your account's library and from nowhere else. There is no scripts folder, and there is no way to add one by hand.

This is deliberate, and it is the reason the review queue is worth anything. A sideloading route would be both the easier one and the unreviewed one, so it is the one people would use, and moderation would protect nobody. Closing it off is what makes review a guarantee rather than a suggestion.

What this costs you
Two real things. Scripting needs a connection to FluxWare, so it is unavailable offline. And writing a script means publishing to test it, which is slower than saving a file. Both are the price of the paragraph above.

Writing your own

Authoring goes through the same place. In the portal, open Scripts, then My Scripts, and create one. You give it a slug, which is its permanent identity. You do not type a name: the script is listed under the name its own code declares, so what the marketplace shows is always what the module is called in game.

Then write it in the editor and publish a version. Leave the visibility on Private while you work: your own scripts are always in your library at their current version, without your having to install them and without anyone else seeing them.

a complete first script
local m = module {
  name = 'Auto Sprint',
  category = 'movement',
}

m:on('tick', function()
  player.setSprinting(true)
end)

Two things worth noticing. The module is not enabled by default; you switch it on in the menu like any other. And the tick callback only runs while it is on, so there is no if enabled check to write.

Two names, and they are not interchangeable
The slug identifies the script in the marketplace and in everyone's library, so it cannot change once created. The module name, the one in module{}, is what shows in the module list, what the script is listed as in the portal, and the key your settings are saved under. The portal reads it from your source each time you publish a version, so it has to be a plain string: name = 'Auto Sprint', not a variable. Changing it in a published update resets that module's settings for everyone who had it. Pick it before you go public.

The write-test loop

Four steps, and the middle two are the loop:

  1. Create the script in the portal once, and leave it Private.
  2. Edit the source and publish a version.
  3. In game, open the menu, Scripts tab, press Sync.
  4. Toggle the module and watch for an error banner.

A sync is a clean rebuild: fresh environment, fresh callbacks, settings restored from your config, and the module switched back on if it was on before. Anything you kept in a local variable is gone, so state that needs to survive belongs in a setting.

Callbacks replace, they do not stack
Calling m:on('tick', ...) twice leaves you with the second handler, not both. That is what makes syncing and toggling safe: a module switched on and off twenty times still has exactly one tick handler.

Publishing

When it is ready, set the visibility. Unlisted makes it installable by share code without appearing in the feed, which is how you hand something to one person. Public puts it in the marketplace.

Both go through review. Unlisted means it is not in the feed, not that it is unchecked: a share code posted in a Discord channel is a distribution channel, and exempting it would be the sideloading route again under a different name. While you are still working, leave it Private, where only you can load it and review is not involved.

Review approves a specific version, not a name, so publishing a new version of a public script sends it back to the queue. That is the point of moderating code: an approved script that could then be silently replaced would be an approval of nothing.

When it breaks

Script errors are reported in a banner at the top of the screen, with the line number. They are not silent and they are not fatal: an error in one callback does not stop the others or affect any other script. Nothing is ever written to chat.

A script that errors three times within ten seconds switches itself off. This is almost always a per-frame callback with a typo in it, which would otherwise produce one error per frame and bury everything else. Fix it, publish, sync.

A script that fails while loading, a syntax error for instance, does not appear in the module list at all. The banner says why.

For your own diagnostics, print(...) and client.print(...) both show a FluxWare notification only you can see.

Adding settings

Settings are declared in the script body and render as the client's own widgets: the same sliders, dropdowns and colour pickers as any built-in module, saved into the same config.

local m = module { name = 'Auto Sprint', category = 'movement' }

local onlyOnGround = m:setting('boolean', 'Only on ground', true)
local mode         = m:setting('mode', 'Mode', { 'Always', 'Moving' }, 'Always')

m:on('tick', function()
  if onlyOnGround:get() and not player.isOnGround() then return end
  if mode:get() == 'Moving' then
    local x, y, z = player.velocity()
    if math.abs(x) + math.abs(z) < 0.01 then return end
  end
  player.setSprinting(true)
end)

Every setting handle has :get() and :set(value). The full list of kinds is on the module{} page.

Setting names are config keys
A setting is saved under its display name, so renaming one loses its saved value for everyone who had it. Pick the name you want before you publish.