init.lua
6.86 KB
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
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
-- TE4 - T-Engine 4
-- Copyright (C) 2009 - 2019 Nicolas Casalini
--
-- This program is free software: you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation, either version 3 of the License, or
-- (at your option) any later version.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
--
-- Nicolas Casalini "DarkGod"
-- darkgod@te4.org
-- Setup the user directory
local homepath = fs.getUserPath()..fs.getPathSeparator()..fs.getHomePath()..fs.getPathSeparator().."4.0"
fs.mount(homepath, "/")
local load load = function(...)
-- Look for the required engine and load it
local args = {...}
local req_engine = args[1] or "te4"
local req_version = args[2] or "LATEST"
__load_module = args[3] or "boot"
__player_name = args[4] or "player"
__player_new = args[5] and true or false
if args[6] then
print('===', args[6])
local f = loadstring(args[6])
__module_extra_info = {}
setfenv(f, __module_extra_info)
pcall(f)
for k, e in pairs(__module_extra_info) do print(" * Module extra info", k, ":=:", e) end
else
__module_extra_info = {}
end
__request_profile = args[7] or "default"
print("Reboot using", req_engine, req_version, __load_module, __player_name, __player_new)
local engines = { __byname={} }
local function tryLoadEngine(ff, dir, teae)
local env = {engine={}}
setfenv(ff, env)
pcall(ff)
if env.engine.version and env.engine.require_c_core == core.game.VERSION then
local name = env.engine.version[4]
local vstr = ("%s-%d.%d.%d"):format(name, env.engine.version[1], env.engine.version[2], env.engine.version[3])
engines[name] = engines[name] or {}
engines.__byname[vstr] = true
engines[name][#engines[name]+1] = {env.engine.version[1], env.engine.version[2], env.engine.version[3], name, env.engine.version[5], load_dir=dir, load_teae=teae}
print("[ENGINE LOADER] available from "..(dir and "dir" or "teae")..": ", vstr)
end
end
-- List all available engines
for i, f in ipairs(fs.list("/engines/")) do
if fs.exists("/engines/"..f.."/engine/version.lua") then
local ff, err = loadfile("/engines/"..f.."/engine/version.lua")
if ff and not err then tryLoadEngine(ff, "/engines/"..f.."/", nil) end
else
local _, _, name, vM, vm, vp = f:find("^([a-z0-9-]+)%-(%d+)%.(%d+)%.(%d+).teae$")
if name then
local eng_path = fs.getRealPath("/engines/"..f)
fs.mount(eng_path, "/tmp")
local ff, err = loadfile("/tmp/engine/version.lua")
if ff and not err then tryLoadEngine(ff, nil, "/engines/"..f) end
fs.umount(eng_path)
end
end
end
__available_engines = engines
print("[ENGINE LOADER] found engines", table.serialize(engines, nil, true))
print("[ENGINE LOADER] looked in:")
for i, m in ipairs(fs.getSearchPath()) do print('', m) end
local use_engine = nil
if req_version == "LATEST" then
-- Sort engines
local engs = engines[req_engine]
if not engs then print("[ENGINE LOADER] no engines with id", req_engine) os.exit() end
table.sort(engs, function(a, b)
if a[1] ~= b[1] then return a[1] < b[1]
else
if a[2] ~= b[2] then return a[2] < b[2]
else
return a[3] < b[3]
end
end
end)
for i, v in ipairs(engs) do
print("[ENGINE LOADER] sorted:", req_engine, v[1], v[2], v[3])
end
-- Use the latest one
use_engine = engs[#engs]
else
-- Look for the required engine
local _, _, name, vM, vm, vp = (req_engine.."-"..req_version):find("([a-z0-9-]+)%-(%d+)%.(%d+)%.(%d+)")
if name then
if engines[name] then
for i, eng in ipairs(engines[name]) do
if eng[1] == tonumber(vM) and eng[2] == tonumber(vm) and eng[3] == tonumber(vp) then
use_engine = eng
break
end
end
end
end
end
if not use_engine then print("[ENGINE LOADER] no engines found! rebooting to default!") return load() end
print("[ENGINE LOADER] loading engine:", use_engine[1], use_engine[2], use_engine[3], use_engine[4])
-- Now load it, either from a directory or from a teae(T-Engine Archived Engine) file
if use_engine.load_teae then
print("[ENGINE LOADER] using archived engine:", use_engine.load_teae)
fs.mount(fs.getRealPath(use_engine.load_teae), "/")
elseif use_engine.load_dir then
print("[ENGINE LOADER] using directory engine:", use_engine.load_dir)
fs.mount(fs.getRealPath(use_engine.load_dir), "/")
end
end
load(...)
fs.umount(homepath)
__addons_superload_order = {}
__addons_fn_superloads = {}
local apply_superloads = function(orig, order)
return function(...)
local r = orig(...)
for i, f in ipairs(order) do r = f(r) end
end
end
local te4_loader = function(name)
local bname = name
-- Base loader
local bfile = "/"..bname:gsub("%.", "/")..".lua"
local prev, err
if fs.exists(bfile) then
prev, err = loadfile(bfile)
if not prev and err then
error("Error while loading base '"..bfile.."':\n"..tostring(err))
return nil
end
end
name = name:gsub("%.", "/")
for i = 1, #__addons_superload_order do
local addon = __addons_superload_order[i]
local fn = "/mod/addons/"..addon.."/superload/"..name..".lua"
if fs.exists(fn) then
local f, err = loadfile(fn)
if not f and err then
error("Error while superloading '"..fn.."':\n"..tostring(err))
end
local base = prev
setfenv(f, setmetatable({
loadPrevious = function()
print("FROM ", fn, "loading previous!")
base(bname)
return package.loaded[bname]
end
}, {__index=_G}))
prev = f
end
if __addons_fn_superloads[addon] and __addons_fn_superloads[addon][bname] then
print("FUNCTIONS FOUND", addon, bname)
prev = apply_superloads(prev, __addons_fn_superloads[addon][bname])
end
end
return prev
end
table.insert(package.loaders, 2, te4_loader)
local oldload = loadfile
local dlcd_loader = function(name)
if not fs.exists("/"..name:gsub("%.", "/")..".lua.stub") then return end
print("===DLCLOADER:class", "/"..name:gsub("%.", "/")..".lua.stub")
local d = oldload("/"..name:gsub("%.", "/")..".lua.stub")()
local data
if profile.dlc_files.classes[name] then
data = profile.dlc_files.classes[name]
print("===DLCLOADER:class using preloaded file")
else
data = profile:getDLCD(d.name, d.version, name:gsub("%.", "/")..".lua")
print("===DLCLOADER:class loaded", (data or ""):len())
end
return loadstring(data)
end
table.insert(package.loaders, 2, dlcd_loader)
loadfile = function(name)
if not fs.exists(name..".stub") then return oldload(name) end
print("===DLCLOADER:file", name..".stub")
local d = oldload(name..".stub")()
local data = profile:getDLCD(d.name, d.version, name)
return loadstring(data)
end
-- RUN engine RUN !!
dofile("/engine/init.lua")