2 --Copyright (C) 2013 sapier
4 --This program is free software; you can redistribute it and/or modify
5 --it under the terms of the GNU Lesser General Public License as published by
6 --the Free Software Foundation; either version 2.1 of the License, or
7 --(at your option) any later version.
9 --This program is distributed in the hope that it will be useful,
10 --but WITHOUT ANY WARRANTY; without even the implied warranty of
11 --MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 --GNU Lesser General Public License for more details.
14 --You should have received a copy of the GNU Lesser General Public License along
15 --with this program; if not, write to the Free Software Foundation, Inc.,
16 --51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 --------------------------------------------------------------------------------
19 function get_mods(path,retval,modpack)
20 local mods = core.get_dir_list(path, true)
23 if mods[i]:sub(1,1) ~= "." then
25 local modpackfile = nil
28 toadd.path = path .. DIR_DELIM .. mods[i] .. DIR_DELIM
31 toadd.modpack = modpack
33 local filename = path .. DIR_DELIM .. mods[i] .. DIR_DELIM .. "modpack.txt"
35 modpackfile,error = io.open(filename,"r")
38 if modpackfile ~= nil then
40 toadd.is_modpack = true
41 table.insert(retval,toadd)
42 get_mods(path .. DIR_DELIM .. mods[i],retval,mods[i])
44 table.insert(retval,toadd)
50 --modmanager implementation
53 --------------------------------------------------------------------------------
54 function modmgr.extract(modfile)
55 if modfile.type == "zip" then
56 local tempfolder = os.tempfolder()
58 if tempfolder ~= nil and
60 core.create_dir(tempfolder)
61 if core.extract_zip(modfile.name,tempfolder) then
69 -------------------------------------------------------------------------------
70 function modmgr.getbasefolder(temppath)
72 if temppath == nil then
79 local testfile = io.open(temppath .. DIR_DELIM .. "init.lua","r")
80 if testfile ~= nil then
88 testfile = io.open(temppath .. DIR_DELIM .. "modpack.txt","r")
89 if testfile ~= nil then
97 local subdirs = core.get_dir_list(temppath, true)
99 --only single mod or modpack allowed
100 if #subdirs ~= 1 then
108 io.open(temppath .. DIR_DELIM .. subdirs[1] ..DIR_DELIM .."init.lua","r")
109 if testfile ~= nil then
113 path= temppath .. DIR_DELIM .. subdirs[1]
118 io.open(temppath .. DIR_DELIM .. subdirs[1] ..DIR_DELIM .."modpack.txt","r")
119 if testfile ~= nil then
123 path=temppath .. DIR_DELIM .. subdirs[1]
133 --------------------------------------------------------------------------------
134 function modmgr.isValidModname(modpath)
135 if modpath:find("-") ~= nil then
142 --------------------------------------------------------------------------------
143 function modmgr.parse_register_line(line)
144 local pos1 = line:find("\"")
147 pos2 = line:find("\"",pos1+1)
150 if pos1 ~= nil and pos2 ~= nil then
151 local item = line:sub(pos1+1,pos2-1)
155 local pos3 = item:find(":")
158 local retval = item:sub(1,pos3-1)
169 --------------------------------------------------------------------------------
170 function modmgr.parse_dofile_line(modpath,line)
171 local pos1 = line:find("\"")
174 pos2 = line:find("\"",pos1+1)
177 if pos1 ~= nil and pos2 ~= nil then
178 local filename = line:sub(pos1+1,pos2-1)
180 if filename ~= nil and
182 filename:find(".lua") then
183 return modmgr.identify_modname(modpath,filename)
189 --------------------------------------------------------------------------------
190 function modmgr.identify_modname(modpath,filename)
191 local testfile = io.open(modpath .. DIR_DELIM .. filename,"r")
192 if testfile ~= nil then
193 local line = testfile:read()
198 if line:find("minetest.register_tool") then
199 modname = modmgr.parse_register_line(line)
202 if line:find("minetest.register_craftitem") then
203 modname = modmgr.parse_register_line(line)
207 if line:find("minetest.register_node") then
208 modname = modmgr.parse_register_line(line)
211 if line:find("dofile") then
212 modname = modmgr.parse_dofile_line(modpath,line)
215 if modname ~= nil then
220 line = testfile:read()
227 --------------------------------------------------------------------------------
228 function modmgr.render_modlist(render_list)
231 if render_list == nil then
232 if modmgr.global_mods == nil then
233 modmgr.refresh_globals()
235 render_list = modmgr.global_mods
238 local list = render_list:get_list()
239 local last_modpack = nil
241 for i,v in ipairs(list) do
243 retval = retval ..","
249 local rawlist = render_list:get_raw_list()
251 local all_enabled = true
252 for j=1,#rawlist,1 do
253 if rawlist[j].modpack == list[i].name and
254 rawlist[j].enabled ~= true then
260 if all_enabled == false then
261 color = mt_color_grey
263 color = mt_color_dark_green
267 if v.typ == "game_mod" then
268 color = mt_color_blue
271 color = mt_color_green
275 retval = retval .. color
276 if v.modpack ~= nil then
277 retval = retval .. " "
279 retval = retval .. v.name
285 --------------------------------------------------------------------------------
286 function modmgr.get_dependencies(modfolder)
288 if modfolder ~= nil then
289 local filename = modfolder ..
290 DIR_DELIM .. "depends.txt"
292 local dependencyfile = io.open(filename,"r")
294 if dependencyfile then
295 local dependency = dependencyfile:read("*l")
300 toadd = toadd .. dependency
301 dependency = dependencyfile:read()
303 dependencyfile:close()
310 --------------------------------------------------------------------------------
311 function modmgr.get_worldconfig(worldpath)
312 local filename = worldpath ..
313 DIR_DELIM .. "world.mt"
315 local worldfile = Settings(filename)
317 local worldconfig = {}
318 worldconfig.global_mods = {}
319 worldconfig.game_mods = {}
321 for key,value in pairs(worldfile:to_table()) do
322 if key == "gameid" then
323 worldconfig.id = value
324 elseif key:sub(0, 9) == "load_mod_" then
325 worldconfig.global_mods[key] = core.is_yes(value)
327 worldconfig[key] = value
332 local gamespec = gamemgr.find_by_gameid(worldconfig.id)
333 gamemgr.get_game_mods(gamespec, worldconfig.game_mods)
338 --------------------------------------------------------------------------------
339 function modmgr.installmod(modfilename,basename)
340 local modfile = modmgr.identify_filetype(modfilename)
341 local modpath = modmgr.extract(modfile)
343 if modpath == nil then
344 gamedata.errormessage = fgettext("Install Mod: file: \"$1\"", modfile.name) ..
345 fgettext("\nInstall Mod: unsupported filetype \"$1\" or broken archive", modfile.type)
349 local basefolder = modmgr.getbasefolder(modpath)
351 if basefolder.type == "modpack" then
352 local clean_path = nil
354 if basename ~= nil then
355 clean_path = "mp_" .. basename
358 if clean_path == nil then
359 clean_path = get_last_folder(cleanup_path(basefolder.path))
362 if clean_path ~= nil then
363 local targetpath = core.get_modpath() .. DIR_DELIM .. clean_path
364 if not core.copy_dir(basefolder.path,targetpath) then
365 gamedata.errormessage = fgettext("Failed to install $1 to $2", basename, targetpath)
368 gamedata.errormessage = fgettext("Install Mod: unable to find suitable foldername for modpack $1", modfilename)
372 if basefolder.type == "mod" then
373 local targetfolder = basename
375 if targetfolder == nil then
376 targetfolder = modmgr.identify_modname(basefolder.path,"init.lua")
379 --if heuristic failed try to use current foldername
380 if targetfolder == nil then
381 targetfolder = get_last_folder(basefolder.path)
384 if targetfolder ~= nil and modmgr.isValidModname(targetfolder) then
385 local targetpath = core.get_modpath() .. DIR_DELIM .. targetfolder
386 core.copy_dir(basefolder.path,targetpath)
388 gamedata.errormessage = fgettext("Install Mod: unable to find real modname for: $1", modfilename)
392 core.delete_dir(modpath)
394 modmgr.refresh_globals()
398 --------------------------------------------------------------------------------
399 function modmgr.preparemodlist(data)
402 local global_mods = {}
406 local modpath = core.get_modpath()
408 if modpath ~= nil and
410 get_mods(modpath,global_mods)
413 for i=1,#global_mods,1 do
414 global_mods[i].typ = "global_mod"
415 table.insert(retval,global_mods[i])
419 local gamespec = gamemgr.find_by_gameid(data.gameid)
420 gamemgr.get_game_mods(gamespec, game_mods)
422 for i=1,#game_mods,1 do
423 game_mods[i].typ = "game_mod"
424 table.insert(retval,game_mods[i])
427 if data.worldpath == nil then
431 --read world mod configuration
432 local filename = data.worldpath ..
433 DIR_DELIM .. "world.mt"
435 local worldfile = Settings(filename)
437 for key,value in pairs(worldfile:to_table()) do
438 if key:sub(1, 9) == "load_mod_" then
442 if retval[i].name == key and
443 not retval[i].is_modpack then
448 if element ~= nil then
449 element.enabled = core.is_yes(value)
451 core.log("info", "Mod: " .. key .. " " .. dump(value) .. " but not found")
459 --------------------------------------------------------------------------------
460 function modmgr.comparemod(elem1,elem2)
461 if elem1 == nil or elem2 == nil then
464 if elem1.name ~= elem2.name then
467 if elem1.is_modpack ~= elem2.is_modpack then
470 if elem1.typ ~= elem2.typ then
473 if elem1.modpack ~= elem2.modpack then
477 if elem1.path ~= elem2.path then
484 --------------------------------------------------------------------------------
485 function modmgr.mod_exists(basename)
487 if modmgr.global_mods == nil then
488 modmgr.refresh_globals()
491 if modmgr.global_mods:raw_index_by_uid(basename) > 0 then
498 --------------------------------------------------------------------------------
499 function modmgr.get_global_mod(idx)
501 if modmgr.global_mods == nil then
505 if idx == nil or idx < 1 or
506 idx > modmgr.global_mods:size() then
510 return modmgr.global_mods:get_list()[idx]
513 --------------------------------------------------------------------------------
514 function modmgr.refresh_globals()
515 modmgr.global_mods = filterlist.create(
516 modmgr.preparemodlist, --refresh
517 modmgr.comparemod, --compare
518 function(element,uid) --uid match
519 if element.name == uid then
526 modmgr.global_mods:add_sort_mechanism("alphabetic", sort_mod_list)
527 modmgr.global_mods:set_sortmode("alphabetic")
530 --------------------------------------------------------------------------------
531 function modmgr.identify_filetype(name)
533 if name:sub(-3):lower() == "zip" then
540 if name:sub(-6):lower() == "tar.gz" or
541 name:sub(-3):lower() == "tgz"then
548 if name:sub(-6):lower() == "tar.bz2" then
555 if name:sub(-2):lower() == "7z" then