]> git.lizzy.rs Git - dragonfireclient.git/blob - builtin/modmgr.lua
Initialize world before creating BanManager and RollbackManager
[dragonfireclient.git] / builtin / modmgr.lua
1 --Minetest
2 --Copyright (C) 2013 sapier
3 --
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.
8 --
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.
13 --
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.
17
18 --------------------------------------------------------------------------------
19 function get_mods(path,retval,modpack)
20
21         local mods = engine.get_dirlist(path,true)
22         for i=1,#mods,1 do
23                 local toadd = {}
24                 local modpackfile = nil
25
26                 toadd.name              = mods[i]
27                 toadd.path              = path .. DIR_DELIM .. mods[i] .. DIR_DELIM
28                 if modpack ~= nil and
29                         modpack ~= "" then
30                         toadd.modpack   = modpack
31                 else
32                         local filename = path .. DIR_DELIM .. mods[i] .. DIR_DELIM .. "modpack.txt"
33                         local error = nil
34                         modpackfile,error = io.open(filename,"r")
35                 end
36
37                 if modpackfile ~= nil then
38                         modpackfile:close()
39                         toadd.is_modpack = true
40                         table.insert(retval,toadd)
41                         get_mods(path .. DIR_DELIM .. mods[i],retval,mods[i])
42                 else
43                         table.insert(retval,toadd)
44                 end
45         end
46 end
47
48 --modmanager implementation
49 modmgr = {}
50
51 --------------------------------------------------------------------------------
52 function modmgr.extract(modfile)
53         if modfile.type == "zip" then
54                 local tempfolder = os.tempfolder()
55
56                 if tempfolder ~= nil and
57                         tempfolder ~= "" then
58                         engine.create_dir(tempfolder)
59                         if engine.extract_zip(modfile.name,tempfolder) then
60                                 return tempfolder
61                         end
62                 end
63         end
64         return nil
65 end
66
67 -------------------------------------------------------------------------------
68 function modmgr.getbasefolder(temppath)
69
70         if temppath == nil then
71                 return {
72                 type = "invalid",
73                 path = ""
74                 }
75         end
76
77         local testfile = io.open(temppath .. DIR_DELIM .. "init.lua","r")
78         if testfile ~= nil then
79                 testfile:close()
80                 return {
81                                 type="mod",
82                                 path=temppath
83                                 }
84         end
85
86         testfile = io.open(temppath .. DIR_DELIM .. "modpack.txt","r")
87         if testfile ~= nil then
88                 testfile:close()
89                 return {
90                                 type="modpack",
91                                 path=temppath
92                                 }
93         end
94
95         local subdirs = engine.get_dirlist(temppath,true)
96
97         --only single mod or modpack allowed
98         if #subdirs ~= 1 then
99                 return {
100                         type = "invalid",
101                         path = ""
102                         }
103         end
104
105         testfile =
106         io.open(temppath .. DIR_DELIM .. subdirs[1] ..DIR_DELIM .."init.lua","r")
107         if testfile ~= nil then
108                 testfile:close()
109                 return {
110                         type="mod",
111                         path= temppath .. DIR_DELIM .. subdirs[1]
112                         }
113         end
114
115         testfile =
116         io.open(temppath .. DIR_DELIM .. subdirs[1] ..DIR_DELIM .."modpack.txt","r")
117         if testfile ~= nil then
118                 testfile:close()
119                 return {
120                         type="modpack",
121                         path=temppath ..  DIR_DELIM .. subdirs[1]
122                         }
123         end
124
125         return {
126                 type = "invalid",
127                 path = ""
128                 }
129 end
130
131 --------------------------------------------------------------------------------
132 function modmgr.isValidModname(modpath)
133         if modpath:find("-") ~= nil then
134                 return false
135         end
136
137         return true
138 end
139
140 --------------------------------------------------------------------------------
141 function modmgr.parse_register_line(line)
142         local pos1 = line:find("\"")
143         local pos2 = nil
144         if pos1 ~= nil then
145                 pos2 = line:find("\"",pos1+1)
146         end
147
148         if pos1 ~= nil and pos2 ~= nil then
149                 local item = line:sub(pos1+1,pos2-1)
150
151                 if item ~= nil and
152                         item ~= "" then
153                         local pos3 = item:find(":")
154
155                         if pos3 ~= nil then
156                                 local retval = item:sub(1,pos3-1)
157                                 if retval ~= nil and
158                                         retval ~= "" then
159                                         return retval
160                                 end
161                         end
162                 end
163         end
164         return nil
165 end
166
167 --------------------------------------------------------------------------------
168 function modmgr.parse_dofile_line(modpath,line)
169         local pos1 = line:find("\"")
170         local pos2 = nil
171         if pos1 ~= nil then
172                 pos2 = line:find("\"",pos1+1)
173         end
174
175         if pos1 ~= nil and pos2 ~= nil then
176                 local filename = line:sub(pos1+1,pos2-1)
177
178                 if filename ~= nil and
179                         filename ~= "" and
180                         filename:find(".lua") then
181                         return modmgr.identify_modname(modpath,filename)
182                 end
183         end
184         return nil
185 end
186
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()
192
193                 while line~= nil do
194                         local modname = nil
195
196                         if line:find("minetest.register_tool") then
197                                 modname = modmgr.parse_register_line(line)
198                         end
199
200                         if line:find("minetest.register_craftitem") then
201                                 modname = modmgr.parse_register_line(line)
202                         end
203
204
205                         if line:find("minetest.register_node") then
206                                 modname = modmgr.parse_register_line(line)
207                         end
208
209                         if line:find("dofile") then
210                                 modname = modmgr.parse_dofile_line(modpath,line)
211                         end
212
213                         if modname ~= nil then
214                                 testfile:close()
215                                 return modname
216                         end
217
218                         line = testfile:read()
219                 end
220                 testfile:close()
221         end
222
223         return nil
224 end
225
226 --------------------------------------------------------------------------------
227 function modmgr.tab()
228
229         if modmgr.global_mods == nil then
230                 modmgr.refresh_globals()
231         end
232
233         if modmgr.selected_mod == nil then
234                 modmgr.selected_mod = 1
235         end
236
237         local retval =
238                 "vertlabel[0,-0.25;".. fgettext("MODS") .. "]" ..
239                 "label[0.8,-0.25;".. fgettext("Installed Mods:") .. "]" ..
240                 "textlist[0.75,0.25;4.5,4;modlist;" ..
241                 modmgr.render_modlist(modmgr.global_mods) ..
242                 ";" .. modmgr.selected_mod .. "]"
243
244         retval = retval ..
245                 "label[0.8,4.2;" .. fgettext("Add mod:") .. "]" ..
246 --              TODO Disabled due to upcoming release 0.4.8 and irrlicht messing up localization
247 --              "button[0.75,4.85;1.8,0.5;btn_mod_mgr_install_local;".. fgettext("Local install") .. "]" ..
248                 "button[2.45,4.85;3.05,0.5;btn_mod_mgr_download;".. fgettext("Online mod repository") .. "]"
249
250         local selected_mod = nil
251
252         if filterlist.size(modmgr.global_mods) >= modmgr.selected_mod then
253                 selected_mod = filterlist.get_list(modmgr.global_mods)[modmgr.selected_mod]
254         end
255
256         if selected_mod ~= nil then
257                 local modscreenshot = nil
258
259                 --check for screenshot beeing available
260                 local screenshotfilename = selected_mod.path .. DIR_DELIM .. "screenshot.png"
261                 local error = nil
262                 screenshotfile,error = io.open(screenshotfilename,"r")
263                 if error == nil then
264                         screenshotfile:close()
265                         modscreenshot = screenshotfilename
266                 end
267
268                 if modscreenshot == nil then
269                                 modscreenshot = modstore.basetexturedir .. "no_screenshot.png"
270                 end
271
272                 retval = retval
273                                 .. "image[5.5,0;3,2;" .. engine.formspec_escape(modscreenshot) .. "]"
274                                 .. "label[8.25,0.6;" .. selected_mod.name .. "]"
275
276                 local descriptionlines = nil
277                 error = nil
278                 local descriptionfilename = selected_mod.path .. "description.txt"
279                 descriptionfile,error = io.open(descriptionfilename,"r")
280                 if error == nil then
281                         descriptiontext = descriptionfile:read("*all")
282
283                         descriptionlines = engine.splittext(descriptiontext,42)
284                         descriptionfile:close()
285                 else
286                         descriptionlines = {}
287                         table.insert(descriptionlines,fgettext("No mod description available"))
288                 end
289
290                 retval = retval ..
291                         "label[5.5,1.7;".. fgettext("Mod information:") .. "]" ..
292                         "textlist[5.5,2.2;6.2,2.4;description;"
293
294                 for i=1,#descriptionlines,1 do
295                         retval = retval .. engine.formspec_escape(descriptionlines[i]) .. ","
296                 end
297
298
299                 if selected_mod.is_modpack then
300                         retval = retval .. ";0]" ..
301                                 "button[10,4.85;2,0.5;btn_mod_mgr_rename_modpack;" ..
302                                 fgettext("Rename") .. "]"
303                         retval = retval .. "button[5.5,4.85;4.5,0.5;btn_mod_mgr_delete_mod;"
304                                 .. fgettext("Uninstall selected modpack") .. "]"
305                 else
306                         --show dependencies
307
308                         retval = retval .. ",Depends:,"
309
310                         toadd = modmgr.get_dependencies(selected_mod.path)
311
312                         retval = retval .. toadd .. ";0]"
313
314                         retval = retval .. "button[5.5,4.85;4.5,0.5;btn_mod_mgr_delete_mod;"
315                                 .. fgettext("Uninstall selected mod") .. "]"
316                 end
317         end
318         return retval
319 end
320
321 --------------------------------------------------------------------------------
322 function modmgr.dialog_rename_modpack()
323
324         local mod = filterlist.get_list(modmgr.global_mods)[modmgr.selected_mod]
325
326         local retval =
327                 "label[1.75,1;".. fgettext("Rename Modpack:") .. "]"..
328                 "field[4.5,1.4;6,0.5;te_modpack_name;;" ..
329                 mod.name ..
330                 "]" ..
331                 "button[5,4.2;2.6,0.5;dlg_rename_modpack_confirm;"..
332                                 fgettext("Accept") .. "]" ..
333                 "button[7.5,4.2;2.8,0.5;dlg_rename_modpack_cancel;"..
334                                 fgettext("Cancel") .. "]"
335
336         return retval
337 end
338
339 --------------------------------------------------------------------------------
340 function modmgr.precheck()
341
342         if modmgr.world_config_selected_world == nil then
343                 modmgr.world_config_selected_world = 1
344         end
345
346         if modmgr.world_config_selected_mod == nil then
347                 modmgr.world_config_selected_mod = 1
348         end
349
350         if modmgr.hide_gamemods == nil then
351                 modmgr.hide_gamemods = true
352         end
353
354         if modmgr.hide_modpackcontents == nil then
355                 modmgr.hide_modpackcontents = true
356         end
357 end
358
359 --------------------------------------------------------------------------------
360 function modmgr.render_modlist(render_list)
361         local retval = ""
362
363         if render_list == nil then
364                 if modmgr.global_mods == nil then
365                         modmgr.refresh_globals()
366                 end
367                 render_list = modmgr.global_mods
368         end
369
370         local list = filterlist.get_list(render_list)
371         local last_modpack = nil
372
373         for i,v in ipairs(list) do
374                 if retval ~= "" then
375                         retval = retval ..","
376                 end
377
378                 local color = ""
379
380                 if v.is_modpack then
381                         local rawlist = filterlist.get_raw_list(render_list)
382
383                         local all_enabled = true
384                         for j=1,#rawlist,1 do
385                                 if rawlist[j].modpack == list[i].name and
386                                         rawlist[j].enabled ~= true then
387                                                 all_enabled = false
388                                                 break
389                                 end
390                         end
391
392                         if all_enabled == false then
393                                 color = mt_color_grey
394                         else
395                                 color = mt_color_dark_green
396                         end
397                 end
398
399                 if v.typ == "game_mod" then
400                         color = mt_color_blue
401                 else
402                         if v.enabled then
403                                 color = mt_color_green
404                         end
405                 end
406
407                 retval = retval .. color
408                 if v.modpack  ~= nil then
409                         retval = retval .. "    "
410                 end
411                 retval = retval .. v.name
412         end
413
414         return retval
415 end
416
417 --------------------------------------------------------------------------------
418 function modmgr.dialog_configure_world()
419         modmgr.precheck()
420
421         local worldspec = engine.get_worlds()[modmgr.world_config_selected_world]
422         local mod = filterlist.get_list(modmgr.modlist)[modmgr.world_config_selected_mod]
423
424         local retval =
425                 "size[11,6.5]" ..
426                 "label[0.5,-0.25;" .. fgettext("World:") .. "]" ..
427                 "label[1.75,-0.25;" .. worldspec.name .. "]"
428
429         if modmgr.hide_gamemods then
430                 retval = retval .. "checkbox[0,5.75;cb_hide_gamemods;" .. fgettext("Hide Game") .. ";true]"
431         else
432                 retval = retval .. "checkbox[0,5.75;cb_hide_gamemods;" .. fgettext("Hide Game") .. ";false]"
433         end
434
435         if modmgr.hide_modpackcontents then
436                 retval = retval .. "checkbox[2,5.75;cb_hide_mpcontent;" .. fgettext("Hide mp content") .. ";true]"
437         else
438                 retval = retval .. "checkbox[2,5.75;cb_hide_mpcontent;" .. fgettext("Hide mp content") .. ";false]"
439         end
440
441         if mod == nil then
442                 mod = {name=""}
443         end
444         retval = retval ..
445                 "label[0,0.45;" .. fgettext("Mod:") .. "]" ..
446                 "label[0.75,0.45;" .. mod.name .. "]" ..
447                 "label[0,1;" .. fgettext("Depends:") .. "]" ..
448                 "textlist[0,1.5;5,4.25;world_config_depends;" ..
449                 modmgr.get_dependencies(mod.path) .. ";0]" ..
450                 "button[9.25,6.35;2,0.5;btn_config_world_save;" .. fgettext("Save") .. "]" ..
451                 "button[7.4,6.35;2,0.5;btn_config_world_cancel;" .. fgettext("Cancel") .. "]"
452
453         if mod ~= nil and mod.name ~= "" and mod.typ ~= "game_mod" then
454                 if mod.is_modpack then
455                         local rawlist = filterlist.get_raw_list(modmgr.modlist)
456
457                         local all_enabled = true
458                         for j=1,#rawlist,1 do
459                                 if rawlist[j].modpack == mod.name and
460                                         rawlist[j].enabled ~= true then
461                                                 all_enabled = false
462                                                 break
463                                 end
464                         end
465
466                         if all_enabled == false then
467                                 retval = retval .. "button[5.5,-0.125;2,0.5;btn_mp_enable;" .. fgettext("Enable MP") .. "]"
468                         else
469                                 retval = retval .. "button[5.5,-0.125;2,0.5;btn_mp_disable;" .. fgettext("Disable MP") .. "]"
470                         end
471                 else
472                         if mod.enabled then
473                                 retval = retval .. "checkbox[5.5,-0.375;cb_mod_enable;" .. fgettext("enabled") .. ";true]"
474                         else
475                                 retval = retval .. "checkbox[5.5,-0.375;cb_mod_enable;" .. fgettext("enabled") .. ";false]"
476                         end
477                 end
478         end
479
480         retval = retval ..
481                 "button[8.5,-0.125;2.5,0.5;btn_all_mods;" .. fgettext("Enable all") .. "]" ..
482                 "textlist[5.5,0.5;5.5,5.75;world_config_modlist;"
483
484         retval = retval .. modmgr.render_modlist(modmgr.modlist)
485
486         retval = retval .. ";" .. modmgr.world_config_selected_mod .."]"
487
488         return retval
489 end
490
491 --------------------------------------------------------------------------------
492 function modmgr.handle_buttons(tab,fields)
493
494         local retval = nil
495
496         if tab == "mod_mgr" then
497                 retval = modmgr.handle_modmgr_buttons(fields)
498         end
499
500         if tab == "dialog_rename_modpack" then
501                 retval = modmgr.handle_rename_modpack_buttons(fields)
502         end
503
504         if tab == "dialog_delete_mod" then
505                 retval = modmgr.handle_delete_mod_buttons(fields)
506         end
507
508         if tab == "dialog_configure_world" then
509                 retval = modmgr.handle_configure_world_buttons(fields)
510         end
511
512         return retval
513 end
514
515 --------------------------------------------------------------------------------
516 function modmgr.get_dependencies(modfolder)
517         local toadd = ""
518         if modfolder ~= nil then
519                 local filename = modfolder ..
520                                         DIR_DELIM .. "depends.txt"
521
522                 local dependencyfile = io.open(filename,"r")
523
524                 if dependencyfile then
525                         local dependency = dependencyfile:read("*l")
526                         while dependency do
527                                 if toadd ~= "" then
528                                         toadd = toadd .. ","
529                                 end
530                                 toadd = toadd .. dependency
531                                 dependency = dependencyfile:read()
532                         end
533                         dependencyfile:close()
534                 end
535         end
536
537         return toadd
538 end
539
540
541 --------------------------------------------------------------------------------
542 function modmgr.get_worldconfig(worldpath)
543         local filename = worldpath ..
544                                 DIR_DELIM .. "world.mt"
545
546         local worldfile = Settings(filename)
547
548         local worldconfig = {}
549         worldconfig.global_mods = {}
550         worldconfig.game_mods = {}
551
552         for key,value in pairs(worldfile:to_table()) do
553                 if key == "gameid" then
554                         worldconfig.id = value
555                 else
556                         worldconfig.global_mods[key] = engine.is_yes(value)
557                 end
558         end
559
560         --read gamemods
561         local gamespec = gamemgr.find_by_gameid(worldconfig.id)
562         gamemgr.get_game_mods(gamespec, worldconfig.game_mods)
563
564         return worldconfig
565 end
566 --------------------------------------------------------------------------------
567 function modmgr.handle_modmgr_buttons(fields)
568         local retval = {
569                         tab = nil,
570                         is_dialog = nil,
571                         show_buttons = nil,
572                 }
573
574         if fields["modlist"] ~= nil then
575                 local event = explode_textlist_event(fields["modlist"])
576                 modmgr.selected_mod = event.index
577         end
578
579         if fields["btn_mod_mgr_install_local"] ~= nil then
580                 engine.show_file_open_dialog("mod_mgt_open_dlg",fgettext("Select Mod File:"))
581         end
582
583         if fields["btn_mod_mgr_download"] ~= nil then
584                 modstore.update_modlist()
585                 retval.current_tab = "dialog_modstore_unsorted"
586                 retval.is_dialog = true
587                 retval.show_buttons = false
588                 return retval
589         end
590
591         if fields["btn_mod_mgr_rename_modpack"] ~= nil then
592                 retval.current_tab = "dialog_rename_modpack"
593                 retval.is_dialog = true
594                 retval.show_buttons = false
595                 return retval
596         end
597
598         if fields["btn_mod_mgr_delete_mod"] ~= nil then
599                 retval.current_tab = "dialog_delete_mod"
600                 retval.is_dialog = true
601                 retval.show_buttons = false
602                 return retval
603         end
604
605         if fields["mod_mgt_open_dlg_accepted"] ~= nil and
606                 fields["mod_mgt_open_dlg_accepted"] ~= "" then
607                 modmgr.installmod(fields["mod_mgt_open_dlg_accepted"],nil)
608         end
609
610         return nil;
611 end
612
613 --------------------------------------------------------------------------------
614 function modmgr.installmod(modfilename,basename)
615         local modfile = modmgr.identify_filetype(modfilename)
616         local modpath = modmgr.extract(modfile)
617
618         if modpath == nil then
619                 gamedata.errormessage = fgettext("Install Mod: file: \"$1\"", modfile.name) ..
620                         fgettext("\nInstall Mod: unsupported filetype \"$1\" or broken archive", modfile.type)
621                 return
622         end
623
624
625         local basefolder = modmgr.getbasefolder(modpath)
626
627         if basefolder.type == "modpack" then
628                 local clean_path = nil
629
630                 if basename ~= nil then
631                         clean_path = "mp_" .. basename
632                 end
633
634                 if clean_path == nil then
635                         clean_path = get_last_folder(cleanup_path(basefolder.path))
636                 end
637
638                 if clean_path ~= nil then
639                         local targetpath = engine.get_modpath() .. DIR_DELIM .. clean_path
640                         if not engine.copy_dir(basefolder.path,targetpath) then
641                                 gamedata.errormessage = fgettext("Failed to install $1 to $2", basename, targetpath)
642                         end
643                 else
644                         gamedata.errormessage = fgettext("Install Mod: unable to find suitable foldername for modpack $1", modfilename)
645                 end
646         end
647
648         if basefolder.type == "mod" then
649                 local targetfolder = basename
650
651                 if targetfolder == nil then
652                         targetfolder = modmgr.identify_modname(basefolder.path,"init.lua")
653                 end
654
655                 --if heuristic failed try to use current foldername
656                 if targetfolder == nil then
657                         targetfolder = get_last_folder(basefolder.path)
658                 end
659
660                 if targetfolder ~= nil and modmgr.isValidModname(targetfolder) then
661                         local targetpath = engine.get_modpath() .. DIR_DELIM .. targetfolder
662                         engine.copy_dir(basefolder.path,targetpath)
663                 else
664                         gamedata.errormessage = fgettext("Install Mod: unable to find real modname for: $1", modfilename)
665                 end
666         end
667
668         engine.delete_dir(modpath)
669
670         modmgr.refresh_globals()
671
672 end
673
674 --------------------------------------------------------------------------------
675 function modmgr.handle_rename_modpack_buttons(fields)
676
677         if fields["dlg_rename_modpack_confirm"] ~= nil then
678                 local mod = filterlist.get_list(modmgr.global_mods)[modmgr.selected_mod]
679                 local oldpath = engine.get_modpath() .. DIR_DELIM .. mod.name
680                 local targetpath = engine.get_modpath() .. DIR_DELIM .. fields["te_modpack_name"]
681                 engine.copy_dir(oldpath,targetpath,false)
682                 modmgr.refresh_globals()
683                 modmgr.selected_mod = filterlist.get_current_index(modmgr.global_mods,
684                         filterlist.raw_index_by_uid(modmgr.global_mods, fields["te_modpack_name"]))
685         end
686
687         return {
688                 is_dialog = false,
689                 show_buttons = true,
690                 current_tab = engine.setting_get("main_menu_tab")
691                 }
692 end
693 --------------------------------------------------------------------------------
694 function modmgr.handle_configure_world_buttons(fields)
695         if fields["world_config_modlist"] ~= nil then
696                 local event = explode_textlist_event(fields["world_config_modlist"])
697                 modmgr.world_config_selected_mod = event.index
698
699                 if event.typ == "DCL" then
700                         modmgr.world_config_enable_mod(nil)
701                 end
702         end
703
704         if fields["key_enter"] ~= nil then
705                 modmgr.world_config_enable_mod(nil)
706         end
707
708         if fields["cb_mod_enable"] ~= nil then
709                 local toset = engine.is_yes(fields["cb_mod_enable"])
710                 modmgr.world_config_enable_mod(toset)
711         end
712
713         if fields["btn_mp_enable"] ~= nil or
714                 fields["btn_mp_disable"] then
715                 local toset = (fields["btn_mp_enable"] ~= nil)
716                 modmgr.world_config_enable_mod(toset)
717         end
718
719         if fields["cb_hide_gamemods"] ~= nil then
720                 local current = filterlist.get_filtercriteria(modmgr.modlist)
721
722                 if current == nil then
723                         current = {}
724                 end
725
726                 if engine.is_yes(fields["cb_hide_gamemods"]) then
727                         current.hide_game = true
728                         modmgr.hide_gamemods = true
729                 else
730                         current.hide_game = false
731                         modmgr.hide_gamemods = false
732                 end
733
734                 filterlist.set_filtercriteria(modmgr.modlist,current)
735         end
736
737                 if fields["cb_hide_mpcontent"] ~= nil then
738                 local current = filterlist.get_filtercriteria(modmgr.modlist)
739
740                 if current == nil then
741                         current = {}
742                 end
743
744                 if engine.is_yes(fields["cb_hide_mpcontent"]) then
745                         current.hide_modpackcontents = true
746                         modmgr.hide_modpackcontents = true
747                 else
748                         current.hide_modpackcontents = false
749                         modmgr.hide_modpackcontents = false
750                 end
751
752                 filterlist.set_filtercriteria(modmgr.modlist,current)
753         end
754
755         if fields["btn_config_world_save"] then
756                 local worldspec = engine.get_worlds()[modmgr.world_config_selected_world]
757
758                 local filename = worldspec.path ..
759                                 DIR_DELIM .. "world.mt"
760
761                 local worldfile = Settings(filename)
762                 local mods = worldfile:to_table()
763
764                 local rawlist = filterlist.get_raw_list(modmgr.modlist)
765
766                 local i,mod
767                 for i,mod in ipairs(rawlist) do
768                         if not mod.is_modpack and
769                                         mod.typ ~= "game_mod" then
770                                 if mod.enabled then
771                                         worldfile:set("load_mod_"..mod.name, "true")
772                                 else
773                                         worldfile:set("load_mod_"..mod.name, "false")
774                                 end
775                                 mods["load_mod_"..mod.name] = nil
776                         end
777                 end
778
779                 -- Remove mods that are not present anymore
780                 for key,value in pairs(mods) do
781                         if key:sub(1,9) == "load_mod_" then
782                                 worldfile:remove(key)
783                         end
784                 end
785
786                 if not worldfile:write() then
787                         engine.log("error", "Failed to write world config file")
788                 end
789
790                 modmgr.modlist = nil
791                 modmgr.worldconfig = nil
792
793                 return {
794                         is_dialog = false,
795                         show_buttons = true,
796                         current_tab = engine.setting_get("main_menu_tab")
797                 }
798         end
799
800         if fields["btn_config_world_cancel"] then
801
802                 modmgr.worldconfig = nil
803
804                 return {
805                         is_dialog = false,
806                         show_buttons = true,
807                         current_tab = engine.setting_get("main_menu_tab")
808                 }
809         end
810
811         if fields["btn_all_mods"] then
812                 local list = filterlist.get_raw_list(modmgr.modlist)
813
814                 for i=1,#list,1 do
815                         if list[i].typ ~= "game_mod" and
816                                 not list[i].is_modpack then
817                                 list[i].enabled = true
818                         end
819                 end
820         end
821
822
823
824         return nil
825 end
826 --------------------------------------------------------------------------------
827 function modmgr.world_config_enable_mod(toset)
828         local mod = filterlist.get_list(modmgr.modlist)
829                 [engine.get_textlist_index("world_config_modlist")]
830
831         if mod.typ == "game_mod" then
832                 -- game mods can't be enabled or disabled
833         elseif not mod.is_modpack then
834                 if toset == nil then
835                         mod.enabled = not mod.enabled
836                 else
837                         mod.enabled = toset
838                 end
839         else
840                 local list = filterlist.get_raw_list(modmgr.modlist)
841                 for i=1,#list,1 do
842                         if list[i].modpack == mod.name then
843                                 if toset == nil then
844                                         toset = not list[i].enabled
845                                 end
846                                 list[i].enabled = toset
847                         end
848                 end
849         end
850 end
851 --------------------------------------------------------------------------------
852 function modmgr.handle_delete_mod_buttons(fields)
853         local mod = filterlist.get_list(modmgr.global_mods)[modmgr.selected_mod]
854
855         if fields["dlg_delete_mod_confirm"] ~= nil then
856
857                 if mod.path ~= nil and
858                         mod.path ~= "" and
859                         mod.path ~= engine.get_modpath() then
860                         if not engine.delete_dir(mod.path) then
861                                 gamedata.errormessage = fgettext("Modmgr: failed to delete \"$1\"", mod.path)
862                         end
863                         modmgr.refresh_globals()
864                 else
865                         gamedata.errormessage = fgettext("Modmgr: invalid modpath \"$1\"", mod.path)
866                 end
867         end
868
869         return {
870                 is_dialog = false,
871                 show_buttons = true,
872                 current_tab = engine.setting_get("main_menu_tab")
873                 }
874 end
875
876 --------------------------------------------------------------------------------
877 function modmgr.dialog_delete_mod()
878
879         local mod = filterlist.get_list(modmgr.global_mods)[modmgr.selected_mod]
880
881         local retval =
882                 "field[1.75,1;10,3;;" .. fgettext("Are you sure you want to delete \"$1\"?", mod.name) ..  ";]"..
883                 "button[4,4.2;1,0.5;dlg_delete_mod_confirm;" .. fgettext("Yes") .. "]" ..
884                 "button[6.5,4.2;3,0.5;dlg_delete_mod_cancel;" .. fgettext("No of course not!") .. "]"
885
886         return retval
887 end
888
889 --------------------------------------------------------------------------------
890 function modmgr.preparemodlist(data)
891         local retval = {}
892
893         local global_mods = {}
894         local game_mods = {}
895
896         --read global mods
897         local modpath = engine.get_modpath()
898
899         if modpath ~= nil and
900                 modpath ~= "" then
901                 get_mods(modpath,global_mods)
902         end
903
904         for i=1,#global_mods,1 do
905                 global_mods[i].typ = "global_mod"
906                 table.insert(retval,global_mods[i])
907         end
908
909         --read game mods
910         local gamespec = gamemgr.find_by_gameid(data.gameid)
911         gamemgr.get_game_mods(gamespec, game_mods)
912
913         for i=1,#game_mods,1 do
914                 game_mods[i].typ = "game_mod"
915                 table.insert(retval,game_mods[i])
916         end
917
918         if data.worldpath == nil then
919                 return retval
920         end
921
922         --read world mod configuration
923         local filename = data.worldpath ..
924                                 DIR_DELIM .. "world.mt"
925
926         local worldfile = Settings(filename)
927
928         for key,value in pairs(worldfile:to_table()) do
929                 if key:sub(1, 9) == "load_mod_" then
930                         key = key:sub(10)
931                         local element = nil
932                         for i=1,#retval,1 do
933                                 if retval[i].name == key then
934                                         element = retval[i]
935                                         break
936                                 end
937                         end
938                         if element ~= nil then
939                                 element.enabled = engine.is_yes(value)
940                         else
941                                 engine.log("info", "Mod: " .. key .. " " .. dump(value) .. " but not found")
942                         end
943                 end
944         end
945
946         return retval
947 end
948
949 --------------------------------------------------------------------------------
950 function modmgr.init_worldconfig()
951         modmgr.precheck()
952         local worldspec = engine.get_worlds()[modmgr.world_config_selected_world]
953
954         if worldspec ~= nil then
955                 --read worldconfig
956                 modmgr.worldconfig = modmgr.get_worldconfig(worldspec.path)
957
958                 if modmgr.worldconfig.id == nil or
959                         modmgr.worldconfig.id == "" then
960                         modmgr.worldconfig = nil
961                         return false
962                 end
963
964                 modmgr.modlist = filterlist.create(
965                                                 modmgr.preparemodlist, --refresh
966                                                 modmgr.comparemod, --compare
967                                                 function(element,uid) --uid match
968                                                         if element.name == uid then
969                                                                 return true
970                                                         end
971                                                 end,
972                                                 function(element,criteria)
973                                                         if criteria.hide_game and
974                                                                 element.typ == "game_mod" then
975                                                                         return false
976                                                         end
977
978                                                         if criteria.hide_modpackcontents and
979                                                                 element.modpack ~= nil then
980                                                                         return false
981                                                                 end
982                                                         return true
983                                                 end, --filter
984                                                 { worldpath= worldspec.path,
985                                                   gameid = worldspec.gameid }
986                                         )
987
988                 filterlist.set_filtercriteria(modmgr.modlist, {
989                                                                         hide_game=modmgr.hide_gamemods,
990                                                                         hide_modpackcontents= modmgr.hide_modpackcontents
991                                                                         })
992                 filterlist.add_sort_mechanism(modmgr.modlist, "alphabetic", sort_mod_list)
993                 filterlist.set_sortmode(modmgr.modlist, "alphabetic")
994
995                 return true
996         end
997
998         return false
999 end
1000
1001 --------------------------------------------------------------------------------
1002 function modmgr.comparemod(elem1,elem2)
1003         if elem1 == nil or elem2 == nil then
1004                 return false
1005         end
1006         if elem1.name ~= elem2.name then
1007                 return false
1008         end
1009         if elem1.is_modpack ~= elem2.is_modpack then
1010                 return false
1011         end
1012         if elem1.typ ~= elem2.typ then
1013                 return false
1014         end
1015         if elem1.modpack ~= elem2.modpack then
1016                 return false
1017         end
1018
1019         if elem1.path ~= elem2.path then
1020                 return false
1021         end
1022
1023         return true
1024 end
1025
1026 --------------------------------------------------------------------------------
1027 function modmgr.gettab(name)
1028         local retval = ""
1029
1030         if name == "mod_mgr" then
1031                 retval = retval .. modmgr.tab()
1032         end
1033
1034         if name == "dialog_rename_modpack" then
1035                 retval = retval .. modmgr.dialog_rename_modpack()
1036         end
1037
1038         if name == "dialog_delete_mod" then
1039                 retval = retval .. modmgr.dialog_delete_mod()
1040         end
1041
1042         if name == "dialog_configure_world" then
1043                 retval = retval .. modmgr.dialog_configure_world()
1044         end
1045
1046         return retval
1047 end
1048
1049 --------------------------------------------------------------------------------
1050 function modmgr.mod_exists(basename)
1051
1052         if modmgr.global_mods == nil then
1053                 modmgr.refresh_globals()
1054         end
1055
1056         if filterlist.raw_index_by_uid(modmgr.global_mods,basename) > 0 then
1057                 return true
1058         end
1059
1060         return false
1061 end
1062
1063 --------------------------------------------------------------------------------
1064 function modmgr.get_global_mod(idx)
1065
1066         if modmgr.global_mods == nil then
1067                 return nil
1068         end
1069
1070         if idx < 1 or idx > filterlist.size(modmgr.global_mods) then
1071                 return nil
1072         end
1073
1074         return filterlist.get_list(modmgr.global_mods)[idx]
1075 end
1076
1077 --------------------------------------------------------------------------------
1078 function modmgr.refresh_globals()
1079         modmgr.global_mods = filterlist.create(
1080                                         modmgr.preparemodlist, --refresh
1081                                         modmgr.comparemod, --compare
1082                                         function(element,uid) --uid match
1083                                                 if element.name == uid then
1084                                                         return true
1085                                                 end
1086                                         end,
1087                                         nil, --filter
1088                                         {}
1089                                         )
1090         filterlist.add_sort_mechanism(modmgr.global_mods, "alphabetic", sort_mod_list)
1091         filterlist.set_sortmode(modmgr.global_mods, "alphabetic")
1092 end
1093
1094 --------------------------------------------------------------------------------
1095 function modmgr.identify_filetype(name)
1096
1097         if name:sub(-3):lower() == "zip" then
1098                 return {
1099                                 name = name,
1100                                 type = "zip"
1101                                 }
1102         end
1103
1104         if name:sub(-6):lower() == "tar.gz" or
1105                 name:sub(-3):lower() == "tgz"then
1106                 return {
1107                                 name = name,
1108                                 type = "tgz"
1109                                 }
1110         end
1111
1112         if name:sub(-6):lower() == "tar.bz2" then
1113                 return {
1114                                 name = name,
1115                                 type = "tbz"
1116                                 }
1117         end
1118
1119         if name:sub(-2):lower() == "7z" then
1120                 return {
1121                                 name = name,
1122                                 type = "7z"
1123                                 }
1124         end
1125
1126         return {
1127                 name = name,
1128                 type = "ukn"
1129         }
1130 end