FluxWareScripting
Back to site

Events

What a script can react to, what each callback is handed, and how to change the outcome rather than just watch it.

Subscribing

m:on(event, fn) registers a handler. Handlers only run while the module is switched on, so there is no enabled check to write.

m:on('tick', function()
  -- twenty times a second, while enabled
end)
A second on() replaces the first
Subscribing twice to the same event leaves you with one handler, not two. That is what makes reloading and repeated toggling safe rather than something that gradually accumulates duplicate work.

Influencing an event

One rule, the same for every event, instead of a different setter per event:

return false → cancel it
return a, b, c → replace its values
return nothing → observe only

Returning nil is not cancelling. A handler with no return statement returns nil, and that is by far the most common case, so only an explicit false counts.

-- Stop the client sending a specific packet
m:on('packetsend', function(name)
  if name == 'PlayerInteractEntityC2SPacket' then return false end
end)

-- Add to the movement delta. Scripts compose here: each one sees the
-- delta as the previous script left it.
m:on('move', function(x, y, z)
  return x * 1.2, y, z * 1.2
end)

The events

m:on('enable', function() end)

The module was switched on. Reset your state here.

budget 200,000 instructions

m:on('disable', function() end)

Switched off, reloaded, or uninstalled. Undo anything you changed.

budget 200,000 instructions

m:on('tick', function() end)

Once per client tick, twenty times a second, while enabled.

budget 200,000 instructions

m:on('update', function() end)

Player pre-motion update. Earlier in the tick than 'tick'.

budget 200,000 instructions

m:on('move', function(x:number, y:number, z:number) end)

The motion delta about to be applied. Returning three numbers is how a Speed-style script works, and scripts compose: each one sees the delta as the previous one left it.

Return: x, y, z to replace the delta

budget 200,000 instructions

m:on('jump', function() end)

The player jumped. Notification only.

budget 200,000 instructions

m:on('attack', function(target:Entity, phase:string) end)

phase is 'pre' (before the hit, cancellable) or 'post'.

Return: false to cancel

budget 200,000 instructions

m:on('render2d', function() end)per frame

Screen-space overlay, once per frame. Use the render2d namespace.

budget 50,000 instructions

m:on('render3d', function() end)per frame

World-space overlay, once per frame. Use the render3d namespace.

budget 50,000 instructions

m:on('hudrender', function() end)per frame

Like render2d, but drawn with the HUD rather than over it.

budget 50,000 instructions

m:on('key', function(key:number, action:string) end)

action is 'press', 'release' or 'repeat'. GLFW key codes.

budget 200,000 instructions

m:on('mouse', function(button:number, action:string) end)

Button 0 is left, 1 is right, 2 is middle.

budget 200,000 instructions

m:on('chatsend', function(message:string) end)

Fires before an outgoing chat message leaves.

Return: a string to replace it, or false to cancel

budget 200,000 instructions

m:on('chatreceive', function(message:string) end)

The plain-text form of an incoming line; formatting codes are stripped.

Return: false to cancel

budget 200,000 instructions

m:on('packetsend', function(name:string) end)

name is the packet's simple class name. Reading its fields is not in v1.

Return: false to cancel

budget 200,000 instructions

m:on('packetreceive', function(name:string) end)

Return: false to cancel

budget 200,000 instructions

m:on('entityspawn', function(entity:Entity) end)

An entity appeared. Handles from here are valid for this tick only.

budget 200,000 instructions

m:on('worldload', function() end)

A world became available. Anything you cached about the old one is stale.

budget 200,000 instructions