Page 1 of 1

How do I figure out what "type" factorio object is?

Posted: Wed May 31, 2017 3:18 am
by credomane
I need to know if a table passed to a function of mine is a LuaPlayer, LuaGui, LuiGuiElement, or some other Factorio "object".

Simply checking for elements that don't exist works for any other table in lua but the ones representing Factorio "objects" FORCE an error even if I use pcall in an attempt to trap the error!

For example

Code: Select all

--assume tbl is a LuaPlayer object
if not tbl.childen then
    --This is not a LuaGui or LuaGuiElement
    if tbl.gui then
        --This is a LuaPlayer; return the Player's LuaGui
        return tbl.gui
    else
        --Not a LuaPlayer either. What is this thing?
        return nil
    end
else
    --This is a LuaGui or LuaGuiElement; no correction needed
    return tbl
end

Instead of reaching the "This is a LuaPlayer" branch Factorio throws the error "LuaPlayer does not contain the key children".

A normal table doesn't throw this error and has unset keys "set" to nil as expected.

I expected reading unset keys on a factorio object to return nil just like any other Lua table while attempting to set a non-existent key on a factorio object to throw the "LuaPlayer does not contain the key children".

Is there any way to work around this problem with Factorio objects? It is really putting a damper on my plans. :(

Re: How do I figure out what "type" factorio object is?

Posted: Wed May 31, 2017 3:59 am
by Rseding91
Pass the type with the object. You know at every call site what each object type is so just pass that along.

Re: How do I figure out what "type" factorio object is?

Posted: Wed May 31, 2017 4:16 am
by credomane
I'm working on a GUI lib for my addons that I plan to eventually turn into PR against stdlib.

I found a super hacky way around it by abusing the new help function on every factorio object that I just discovered. Now that I have a "properly" working proof-of-concept I really want this function in the modding api! Filing a request shortly. :D

Code: Select all

    function table_contains(tbl, query)
        return string.contains(tbl.help(), query) --provided by stdlib
    end

    -- Is this a LuaGui or LuaGuiElement?
    if not table_contains(element, "LuaGui") then
        --Were we given a LuaPlayer directly?
        if not table_contains(element, "LuaPlayer") then
            --Abort, abort, abort! What is this thing!?
            return nil
        end
        --Use the player's root gui element
        element = element.gui
    end
    return element

Re: How do I figure out what "type" factorio object is?

Posted: Wed May 31, 2017 4:22 am
by Rseding91
credomane wrote:I'm working on a GUI lib for my addons that I plan to eventually turn into PR against stdlib.

I found a super hacky way around it by abusing the new help function on every factorio object that I just discovered. Now that I have a "properly" working proof-of-concept I really want this function in the modding api! Filing a request shortly. :D

Code: Select all

    function table_contains(tbl, query)
        return string.contains(tbl.help(), query) --provided by stdlib
    end

    -- Is this a LuaGui or LuaGuiElement?
    if not table_contains(element, "LuaGui") then
        --Were we given a LuaPlayer directly?
        if not table_contains(element, "LuaPlayer") then
            --Abort, abort, abort! What is this thing!?
            return nil
        end
        --Use the player's root gui element
        element = element.gui
    end
    return element
That's going to be *incredibly* slow performance wise. Don't do that...

Re: How do I figure out what "type" factorio object is?

Posted: Wed May 31, 2017 4:29 am
by credomane
Rseding91 wrote:That's going to be *incredibly* slow performance wise. Don't do that...
I know but it was the only way to make my function "smart" in the desired fashion. :(

Hopefully the Modding API Request I'm working on will make sense why I did it the way I did.

Re: How do I figure out what "type" factorio object is?

Posted: Wed May 31, 2017 6:15 am
by credomane
And I just caught my mistake with pcall that I spent literally hours pacing the house trying to figure out. Forgot the anonymous "wrapper" function. No wonder the error was "escaping" pcall. The error was actually thrown before pcall even got called. Doh! Now I can finally go to bed and actually sleep.

This doesn't work so well and lead to my horrid hack:

Code: Select all

pcall(contains(element, "children"))
The correctly working snippet:

Code: Select all

    --Workaround for Factorio throwing errors when accessing non-existent properties on Factorio Objects.
    function contains(tbl, query)
        if tbl[query] ~= nil then
            return true
        end
        return nil
    end

    -- Is this a LuaGui or LuaGuiElement?
    if not pcall(function() contains(element, "children") end) then
        --Were we given a LuaPlayer directly?
        if not pcall(function() contains(element, "gui") end) then
            --Abort, abort, abort! What is this thing!?
            return nil
        end
        --Use the player's root gui element
        element = element.gui
    end


Re: How do I figure out what "type" factorio object is?

Posted: Wed May 31, 2017 6:22 am
by Rseding91
Again, why can't you just pass the type of the object into the function you're using?