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)
21 local mods = core.get_dirlist(path,true)
24 local modpackfile = nil
27 toadd.path = path .. DIR_DELIM .. mods[i] .. DIR_DELIM
30 toadd.modpack = modpack
32 local filename = path .. DIR_DELIM .. mods[i] .. DIR_DELIM .. "modpack.txt"
34 modpackfile,error = io.open(filename,"r")
37 if modpackfile ~= nil then
39 toadd.is_modpack = true
40 table.insert(retval,toadd)
41 get_mods(path .. DIR_DELIM .. mods[i],retval,mods[i])
43 table.insert(retval,toadd)
48 --modmanager implementation
51 --------------------------------------------------------------------------------
52 function modmgr.extract(modfile)
53 if modfile.type == "zip" then
54 local tempfolder = os.tempfolder()
56 if tempfolder ~= nil and
58 core.create_dir(tempfolder)
59 if core.extract_zip(modfile.name,tempfolder) then
67 -------------------------------------------------------------------------------
68 function modmgr.getbasefolder(temppath)
70 if temppath == nil then
77 local testfile = io.open(temppath .. DIR_DELIM .. "init.lua","r")
78 if testfile ~= nil then
86 testfile = io.open(temppath .. DIR_DELIM .. "modpack.txt","r")
87 if testfile ~= nil then
95 local subdirs = core.get_dirlist(temppath,true)
97 --only single mod or modpack allowed
106 io.open(temppath .. DIR_DELIM .. subdirs[1] ..DIR_DELIM .."init.lua","r")
107 if testfile ~= nil then
111 path= temppath .. DIR_DELIM .. subdirs[1]
116 io.open(temppath .. DIR_DELIM .. subdirs[1] ..DIR_DELIM .."modpack.txt","r")
117 if testfile ~= nil then
121 path=temppath .. DIR_DELIM .. subdirs[1]
131 --------------------------------------------------------------------------------
132 function modmgr.isValidModname(modpath)
133 if modpath:find("-") ~= nil then
140 --------------------------------------------------------------------------------
141 function modmgr.parse_register_line(line)
142 local pos1 = line:find("\"")
145 pos2 = line:find("\"",pos1+1)
148 if pos1 ~= nil and pos2 ~= nil then
149 local item = line:sub(pos1+1,pos2-1)
153 local pos3 = item:find(":")
156 local retval = item:sub(1,pos3-1)
167 --------------------------------------------------------------------------------
168 function modmgr.parse_dofile_line(modpath,line)
169 local pos1 = line:find("\"")
172 pos2 = line:find("\"",pos1+1)
175 if pos1 ~= nil and pos2 ~= nil then
176 local filename = line:sub(pos1+1,pos2-1)
178 if filename ~= nil and
180 filename:find(".lua") then
181 return modmgr.identify_modname(modpath,filename)
187 --------------------------------------------------------------------------------
188 function modmgr.identify_modname(modpath,filename)
189 local testfile = io.open(modpath .. DIR_DELIM .. filename,"r")
190 if testfile ~= nil then
191 local line = testfile:read()
196 if line:find("minetest.register_tool") then
197 modname = modmgr.parse_register_line(line)
200 if line:find("minetest.register_craftitem") then
201 modname = modmgr.parse_register_line(line)
205 if line:find("minetest.register_node") then
206 modname = modmgr.parse_register_line(line)
209 if line:find("dofile") then
210 modname = modmgr.parse_dofile_line(modpath,line)
213 if modname ~= nil then
218 line = testfile:read()
225 --------------------------------------------------------------------------------
226 function modmgr.render_modlist(render_list)
229 if render_list == nil then
230 if modmgr.global_mods == nil then
231 modmgr.refresh_globals()
233 render_list = modmgr.global_mods
236 local list = render_list:get_list()
237 local last_modpack = nil
239 for i,v in ipairs(list) do
241 retval = retval ..","
247 local rawlist = render_list:get_raw_list()
249 local all_enabled = true
250 for j=1,#rawlist,1 do
251 if rawlist[j].modpack == list[i].name and
252 rawlist[j].enabled ~= true then
258 if all_enabled == false then
259 color = mt_color_grey
261 color = mt_color_dark_green
265 if v.typ == "game_mod" then
266 color = mt_color_blue
269 color = mt_color_green
273 retval = retval .. color
274 if v.modpack ~= nil then
275 retval = retval .. " "
277 retval = retval .. v.name
283 --------------------------------------------------------------------------------
284 function modmgr.get_dependencies(modfolder)
286 if modfolder ~= nil then
287 local filename = modfolder ..
288 DIR_DELIM .. "depends.txt"
290 local dependencyfile = io.open(filename,"r")
292 if dependencyfile then
293 local dependency = dependencyfile:read("*l")
298 toadd = toadd .. dependency
299 dependency = dependencyfile:read()
301 dependencyfile:close()
308 --------------------------------------------------------------------------------
309 function modmgr.get_worldconfig(worldpath)
310 local filename = worldpath ..
311 DIR_DELIM .. "world.mt"
313 local worldfile = Settings(filename)
315 local worldconfig = {}
316 worldconfig.global_mods = {}
317 worldconfig.game_mods = {}
319 for key,value in pairs(worldfile:to_table()) do
320 if key == "gameid" then
321 worldconfig.id = value
323 worldconfig.global_mods[key] = core.is_yes(value)
328 local gamespec = gamemgr.find_by_gameid(worldconfig.id)
329 gamemgr.get_game_mods(gamespec, worldconfig.game_mods)
334 --------------------------------------------------------------------------------
335 function modmgr.installmod(modfilename,basename)
336 local modfile = modmgr.identify_filetype(modfilename)
337 local modpath = modmgr.extract(modfile)
339 if modpath == nil then
340 gamedata.errormessage = fgettext("Install Mod: file: \"$1\"", modfile.name) ..
341 fgettext("\nInstall Mod: unsupported filetype \"$1\" or broken archive", modfile.type)
345 local basefolder = modmgr.getbasefolder(modpath)
347 if basefolder.type == "modpack" then
348 local clean_path = nil
350 if basename ~= nil then
351 clean_path = "mp_" .. basename
354 if clean_path == nil then
355 clean_path = get_last_folder(cleanup_path(basefolder.path))
358 if clean_path ~= nil then
359 local targetpath = core.get_modpath() .. DIR_DELIM .. clean_path
360 if not core.copy_dir(basefolder.path,targetpath) then
361 gamedata.errormessage = fgettext("Failed to install $1 to $2", basename, targetpath)
364 gamedata.errormessage = fgettext("Install Mod: unable to find suitable foldername for modpack $1", modfilename)
368 if basefolder.type == "mod" then
369 local targetfolder = basename
371 if targetfolder == nil then
372 targetfolder = modmgr.identify_modname(basefolder.path,"init.lua")
375 --if heuristic failed try to use current foldername
376 if targetfolder == nil then
377 targetfolder = get_last_folder(basefolder.path)
380 if targetfolder ~= nil and modmgr.isValidModname(targetfolder) then
381 local targetpath = core.get_modpath() .. DIR_DELIM .. targetfolder
382 core.copy_dir(basefolder.path,targetpath)
384 gamedata.errormessage = fgettext("Install Mod: unable to find real modname for: $1", modfilename)
388 core.delete_dir(modpath)
390 modmgr.refresh_globals()
394 --------------------------------------------------------------------------------
395 function modmgr.preparemodlist(data)
398 local global_mods = {}
402 local modpath = core.get_modpath()
404 if modpath ~= nil and
406 get_mods(modpath,global_mods)
409 for i=1,#global_mods,1 do
410 global_mods[i].typ = "global_mod"
411 table.insert(retval,global_mods[i])
415 local gamespec = gamemgr.find_by_gameid(data.gameid)
416 gamemgr.get_game_mods(gamespec, game_mods)
418 for i=1,#game_mods,1 do
419 game_mods[i].typ = "game_mod"
420 table.insert(retval,game_mods[i])
423 if data.worldpath == nil then
427 --read world mod configuration
428 local filename = data.worldpath ..
429 DIR_DELIM .. "world.mt"
431 local worldfile = Settings(filename)
433 for key,value in pairs(worldfile:to_table()) do
434 if key:sub(1, 9) == "load_mod_" then
438 if retval[i].name == key and
439 not retval[i].is_modpack then
444 if element ~= nil then
445 element.enabled = core.is_yes(value)
447 core.log("info", "Mod: " .. key .. " " .. dump(value) .. " but not found")
455 --------------------------------------------------------------------------------
456 function modmgr.comparemod(elem1,elem2)
457 if elem1 == nil or elem2 == nil then
460 if elem1.name ~= elem2.name then
463 if elem1.is_modpack ~= elem2.is_modpack then
466 if elem1.typ ~= elem2.typ then
469 if elem1.modpack ~= elem2.modpack then
473 if elem1.path ~= elem2.path then
480 --------------------------------------------------------------------------------
481 function modmgr.mod_exists(basename)
483 if modmgr.global_mods == nil then
484 modmgr.refresh_globals()
487 if modmgr.global_mods:raw_index_by_uid(basename) > 0 then
494 --------------------------------------------------------------------------------
495 function modmgr.get_global_mod(idx)
497 if modmgr.global_mods == nil then
501 if idx == nil or idx < 1 or
502 idx > modmgr.global_mods:size() then
506 return modmgr.global_mods:get_list()[idx]
509 --------------------------------------------------------------------------------
510 function modmgr.refresh_globals()
511 modmgr.global_mods = filterlist.create(
512 modmgr.preparemodlist, --refresh
513 modmgr.comparemod, --compare
514 function(element,uid) --uid match
515 if element.name == uid then
522 modmgr.global_mods:add_sort_mechanism("alphabetic", sort_mod_list)
523 modmgr.global_mods:set_sortmode("alphabetic")
526 --------------------------------------------------------------------------------
527 function modmgr.identify_filetype(name)
529 if name:sub(-3):lower() == "zip" then
536 if name:sub(-6):lower() == "tar.gz" or
537 name:sub(-3):lower() == "tgz"then
544 if name:sub(-6):lower() == "tar.bz2" then
551 if name:sub(-2):lower() == "7z" then