States

Simulating LSL states.

States, with the LSL default "new script"

default
{
    state_entry()
    {
        llSay(0, "Hello, Avatar!");
    }

    touch_start(integer total_number)
    {
        llSay(0, "Touched.");
    }
}
-- simulating LSL states, LSL default "new script"

local currentState

local function state(fnState)
    if fnState ~= currentState then
        if currentState and currentState.state_exit then
            currentState.state_exit()
        end
        for _, eventName in LLEvents:eventNames() do
            for _, handler in LLEvents:listeners(eventName) do
                LLEvents:off(eventName, handler)
            end
        end
        for ev, fn in fnState do
            if ev ~= "state_entry" and ev ~= "state_exit" then
                LLEvents:on(ev, fn)
            end
        end
        currentState = fnState
        if currentState.state_entry then
            currentState.state_entry()
        end
    end
end

local default = {}

function default.state_entry()
    ll.Say(0, "Hello, Avatar!")
end

function default.touch_start(events)
    ll.Say(0, "Touched.")
end

state(default)

States, with the LSL wiki example for states

default
{
    state_entry()
    {
        llSay(0,
            "You either just saved the script after editing it"
            + "\nand/or the script (re)entered the default state.");

        // white and opaque text
        llSetText("Click to change states", <1.0, 1.0, 1.0>, (float)TRUE);
    }

    touch_end(integer num_detected)
    {
        // Note: NEVER do a state change from within a touch_start event -
        // - that can lead to the next touch_start on return to this state to be missed.
        // Here we do the state change safely, from within touch_end
        state two;
    }

    state_exit()
    {
        llSay(0, "The script leaves the default state.");
    }
}

state two
{
    state_entry()
    {
        llSay(0, "The script entered state 'two'");
        state default;
    }

    state_exit()
    {
        llSay(0, "The script leaves state 'two'");
    }
}
-- simulating LSL states, LSL wiki example for states
    
local currentState

local function state(fnState)
    if fnState ~= currentState then
        if currentState and currentState.state_exit then
            currentState.state_exit()
        end
        for _, eventName in LLEvents:eventNames() do
            for _, handler in LLEvents:listeners(eventName) do
                LLEvents:off(eventName, handler)
            end
        end
        for ev, fn in fnState do
            if ev ~= "state_entry" and ev ~= "state_exit" then
                LLEvents:on(ev, fn)
            end
        end
        currentState = fnState
        if currentState.state_entry then
            currentState.state_entry()
        end
    end
end

local default, two = {}, {}

function default.state_entry()
    ll.Say(0,
        "You either just saved the script after editing it"
        .. "\nand/or the script (re)entered the default state.")

    -- white and opaque text
    ll.SetText("Click to change states", vector(1.0, 1.0, 1.0), 1)
end

function default.touch_end(events)
    -- Note: NEVER do a state change from within a touch_start event -
    -- that can lead to the next touch_start on return to this state to be missed.
    -- Here we do the state change safely, from within touch_end
    state(two)
end

function default.state_exit()
    ll.Say(0, "The script leaves the default state.")
end

function two.state_entry()
    ll.Say(0, "The script entered state 'two'")
    state(default)
end

function two.state_exit()
    ll.Say(0, "The script leaves state 'two'")
end

state(default)

States, using a closure to avoid the script-wide variable

-- simulating LSL states
    
local state = (function()
    local currentState
    return function(fnState)
        if fnState ~= currentState then
            if currentState and currentState.state_exit then
                currentState.state_exit()
            end
            for _, eventName in LLEvents:eventNames() do
                for _, handler in LLEvents:listeners(eventName) do
                    LLEvents:off(eventName, handler)
                end
            end
            for ev, fn in fnState do
                if ev ~= "state_entry" and ev ~= "state_exit" then
                    LLEvents:on(ev, fn)
                end
            end
            currentState = fnState
            if currentState.state_entry then
                currentState.state_entry()
            end
        end
    end
end)()

local default = {}

--

state(default)