Lua - "attempt to call a nil value (global 'require')"?

Spring E. Thing

Member
Modder
Apr 8, 2024
41
5
230
Hey guys, so I want to divide my Lua code up into multiple .lua files without polluting the global namespace. What seems like the best way to do this at least to me is a solution I found on StackOverflow:
What you need to do is to return a table with the fields you want to access in subsystem.lua and then assign and use fields from that table in your main file. Something along these lines:

Code:
-- subsystem.lua

local function doSomething()
  -- do something useful here
end

local function doMore()
  -- do something else useful
end

return { doSomething = doSomething, doMore = doMore }

-- main.lua

local subsystem = require "subsystem" -- don't add `.lua` to your `require` call
subsystem.doSomething()
subsystem.doMore()
I've gone and done exactly this, all my .lua files side-by-side in one directory, and in my IDE this is clearly valid to some degree as going to the definition of methods called outside of the script they are defined in through this require design finds the definition no problem. The problem comes in when I load my mod folder with all these .lua scripts in it inside of Co-Op DX, at which point I get multiple exceptions that all read along the lines of:
Code:
attempt to call a nil value (global 'require')
Is it simply that Co-OP DX does not load the .lua files in a way that permits this require design? If so, what are my other options for passing methods and variables around in sibling directory .lua files without polluting the global namespace? Otherwise, what am I doing wrong here?

Thanks for reading!
 
Global variables are automatically shared between files, local vars aren't. That's pretty much all there is to it
I was just thinking in terms of other mods loaded. If I have a global variable named someVar in the global namespace and so does some other mod, do they conflict or am I good? If they don't conflict then I can just use the global namespace.
 
TL;DR
The global namespace of one mod NEVER pollutes the global namespace of another, even if the mod is just one .lua file side-by-side in the same directory with another mod that is just one .lua file.


Decided to do a little test of the global namespace. Turns out it's totally safe to use the same variable name in the global namespace across two unrelated mods even if the variables are of two different data types!

Here we have two .lua files, named globalTesterA and globalTesterB respectively:
Code:
local function testerA(m)
    if(m.playerIndex == 0 and (m.controller.buttonPressed & A_BUTTON ~=0)) then
        sharedGlobal="the shared global has been corrupted by an outside mod"
    end
end
hook_event(HOOK_MARIO_UPDATE, testerA)
Code:
sharedGlobal = "this is how the shared global should be read"
local function testerB(m)
    if(m.playerIndex==0) then
        log_to_console(sharedGlobal)
    end
end
hook_event(HOOK_MARIO_UPDATE, testerB)

These files are designed such that they intentionally conflict with one another. If both mods are enabled, then when the A button is pressed by the local player in the globalTesterA mod, the log_to_console() parameter of globalTesterB should change value which should be impossible without pollution. However, as it turns out, this does not occur, meaning that even though both files share the global namespace, that global namespace is mutual to each mod, meaning the global namespace of one mod does not affect another.
Similarly, and more to what one might expect, if we pack globalTesterA and globalTesterB into their own subdirectories (renaming each .lua file to main.lua to ensure that they load as the autoexec of the respective mod subdirectories), then there is again no global namespace polluion, the global namespace is mutually exclusive between each of these mods and one does not bleed into another.
 

Users who are viewing this thread