modmgr.lua 26 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082
  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. function get_mods(path,retval,modpack)
  19. local mods = engine.get_dirlist(path,true)
  20. for i=1,#mods,1 do
  21. local toadd = {}
  22. local modpackfile = nil
  23. toadd.name = mods[i]
  24. toadd.path = path .. DIR_DELIM .. mods[i] .. DIR_DELIM
  25. if modpack ~= nil and
  26. modpack ~= "" then
  27. toadd.modpack = modpack
  28. else
  29. local filename = path .. DIR_DELIM .. mods[i] .. DIR_DELIM .. "modpack.txt"
  30. local error = nil
  31. modpackfile,error = io.open(filename,"r")
  32. end
  33. if modpackfile ~= nil then
  34. modpackfile:close()
  35. toadd.is_modpack = true
  36. table.insert(retval,toadd)
  37. get_mods(path .. DIR_DELIM .. mods[i],retval,mods[i])
  38. else
  39. table.insert(retval,toadd)
  40. end
  41. end
  42. end
  43. --modmanager implementation
  44. modmgr = {}
  45. --------------------------------------------------------------------------------
  46. function modmgr.extract(modfile)
  47. if modfile.type == "zip" then
  48. local tempfolder = os.tempfolder()
  49. if tempfolder ~= nil and
  50. tempfodler ~= "" then
  51. engine.create_dir(tempfolder)
  52. engine.extract_zip(modfile.name,tempfolder)
  53. return tempfolder
  54. end
  55. end
  56. end
  57. -------------------------------------------------------------------------------
  58. function modmgr.getbasefolder(temppath)
  59. if temppath == nil then
  60. return {
  61. type = "invalid",
  62. path = ""
  63. }
  64. end
  65. local testfile = io.open(temppath .. DIR_DELIM .. "init.lua","r")
  66. if testfile ~= nil then
  67. testfile:close()
  68. return {
  69. type="mod",
  70. path=temppath
  71. }
  72. end
  73. testfile = io.open(temppath .. DIR_DELIM .. "modpack.txt","r")
  74. if testfile ~= nil then
  75. testfile:close()
  76. return {
  77. type="modpack",
  78. path=temppath
  79. }
  80. end
  81. local subdirs = engine.get_dirlist(temppath,true)
  82. --only single mod or modpack allowed
  83. if #subdirs ~= 1 then
  84. return {
  85. type = "invalid",
  86. path = ""
  87. }
  88. end
  89. testfile =
  90. io.open(temppath .. DIR_DELIM .. subdirs[1] ..DIR_DELIM .."init.lua","r")
  91. if testfile ~= nil then
  92. testfile:close()
  93. return {
  94. type="mod",
  95. path= temppath .. DIR_DELIM .. subdirs[1]
  96. }
  97. end
  98. testfile =
  99. io.open(temppath .. DIR_DELIM .. subdirs[1] ..DIR_DELIM .."modpack.txt","r")
  100. if testfile ~= nil then
  101. testfile:close()
  102. return {
  103. type="modpack",
  104. path=temppath .. DIR_DELIM .. subdirs[1]
  105. }
  106. end
  107. return {
  108. type = "invalid",
  109. path = ""
  110. }
  111. end
  112. --------------------------------------------------------------------------------
  113. function modmgr.isValidModname(modpath)
  114. if modpath:find("-") ~= nil then
  115. return false
  116. end
  117. return true
  118. end
  119. --------------------------------------------------------------------------------
  120. function modmgr.parse_register_line(line)
  121. local pos1 = line:find("\"")
  122. local pos2 = nil
  123. if pos1 ~= nil then
  124. pos2 = line:find("\"",pos1+1)
  125. end
  126. if pos1 ~= nil and pos2 ~= nil then
  127. local item = line:sub(pos1+1,pos2-1)
  128. if item ~= nil and
  129. item ~= "" then
  130. local pos3 = item:find(":")
  131. if pos3 ~= nil then
  132. local retval = item:sub(1,pos3-1)
  133. if retval ~= nil and
  134. retval ~= "" then
  135. return retval
  136. end
  137. end
  138. end
  139. end
  140. return nil
  141. end
  142. --------------------------------------------------------------------------------
  143. function modmgr.parse_dofile_line(modpath,line)
  144. local pos1 = line:find("\"")
  145. local pos2 = nil
  146. if pos1 ~= nil then
  147. pos2 = line:find("\"",pos1+1)
  148. end
  149. if pos1 ~= nil and pos2 ~= nil then
  150. local filename = line:sub(pos1+1,pos2-1)
  151. if filename ~= nil and
  152. filename ~= "" and
  153. filename:find(".lua") then
  154. return modmgr.identify_modname(modpath,filename)
  155. end
  156. end
  157. return nil
  158. end
  159. --------------------------------------------------------------------------------
  160. function modmgr.identify_modname(modpath,filename)
  161. local testfile = io.open(modpath .. DIR_DELIM .. filename,"r")
  162. if testfile ~= nil then
  163. local line = testfile:read()
  164. while line~= nil do
  165. local modname = nil
  166. if line:find("minetest.register_tool") then
  167. modname = modmgr.parse_register_line(line)
  168. end
  169. if line:find("minetest.register_craftitem") then
  170. modname = modmgr.parse_register_line(line)
  171. end
  172. if line:find("minetest.register_node") then
  173. modname = modmgr.parse_register_line(line)
  174. end
  175. if line:find("dofile") then
  176. modname = modmgr.parse_dofile_line(modpath,line)
  177. end
  178. if modname ~= nil then
  179. testfile:close()
  180. return modname
  181. end
  182. line = testfile:read()
  183. end
  184. testfile:close()
  185. end
  186. return nil
  187. end
  188. --------------------------------------------------------------------------------
  189. function modmgr.tab()
  190. if modmgr.global_mods == nil then
  191. modmgr.refresh_globals()
  192. end
  193. if modmgr.selected_mod == nil then
  194. modmgr.selected_mod = 1
  195. end
  196. local retval =
  197. "vertlabel[0,-0.25;".. fgettext("MODS") .. "]" ..
  198. "label[0.8,-0.25;".. fgettext("Installed Mods:") .. "]" ..
  199. "textlist[0.75,0.25;4.5,4.3;modlist;" ..
  200. modmgr.render_modlist(modmgr.global_mods) ..
  201. ";" .. modmgr.selected_mod .. "]"
  202. retval = retval ..
  203. "button[1,4.85;2,0.5;btn_mod_mgr_install_local;".. fgettext("Install") .. "]" ..
  204. "button[3,4.85;2,0.5;btn_mod_mgr_download;".. fgettext("Download") .. "]"
  205. local selected_mod = nil
  206. if filterlist.size(modmgr.global_mods) >= modmgr.selected_mod then
  207. selected_mod = filterlist.get_list(modmgr.global_mods)[modmgr.selected_mod]
  208. end
  209. if selected_mod ~= nil then
  210. if selected_mod.is_modpack then
  211. retval = retval
  212. .. "button[10,4.85;2,0.5;btn_mod_mgr_rename_modpack;" ..
  213. fgettext("Rename") .. "]"
  214. else
  215. --show dependencies
  216. retval = retval ..
  217. "label[6,1.9;".. fgettext("Depends:") .. "]" ..
  218. "textlist[6,2.4;5.7,2;deplist;"
  219. toadd = modmgr.get_dependencies(selected_mod.path)
  220. retval = retval .. toadd .. ";0;true,false]"
  221. --TODO read modinfo
  222. end
  223. --show delete button
  224. retval = retval .. "button[8,4.85;2,0.5;btn_mod_mgr_delete_mod;"
  225. .. fgettext("Delete") .. "]"
  226. end
  227. return retval
  228. end
  229. --------------------------------------------------------------------------------
  230. function modmgr.dialog_rename_modpack()
  231. local mod = filterlist.get_list(modmgr.modlist)[modmgr.selected_mod]
  232. local retval =
  233. "label[1.75,1;".. fgettext("Rename Modpack:") .. "]"..
  234. "field[4.5,1.4;6,0.5;te_modpack_name;;" ..
  235. mod.name ..
  236. "]" ..
  237. "button[5,4.2;2.6,0.5;dlg_rename_modpack_confirm;"..
  238. fgettext("Accept") .. "]" ..
  239. "button[7.5,4.2;2.8,0.5;dlg_rename_modpack_cancel;"..
  240. fgettext("Cancel") .. "]"
  241. return retval
  242. end
  243. --------------------------------------------------------------------------------
  244. function modmgr.precheck()
  245. if modmgr.world_config_selected_world == nil then
  246. modmgr.world_config_selected_world = 1
  247. end
  248. if modmgr.world_config_selected_mod == nil then
  249. modmgr.world_config_selected_mod = 1
  250. end
  251. if modmgr.hide_gamemods == nil then
  252. modmgr.hide_gamemods = true
  253. end
  254. if modmgr.hide_modpackcontents == nil then
  255. modmgr.hide_modpackcontents = true
  256. end
  257. end
  258. --------------------------------------------------------------------------------
  259. function modmgr.render_modlist(render_list)
  260. local retval = ""
  261. if render_list == nil then
  262. if modmgr.global_mods == nil then
  263. modmgr.refresh_globals()
  264. end
  265. render_list = modmgr.global_mods
  266. end
  267. local list = filterlist.get_list(render_list)
  268. local last_modpack = nil
  269. for i,v in ipairs(list) do
  270. if retval ~= "" then
  271. retval = retval ..","
  272. end
  273. local color = ""
  274. if v.is_modpack then
  275. local rawlist = filterlist.get_raw_list(render_list)
  276. local all_enabled = true
  277. for j=1,#rawlist,1 do
  278. if rawlist[j].modpack == list[i].name and
  279. rawlist[j].enabled ~= true then
  280. all_enabled = false
  281. break
  282. end
  283. end
  284. if all_enabled == false then
  285. color = mt_color_grey
  286. else
  287. color = mt_color_dark_green
  288. end
  289. end
  290. if v.typ == "game_mod" then
  291. color = mt_color_blue
  292. else
  293. if v.enabled then
  294. color = mt_color_green
  295. end
  296. end
  297. retval = retval .. color
  298. if v.modpack ~= nil then
  299. retval = retval .. " "
  300. end
  301. retval = retval .. v.name
  302. end
  303. return retval
  304. end
  305. --------------------------------------------------------------------------------
  306. function modmgr.dialog_configure_world()
  307. modmgr.precheck()
  308. local worldspec = engine.get_worlds()[modmgr.world_config_selected_world]
  309. local mod = filterlist.get_list(modmgr.modlist)[modmgr.world_config_selected_mod]
  310. local retval =
  311. "size[11,6.5]" ..
  312. "label[0.5,-0.25;" .. fgettext("World:") .. "]" ..
  313. "label[1.75,-0.25;" .. worldspec.name .. "]"
  314. if modmgr.hide_gamemods then
  315. retval = retval .. "checkbox[0,5.75;cb_hide_gamemods;" .. fgettext("Hide Game") .. ";true]"
  316. else
  317. retval = retval .. "checkbox[0,5.75;cb_hide_gamemods;" .. fgettext("Hide Game") .. ";false]"
  318. end
  319. if modmgr.hide_modpackcontents then
  320. retval = retval .. "checkbox[2,5.75;cb_hide_mpcontent;" .. fgettext("Hide mp content") .. ";true]"
  321. else
  322. retval = retval .. "checkbox[2,5.75;cb_hide_mpcontent;" .. fgettext("Hide mp content") .. ";false]"
  323. end
  324. if mod == nil then
  325. mod = {name=""}
  326. end
  327. retval = retval ..
  328. "label[0,0.45;" .. fgettext("Mod:") .. "]" ..
  329. "label[0.75,0.45;" .. mod.name .. "]" ..
  330. "label[0,1;" .. fgettext("Depends:") .. "]" ..
  331. "textlist[0,1.5;5,4.25;world_config_depends;" ..
  332. modmgr.get_dependencies(mod.path) .. ";0]" ..
  333. "button[9.25,6.35;2,0.5;btn_config_world_save;" .. fgettext("Save") .. "]" ..
  334. "button[7.4,6.35;2,0.5;btn_config_world_cancel;" .. fgettext("Cancel") .. "]"
  335. if mod ~= nil and mod.name ~= "" and mod.typ ~= "game_mod" then
  336. if mod.is_modpack then
  337. local rawlist = filterlist.get_raw_list(modmgr.modlist)
  338. local all_enabled = true
  339. for j=1,#rawlist,1 do
  340. if rawlist[j].modpack == mod.name and
  341. rawlist[j].enabled ~= true then
  342. all_enabled = false
  343. break
  344. end
  345. end
  346. if all_enabled == false then
  347. retval = retval .. "button[5.5,-0.125;2,0.5;btn_mp_enable;" .. fgettext("Enable MP") .. "]"
  348. else
  349. retval = retval .. "button[5.5,-0.125;2,0.5;btn_mp_disable;" .. fgettext("Disable MP") .. "]"
  350. end
  351. else
  352. if mod.enabled then
  353. retval = retval .. "checkbox[5.5,-0.375;cb_mod_enable;" .. fgettext("enabled") .. ";true]"
  354. else
  355. retval = retval .. "checkbox[5.5,-0.375;cb_mod_enable;" .. fgettext("enabled") .. ";false]"
  356. end
  357. end
  358. end
  359. retval = retval ..
  360. "button[8.5,-0.125;2.5,0.5;btn_all_mods;" .. fgettext("Enable all") .. "]" ..
  361. "textlist[5.5,0.5;5.5,5.75;world_config_modlist;"
  362. retval = retval .. modmgr.render_modlist(modmgr.modlist)
  363. retval = retval .. ";" .. modmgr.world_config_selected_mod .."]"
  364. return retval
  365. end
  366. --------------------------------------------------------------------------------
  367. function modmgr.handle_buttons(tab,fields)
  368. local retval = nil
  369. if tab == "mod_mgr" then
  370. retval = modmgr.handle_modmgr_buttons(fields)
  371. end
  372. if tab == "dialog_rename_modpack" then
  373. retval = modmgr.handle_rename_modpack_buttons(fields)
  374. end
  375. if tab == "dialog_delete_mod" then
  376. retval = modmgr.handle_delete_mod_buttons(fields)
  377. end
  378. if tab == "dialog_configure_world" then
  379. retval = modmgr.handle_configure_world_buttons(fields)
  380. end
  381. return retval
  382. end
  383. --------------------------------------------------------------------------------
  384. function modmgr.get_dependencies(modfolder)
  385. local toadd = ""
  386. if modfolder ~= nil then
  387. local filename = modfolder ..
  388. DIR_DELIM .. "depends.txt"
  389. local dependencyfile = io.open(filename,"r")
  390. if dependencyfile then
  391. local dependency = dependencyfile:read("*l")
  392. while dependency do
  393. if toadd ~= "" then
  394. toadd = toadd .. ","
  395. end
  396. toadd = toadd .. dependency
  397. dependency = dependencyfile:read()
  398. end
  399. dependencyfile:close()
  400. end
  401. end
  402. return toadd
  403. end
  404. --------------------------------------------------------------------------------
  405. function modmgr.get_worldconfig(worldpath)
  406. local filename = worldpath ..
  407. DIR_DELIM .. "world.mt"
  408. local worldfile = Settings(filename)
  409. local worldconfig = {}
  410. worldconfig.global_mods = {}
  411. worldconfig.game_mods = {}
  412. for key,value in pairs(worldfile:to_table()) do
  413. if key == "gameid" then
  414. worldconfig.id = value
  415. else
  416. worldconfig.global_mods[key] = engine.is_yes(value)
  417. end
  418. end
  419. --read gamemods
  420. local gamespec = gamemgr.find_by_gameid(worldconfig.id)
  421. gamemgr.get_game_mods(gamespec, worldconfig.game_mods)
  422. return worldconfig
  423. end
  424. --------------------------------------------------------------------------------
  425. function modmgr.handle_modmgr_buttons(fields)
  426. local retval = {
  427. tab = nil,
  428. is_dialog = nil,
  429. show_buttons = nil,
  430. }
  431. if fields["modlist"] ~= nil then
  432. local event = explode_textlist_event(fields["modlist"])
  433. modmgr.selected_mod = event.index
  434. end
  435. if fields["btn_mod_mgr_install_local"] ~= nil then
  436. engine.show_file_open_dialog("mod_mgt_open_dlg",fgettext("Select Mod File:"))
  437. end
  438. if fields["btn_mod_mgr_download"] ~= nil then
  439. modstore.update_modlist()
  440. retval.current_tab = "dialog_modstore_unsorted"
  441. retval.is_dialog = true
  442. retval.show_buttons = false
  443. return retval
  444. end
  445. if fields["btn_mod_mgr_rename_modpack"] ~= nil then
  446. retval.current_tab = "dialog_rename_modpack"
  447. retval.is_dialog = true
  448. retval.show_buttons = false
  449. return retval
  450. end
  451. if fields["btn_mod_mgr_delete_mod"] ~= nil then
  452. retval.current_tab = "dialog_delete_mod"
  453. retval.is_dialog = true
  454. retval.show_buttons = false
  455. return retval
  456. end
  457. if fields["mod_mgt_open_dlg_accepted"] ~= nil and
  458. fields["mod_mgt_open_dlg_accepted"] ~= "" then
  459. modmgr.installmod(fields["mod_mgt_open_dlg_accepted"],nil)
  460. end
  461. return nil;
  462. end
  463. --------------------------------------------------------------------------------
  464. function modmgr.installmod(modfilename,basename)
  465. local modfile = modmgr.identify_filetype(modfilename)
  466. local modpath = modmgr.extract(modfile)
  467. if modpath == nil then
  468. gamedata.errormessage = fgettext("Install Mod: file: \"$1\"", modfile.name) ..
  469. fgettext("\nInstall Mod: unsupported filetype \"$1\"", modfile.type)
  470. return
  471. end
  472. local basefolder = modmgr.getbasefolder(modpath)
  473. if basefolder.type == "modpack" then
  474. local clean_path = nil
  475. if basename ~= nil then
  476. clean_path = "mp_" .. basename
  477. end
  478. if clean_path == nil then
  479. clean_path = get_last_folder(cleanup_path(basefolder.path))
  480. end
  481. if clean_path ~= nil then
  482. local targetpath = engine.get_modpath() .. DIR_DELIM .. clean_path
  483. if not engine.copy_dir(basefolder.path,targetpath) then
  484. gamedata.errormessage = fgettext("Failed to install $1 to $2", basename, targetpath)
  485. end
  486. else
  487. gamedata.errormessage = fgettext("Install Mod: unable to find suitable foldername for modpack $1", modfilename)
  488. end
  489. end
  490. if basefolder.type == "mod" then
  491. local targetfolder = basename
  492. if targetfolder == nil then
  493. targetfolder = modmgr.identify_modname(basefolder.path,"init.lua")
  494. end
  495. --if heuristic failed try to use current foldername
  496. if targetfolder == nil then
  497. targetfolder = get_last_folder(basefolder.path)
  498. end
  499. if targetfolder ~= nil and modmgr.isValidModname(targetfolder) then
  500. local targetpath = engine.get_modpath() .. DIR_DELIM .. targetfolder
  501. engine.copy_dir(basefolder.path,targetpath)
  502. else
  503. gamedata.errormessage = fgettext("Install Mod: unable to find real modname for: $1", modfilename)
  504. end
  505. end
  506. engine.delete_dir(modpath)
  507. modmgr.refresh_globals()
  508. end
  509. --------------------------------------------------------------------------------
  510. function modmgr.handle_rename_modpack_buttons(fields)
  511. if fields["dlg_rename_modpack_confirm"] ~= nil then
  512. local mod = filterlist.get_list(modmgr.modlist)[modmgr.selected_mod]
  513. local oldpath = engine.get_modpath() .. DIR_DELIM .. mod.name
  514. local targetpath = engine.get_modpath() .. DIR_DELIM .. fields["te_modpack_name"]
  515. engine.copy_dir(oldpath,targetpath,false)
  516. end
  517. return {
  518. is_dialog = false,
  519. show_buttons = true,
  520. current_tab = engine.setting_get("main_menu_tab")
  521. }
  522. end
  523. --------------------------------------------------------------------------------
  524. function modmgr.handle_configure_world_buttons(fields)
  525. if fields["world_config_modlist"] ~= nil then
  526. local event = explode_textlist_event(fields["world_config_modlist"])
  527. modmgr.world_config_selected_mod = event.index
  528. if event.typ == "DCL" then
  529. modmgr.world_config_enable_mod(nil)
  530. end
  531. end
  532. if fields["key_enter"] ~= nil then
  533. modmgr.world_config_enable_mod(nil)
  534. end
  535. if fields["cb_mod_enable"] ~= nil then
  536. local toset = engine.is_yes(fields["cb_mod_enable"])
  537. modmgr.world_config_enable_mod(toset)
  538. end
  539. if fields["btn_mp_enable"] ~= nil or
  540. fields["btn_mp_disable"] then
  541. local toset = (fields["btn_mp_enable"] ~= nil)
  542. modmgr.world_config_enable_mod(toset)
  543. end
  544. if fields["cb_hide_gamemods"] ~= nil then
  545. local current = filterlist.get_filtercriteria(modmgr.modlist)
  546. if current == nil then
  547. current = {}
  548. end
  549. if engine.is_yes(fields["cb_hide_gamemods"]) then
  550. current.hide_game = true
  551. modmgr.hide_gamemods = true
  552. else
  553. current.hide_game = false
  554. modmgr.hide_gamemods = false
  555. end
  556. filterlist.set_filtercriteria(modmgr.modlist,current)
  557. end
  558. if fields["cb_hide_mpcontent"] ~= nil then
  559. local current = filterlist.get_filtercriteria(modmgr.modlist)
  560. if current == nil then
  561. current = {}
  562. end
  563. if engine.is_yes(fields["cb_hide_mpcontent"]) then
  564. current.hide_modpackcontents = true
  565. modmgr.hide_modpackcontents = true
  566. else
  567. current.hide_modpackcontents = false
  568. modmgr.hide_modpackcontents = false
  569. end
  570. filterlist.set_filtercriteria(modmgr.modlist,current)
  571. end
  572. if fields["btn_config_world_save"] then
  573. local worldspec = engine.get_worlds()[modmgr.world_config_selected_world]
  574. local filename = worldspec.path ..
  575. DIR_DELIM .. "world.mt"
  576. local worldfile = Settings(filename)
  577. local mods = worldfile:to_table()
  578. local rawlist = filterlist.get_raw_list(modmgr.modlist)
  579. local i,mod
  580. for i,mod in ipairs(rawlist) do
  581. if not mod.is_modpack and
  582. mod.typ ~= "game_mod" then
  583. if mod.enabled then
  584. worldfile:set("load_mod_"..mod.name, "true")
  585. else
  586. worldfile:set("load_mod_"..mod.name, "false")
  587. end
  588. mods["load_mod_"..mod.name] = nil
  589. end
  590. end
  591. -- Remove mods that are not present anymore
  592. for key,value in pairs(mods) do
  593. if key:sub(1,9) == "load_mod_" then
  594. worldfile:remove(key)
  595. end
  596. end
  597. if not worldfile:write() then
  598. print("failed to write world config file")
  599. end
  600. modmgr.modlist = nil
  601. modmgr.worldconfig = nil
  602. return {
  603. is_dialog = false,
  604. show_buttons = true,
  605. current_tab = engine.setting_get("main_menu_tab")
  606. }
  607. end
  608. if fields["btn_config_world_cancel"] then
  609. modmgr.worldconfig = nil
  610. return {
  611. is_dialog = false,
  612. show_buttons = true,
  613. current_tab = engine.setting_get("main_menu_tab")
  614. }
  615. end
  616. if fields["btn_all_mods"] then
  617. local list = filterlist.get_raw_list(modmgr.modlist)
  618. for i=1,#list,1 do
  619. if list[i].typ ~= "game_mod" and
  620. not list[i].is_modpack then
  621. list[i].enabled = true
  622. end
  623. end
  624. end
  625. return nil
  626. end
  627. --------------------------------------------------------------------------------
  628. function modmgr.world_config_enable_mod(toset)
  629. local mod = filterlist.get_list(modmgr.modlist)
  630. [engine.get_textlist_index("world_config_modlist")]
  631. if mod.typ == "game_mod" then
  632. -- game mods can't be enabled or disabled
  633. elseif not mod.is_modpack then
  634. if toset == nil then
  635. mod.enabled = not mod.enabled
  636. else
  637. mod.enabled = toset
  638. end
  639. else
  640. local list = filterlist.get_raw_list(modmgr.modlist)
  641. for i=1,#list,1 do
  642. if list[i].modpack == mod.name then
  643. if toset == nil then
  644. toset = not list[i].enabled
  645. end
  646. list[i].enabled = toset
  647. end
  648. end
  649. end
  650. end
  651. --------------------------------------------------------------------------------
  652. function modmgr.handle_delete_mod_buttons(fields)
  653. local mod = filterlist.get_list(modmgr.global_mods)[modmgr.selected_mod]
  654. if fields["dlg_delete_mod_confirm"] ~= nil then
  655. if mod.path ~= nil and
  656. mod.path ~= "" and
  657. mod.path ~= engine.get_modpath() then
  658. if not engine.delete_dir(mod.path) then
  659. gamedata.errormessage = fgettext("Modmgr: failed to delete \"$1\"", mod.path)
  660. end
  661. modmgr.refresh_globals()
  662. else
  663. gamedata.errormessage = fgettext("Modmgr: invalid modpath \"$1\"", mod.path)
  664. end
  665. end
  666. return {
  667. is_dialog = false,
  668. show_buttons = true,
  669. current_tab = engine.setting_get("main_menu_tab")
  670. }
  671. end
  672. --------------------------------------------------------------------------------
  673. function modmgr.dialog_delete_mod()
  674. local mod = filterlist.get_list(modmgr.global_mods)[modmgr.selected_mod]
  675. local retval =
  676. "field[1.75,1;10,3;;" .. fgettext("Are you sure you want to delete \"$1\"?", mod.name) .. ";]"..
  677. "button[4,4.2;1,0.5;dlg_delete_mod_confirm;" .. fgettext("Yes") .. "]" ..
  678. "button[6.5,4.2;3,0.5;dlg_delete_mod_cancel;" .. fgettext("No of course not!") .. "]"
  679. return retval
  680. end
  681. --------------------------------------------------------------------------------
  682. function modmgr.preparemodlist(data)
  683. local retval = {}
  684. local global_mods = {}
  685. local game_mods = {}
  686. --read global mods
  687. local modpath = engine.get_modpath()
  688. if modpath ~= nil and
  689. modpath ~= "" then
  690. get_mods(modpath,global_mods)
  691. end
  692. for i=1,#global_mods,1 do
  693. global_mods[i].typ = "global_mod"
  694. table.insert(retval,global_mods[i])
  695. end
  696. --read game mods
  697. local gamespec = gamemgr.find_by_gameid(data.gameid)
  698. gamemgr.get_game_mods(gamespec, game_mods)
  699. for i=1,#game_mods,1 do
  700. game_mods[i].typ = "game_mod"
  701. table.insert(retval,game_mods[i])
  702. end
  703. if data.worldpath == nil then
  704. return retval
  705. end
  706. --read world mod configuration
  707. local filename = data.worldpath ..
  708. DIR_DELIM .. "world.mt"
  709. local worldfile = Settings(filename)
  710. for key,value in pairs(worldfile:to_table()) do
  711. if key:sub(1, 9) == "load_mod_" then
  712. key = key:sub(10)
  713. local element = nil
  714. for i=1,#retval,1 do
  715. if retval[i].name == key then
  716. element = retval[i]
  717. break
  718. end
  719. end
  720. if element ~= nil then
  721. element.enabled = engine.is_yes(value)
  722. else
  723. print("Mod: " .. key .. " " .. dump(value) .. " but not found")
  724. end
  725. end
  726. end
  727. return retval
  728. end
  729. --------------------------------------------------------------------------------
  730. function modmgr.init_worldconfig()
  731. modmgr.precheck()
  732. local worldspec = engine.get_worlds()[modmgr.world_config_selected_world]
  733. if worldspec ~= nil then
  734. --read worldconfig
  735. modmgr.worldconfig = modmgr.get_worldconfig(worldspec.path)
  736. if modmgr.worldconfig.id == nil or
  737. modmgr.worldconfig.id == "" then
  738. modmgr.worldconfig = nil
  739. return false
  740. end
  741. modmgr.modlist = filterlist.create(
  742. modmgr.preparemodlist, --refresh
  743. modmgr.comparemod, --compare
  744. function(element,uid) --uid match
  745. if element.name == uid then
  746. return true
  747. end
  748. end,
  749. function(element,criteria)
  750. if criteria.hide_game and
  751. element.typ == "game_mod" then
  752. return false
  753. end
  754. if criteria.hide_modpackcontents and
  755. element.modpack ~= nil then
  756. return false
  757. end
  758. return true
  759. end, --filter
  760. { worldpath= worldspec.path,
  761. gameid = worldspec.gameid }
  762. )
  763. filterlist.set_filtercriteria(modmgr.modlist, {
  764. hide_game=modmgr.hide_gamemods,
  765. hide_modpackcontents= modmgr.hide_modpackcontents
  766. })
  767. filterlist.add_sort_mechanism(modmgr.modlist, "alphabetic", sort_mod_list)
  768. filterlist.set_sortmode(modmgr.modlist, "alphabetic")
  769. return true
  770. end
  771. return false
  772. end
  773. --------------------------------------------------------------------------------
  774. function modmgr.comparemod(elem1,elem2)
  775. if elem1 == nil or elem2 == nil then
  776. return false
  777. end
  778. if elem1.name ~= elem2.name then
  779. return false
  780. end
  781. if elem1.is_modpack ~= elem2.is_modpack then
  782. return false
  783. end
  784. if elem1.typ ~= elem2.typ then
  785. return false
  786. end
  787. if elem1.modpack ~= elem2.modpack then
  788. return false
  789. end
  790. if elem1.path ~= elem2.path then
  791. return false
  792. end
  793. return true
  794. end
  795. --------------------------------------------------------------------------------
  796. function modmgr.gettab(name)
  797. local retval = ""
  798. if name == "mod_mgr" then
  799. retval = retval .. modmgr.tab()
  800. end
  801. if name == "dialog_rename_modpack" then
  802. retval = retval .. modmgr.dialog_rename_modpack()
  803. end
  804. if name == "dialog_delete_mod" then
  805. retval = retval .. modmgr.dialog_delete_mod()
  806. end
  807. if name == "dialog_configure_world" then
  808. retval = retval .. modmgr.dialog_configure_world()
  809. end
  810. return retval
  811. end
  812. --------------------------------------------------------------------------------
  813. function modmgr.mod_exists(basename)
  814. if modmgr.global_mods == nil then
  815. modmgr.refresh_globals()
  816. end
  817. if filterlist.raw_index_by_uid(modmgr.global_mods,basename) > 0 then
  818. return true
  819. end
  820. return false
  821. end
  822. --------------------------------------------------------------------------------
  823. function modmgr.get_global_mod(idx)
  824. if modmgr.global_mods == nil then
  825. return nil
  826. end
  827. if idx < 1 or idx > filterlist.size(modmgr.global_mods) then
  828. return nil
  829. end
  830. return filterlist.get_list(modmgr.global_mods)[idx]
  831. end
  832. --------------------------------------------------------------------------------
  833. function modmgr.refresh_globals()
  834. modmgr.global_mods = filterlist.create(
  835. modmgr.preparemodlist, --refresh
  836. modmgr.comparemod, --compare
  837. function(element,uid) --uid match
  838. if element.name == uid then
  839. return true
  840. end
  841. end,
  842. nil, --filter
  843. {}
  844. )
  845. filterlist.add_sort_mechanism(modmgr.global_mods, "alphabetic", sort_mod_list)
  846. filterlist.set_sortmode(modmgr.global_mods, "alphabetic")
  847. end
  848. --------------------------------------------------------------------------------
  849. function modmgr.identify_filetype(name)
  850. if name:sub(-3):lower() == "zip" then
  851. return {
  852. name = name,
  853. type = "zip"
  854. }
  855. end
  856. if name:sub(-6):lower() == "tar.gz" or
  857. name:sub(-3):lower() == "tgz"then
  858. return {
  859. name = name,
  860. type = "tgz"
  861. }
  862. end
  863. if name:sub(-6):lower() == "tar.bz2" then
  864. return {
  865. name = name,
  866. type = "tbz"
  867. }
  868. end
  869. if name:sub(-2):lower() == "7z" then
  870. return {
  871. name = name,
  872. type = "7z"
  873. }
  874. end
  875. return {
  876. name = name,
  877. type = "ukn"
  878. }
  879. end