modmgr.lua 28 KB

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