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