synthetic-factorio 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,63 @@
1
+ local old_require = require
2
+
3
+ -- Wrapper around lua's require() to handle several Factorio-isms that are used by either vanilla or other mods that break under regular lua import rules
4
+
5
+ -- Mods can require() the same filename across different mods, and each one will load its own version
6
+ -- for example both mods base and space-age import "prototypes.tile.tiles" but refer to different files
7
+ -- The lua spec says such an import re-uses the existing module, even if package.paths has changed, so this is a workaround
8
+ -- Each mod starts in its own "context" defined by the global current_mod_root_path
9
+ -- Imports are first attempted from this root path, and then allowed to fall back on error to find things like lualib
10
+ -- If a mod explicitly imports from another mod using the double-underscore syntax, i.e. require("__modname__.file")
11
+ -- then current_mod_root_path is set to that mod, and then restored after
12
+
13
+ -- This cannot be handled by running mods in different lua contexts because mods can re-use globals that were previously declared
14
+ -- for example "apply_heat_pipe_glow" is defined in base.prototypes.entity.entities, but then used in space-age.prototypes.entity.entities without being re-declared
15
+ -- Therefore both mods need to load in the same lua context to preserve globals
16
+
17
+ function require(name, ...)
18
+ local mod_changed = false
19
+ local previous_mod = current_mod_root_path
20
+ local new_name = name
21
+ if(string.find(name, '__')) then
22
+ mod_changed = true
23
+ local end_index = string.find(name, '__', 3)
24
+ current_mod_root_path = string.sub(name, 3, end_index - 1)
25
+ else
26
+ new_name = '__' .. current_mod_root_path .. '__.' .. name
27
+ end
28
+
29
+ -- This is the first load attempt that tries within the context of current_mod_root_path
30
+ local status, lib = pcall(old_require, new_name, ...)
31
+ if(mod_changed) then
32
+ current_mod_root_path = previous_mod
33
+ end
34
+ if(status) then return lib end
35
+
36
+ if(not string.find(lib, string.format("module '%s' not found", new_name), 1, true)) then
37
+ error(lib)
38
+ end
39
+
40
+ -- First import has failed, fall back to the exact name that was provided. Most commonly this is loading lualib
41
+ -- though it also handles the case where mods require paths from vanilla mods without specifying the mod prefix
42
+ status, lib = pcall(old_require, name, ...)
43
+ if(status) then return lib end
44
+ if(not string.find(lib, string.format("module '%s' not found", name), 1, true)) then
45
+ error(lib)
46
+ end
47
+
48
+ -- The factorio-data repo (https://github.com/wube/factorio-data) is the source for the data for the vanilla "mods"
49
+ -- This repo doesn't have things like graphics, sounds or menu simulations, but these are still require()d in many places from the existing lua files
50
+ -- The global suppress_require_errors is set during vanilla mod loading to suppress these
51
+ -- They are also suppressed when loading from the vanilla mod namespaces to handle loads from other mods
52
+ -- By default non-vanilla mods do not suppress, set the global suppress_require_errors = true to change
53
+ if(suppress_require_errors or string.find(name, '__base__') or string.find(name, '__space-age__', 1, true) or string.find(name, '__quality__') or string.find(name, '__recycler__') or string.find(name, '__elevated-rails__', 1, true)) then
54
+ if(string.find(name, 'graphics')) then
55
+ return { width = 1, height = 1, shift = util.by_pixel(1.0, 1.0), line_length = 5 }
56
+ end
57
+ if(string.find(name, 'menu-simulations', 1, true) or string.find(name, 'sound')) then
58
+ return {}
59
+ end
60
+ end
61
+
62
+ error(lib)
63
+ end