Require and subdirectories

Place to get help with not working mods / modding interface.
Post Reply
dementedpeanut
Burner Inserter
Burner Inserter
Posts: 5
Joined: Mon Aug 03, 2020 1:56 am
Contact:

Require and subdirectories

Post by dementedpeanut »

Consider this folder structure

Code: Select all

control.lua
scripts/
	some_module.lua
	file1.lua
control.lua imports the module like so

Code: Select all

local module = require("scripts.some_module")
and file1.lua imports like

Code: Select all

local module = require("some_module")
The issue I am having is that both of these imports reference NEW instances of that module, I am guessing because require uses the string parameter as a key for whether or not it has been loaded.

I am relatively new to lua so not sure on best practices here and how to solve this issue?

Pi-C
Smart Inserter
Smart Inserter
Posts: 1639
Joined: Sun Oct 14, 2018 8:13 am
Contact:

Re: Require and subdirectories

Post by Pi-C »

dementedpeanut wrote:
Sun Feb 21, 2021 2:55 pm
Consider this folder structure

Code: Select all

control.lua
scripts/
	some_module.lua
	file1.lua
The issue I am having is that both of these imports reference NEW instances of that module, I am guessing because require uses the string parameter as a key for whether or not it has been loaded.
Put functions or data into some_module.lua. You can access these functions/data from both control.lua and file1.lua. That's probably enough if you want to do some simple stuff, like converting a position:

Code: Select all

--some_module.lua:
some_functions = {}

some_functions.get_x = function(position)
 return position and position.x or position[1]
end

return some_functions

--control.lua:
local my_functions = require("scripts.some_functions")

local x = my_functions.get_x({123, 456}) 
However, as you've already noticed, control.lua and file1.lua use different instances of some_functions.lua, so you can't use that to share data across files. For this, you'll need the table "global" (which is global to your mod only, and isolated from other mods, and will be saved with the game).

Code: Select all

--control.lua:
local my_functions = require("scripts.some_functions")

global = global or {}
global.x = my_functions.get_x({123, 456}) 

--file1.lua
local my_functions = require("scripts.some_functions")

global = global or {}
local x = global.x or my_functions.get_x({234, 567})
Hope that helps a bit! :-)
Last edited by Pi-C on Sun Feb 21, 2021 5:58 pm, edited 1 time in total.
A good mod deserves a good changelog. Here's a tutorial (WIP) about Factorio's way too strict changelog syntax!

dementedpeanut
Burner Inserter
Burner Inserter
Posts: 5
Joined: Mon Aug 03, 2020 1:56 am
Contact:

Re: Require and subdirectories

Post by dementedpeanut »

Thanks! More out of curiosity than anything but is there a way to get it to load only once? If I have another file in the same directory as file1.lua it would not create another instance of some_module.lua and instead return the same value.

User avatar
DaveMcW
Smart Inserter
Smart Inserter
Posts: 3699
Joined: Tue May 13, 2014 11:06 am
Contact:

Re: Require and subdirectories

Post by DaveMcW »

Don't use the local keyword if you want a global module.

control.lua:

Code: Select all

my_functions = require("scripts.some_functions")
require("scripts.file1")
file1.lua:

Code: Select all

assert(my_functions, "my_functions does not exist!") -- will not fail

User avatar
eradicator
Smart Inserter
Smart Inserter
Posts: 5206
Joined: Tue Jul 12, 2016 9:03 am
Contact:

Re: Require and subdirectories

Post by eradicator »

dementedpeanut wrote:
Sun Feb 21, 2021 5:49 pm
Thanks! More out of curiosity than anything but is there a way to get it to load only once?
As you've noticed yourself loaded modules are indexed by string key (and references stored in the table _ENV.packages.loaded). Thus the easiest way to load the same thing into different local environments is to use identical string keys - i.e. absolute paths - in both files.

Code: Select all

local mymod = require '__my-mod-name__/subdirectory/mymod.lua'
If you need something more elaborate you could write a wrapper function around require() that translates relative paths to absolute or manually scans packages.loaded.
Author of: Belt Planner, Hand Crank Generator, Screenshot Maker, /sudo and more.
Mod support languages: 日本語, Deutsch, English
My code in the post above is dedicated to the public domain under CC0.

Post Reply

Return to “Modding help”