-
Notifications
You must be signed in to change notification settings - Fork 13
/
Copy pathloader.lua
143 lines (120 loc) · 4.26 KB
/
loader.lua
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
assert(sys.provides "nested-nodes", "nested nodes feature missing")
local GLOBAL_CONTENTS, GLOBAL_CHILDS = node.make_nested()
local json = require "json"
local function setup(module_name)
local M = {}
local modules = {}
local modules_content_versions = {}
function M.make_api()
return {}
end
local function event_handler(child, event_name)
if not modules[child] then
return
end
return modules[child][event_name]
end
local function module_event(child, event_name, content, ...)
if not modules[child] then
return
end
local handler = event_handler(child, event_name)
if handler then
-- print('-> event', event_name, content)
return handler(content, ...)
end
end
local function module_unload(child)
print("MODULE: " .. child .. " is unloading")
for content, version in pairs(modules_content_versions[child]) do
module_event(child, 'content_remove', content)
end
module_event(child, 'unload')
modules[child] = nil
node.dispatch("module_unload", child)
node.gc()
end
local function content_update_event(child, content, obj)
if content:sub(-5) == ".json" then
local event_name = "updated_" .. content:gsub("[.]", "_")
local handler = event_handler(child, event_name)
if handler then
local json = json.decode(resource.load_file(
obj or (child .. "/" .. content)
))
module_event(child, event_name, json)
end
end
return module_event(child, 'content_update', content)
end
local function module_load(child, module_func)
if modules[child] then
print("MODULE: about to replace ".. child)
module_unload(child)
end
print("MODULE: loading ".. child)
local api = M.make_api(child)
local function localized(name)
return child .. "/" .. name
end
api.localized = localized
api.pinned_asset = function(asset)
print("MODULE: localizing asset " .. asset.asset_name)
asset.file = resource.open_file(child .. "/" .. asset.asset_name)
return asset
end
local module = module_func(api, GLOBAL_CHILDS[child], GLOBAL_CONTENTS[child])
modules[child] = module
module_event(child, 'load')
for content, version in pairs(modules_content_versions[child]) do
content_update_event(child, content)
end
pp(modules)
node.gc()
end
local function module_update_content(child, content, version, obj)
local mcv = modules_content_versions[child]
if not mcv[content] or mcv[content] < version then
mcv[content] = version
return content_update_event(child, content, obj)
end
end
local function module_delete_content(child, content)
local mcv = modules_content_versions[child]
modules_content_versions[child][content] = nil
return module_event(child, 'content_remove', content)
end
node.event("child_add", function(child)
modules_content_versions[child] = {}
end)
node.event("child_remove", function(child)
modules_content_versions[child] = nil
end)
node.event("content_update", function(name, obj)
local child, content = util.splitpath(name)
if child == '' then -- not interested in top level events
return
elseif content == module_name then
return module_load(child, assert(
loadstring(resource.load_file(obj), "=" .. name)
))
else
return module_update_content(child, content, GLOBAL_CONTENTS[child][name], obj)
end
end)
node.event("content_remove", function(name)
local child, content = util.splitpath(name)
if child == '' then -- not interested in top level events
return
elseif content == module_name then
return module_unload(child)
else
return module_delete_content(child, content)
end
end)
M.modules = modules
return M
end
return {
setup = setup;
}