From 4bb6a41c04461e1b60f23dcce2930fc8b251d34f Mon Sep 17 00:00:00 2001 From: sapier Date: Tue, 26 Nov 2013 18:15:31 +0100 Subject: [PATCH] Fix modstore/favourites hang by adding asynchronous lua job support --- builtin/async_env.lua | 19 +++ builtin/async_event.lua | 59 +++++++ builtin/mainmenu.lua | 331 +++++++++++++++++++++----------------- builtin/modmgr.lua | 332 +++++++++++++++++++------------------- builtin/modstore.lua | 345 +++++++++++++++++++++++++++------------- 5 files changed, 663 insertions(+), 423 deletions(-) create mode 100644 builtin/async_env.lua create mode 100644 builtin/async_event.lua diff --git a/builtin/async_env.lua b/builtin/async_env.lua new file mode 100644 index 0000000..afc6921 --- /dev/null +++ b/builtin/async_env.lua @@ -0,0 +1,19 @@ +engine.log("info","Initializing Asynchronous environment") + +dofile(SCRIPTDIR .. DIR_DELIM .. "misc_helpers.lua") + +function engine.job_processor(serialized_function, serialized_data) + + local fct = marshal.decode(serialized_function) + local params = marshal.decode(serialized_data) + local retval = marshal.encode(nil) + + if fct ~= nil and type(fct) == "function" then + local result = fct(params) + retval = marshal.encode(result) + else + engine.log("error","ASYNC WORKER: unable to deserialize function") + end + + return retval,retval:len() +end diff --git a/builtin/async_event.lua b/builtin/async_event.lua new file mode 100644 index 0000000..f4c7d24 --- /dev/null +++ b/builtin/async_event.lua @@ -0,0 +1,59 @@ +local tbl = engine or minetest + +tbl.async_jobs = {} + +if engine ~= nil then + function tbl.async_event_handler(jobid, serialized_retval) + local retval = nil + if serialized_retval ~= "ERROR" then + retval= marshal.decode(serialized_retval) + else + tbl.log("error","Error fetching async result") + end + + assert(type(tbl.async_jobs[jobid]) == "function") + tbl.async_jobs[jobid](retval) + tbl.async_jobs[jobid] = nil + end +else + + minetest.register_globalstep( + function(dtime) + local list = tbl.get_finished_jobs() + + for i=1,#list,1 do + local retval = marshal.decode(list[i].retval) + + assert(type(tbl.async_jobs[jobid]) == "function") + tbl.async_jobs[list[i].jobid](retval) + tbl.async_jobs[list[i].jobid] = nil + end + end) +end + +function tbl.handle_async(fct, parameters, callback) + + --serialize fct + local serialized_fct = marshal.encode(fct) + + assert(marshal.decode(serialized_fct) ~= nil) + + --serialize parameters + local serialized_params = marshal.encode(parameters) + + if serialized_fct == nil or + serialized_params == nil or + serialized_fct:len() == 0 or + serialized_params:len() == 0 then + return false + end + + local jobid = tbl.do_async_callback( serialized_fct, + serialized_fct:len(), + serialized_params, + serialized_params:len()) + + tbl.async_jobs[jobid] = callback + + return true +end diff --git a/builtin/mainmenu.lua b/builtin/mainmenu.lua index 0032017..6c0aaf2 100644 --- a/builtin/mainmenu.lua +++ b/builtin/mainmenu.lua @@ -24,6 +24,7 @@ dofile(scriptpath .. DIR_DELIM .. "modstore.lua") dofile(scriptpath .. DIR_DELIM .. "gamemgr.lua") dofile(scriptpath .. DIR_DELIM .. "mm_textures.lua") dofile(scriptpath .. DIR_DELIM .. "mm_menubar.lua") +dofile(scriptpath .. DIR_DELIM .. "async_event.lua") menu = {} local tabbuilder = {} @@ -43,10 +44,10 @@ end -------------------------------------------------------------------------------- function menu.render_favorite(spec,render_details) local text = "" - + if spec.name ~= nil then text = text .. engine.formspec_escape(spec.name:trim()) - + -- if spec.description ~= nil and -- engine.formspec_escape(spec.description):trim() ~= "" then -- text = text .. " (" .. engine.formspec_escape(spec.description) .. ")" @@ -54,51 +55,51 @@ function menu.render_favorite(spec,render_details) else if spec.address ~= nil then text = text .. spec.address:trim() - + if spec.port ~= nil then text = text .. ":" .. spec.port end end end - + if not render_details then return text end - + local details = "" if spec.password == true then details = details .. "*" else details = details .. "_" end - + if spec.creative then details = details .. "C" else details = details .. "_" end - + if spec.damage then details = details .. "D" else details = details .. "_" end - + if spec.pvp then details = details .. "P" else details = details .. "_" end details = details .. " " - + local playercount = "" - + if spec.clients ~= nil and spec.clients_max ~= nil then playercount = string.format("%03d",spec.clients) .. "/" .. string.format("%03d",spec.clients_max) .. " " end - + return playercount .. engine.formspec_escape(details) .. text end @@ -106,7 +107,7 @@ end os.tempfolder = function() local filetocheck = os.tmpname() os.remove(filetocheck) - + local randname = "MTTempModFolder_" .. math.random(0,10000) if DIR_DELIM == "\\" then local tempfolder = os.getenv("TEMP") @@ -122,7 +123,7 @@ end function init_globals() --init gamedata gamedata.worldindex = 0 - + worldlist = filterlist.create( engine.get_worlds, compare_worlds, @@ -139,7 +140,7 @@ function init_globals() return false end --filter fct ) - + filterlist.add_sort_mechanism(worldlist,"alphabetic",sort_worlds_alphabetic) filterlist.set_sortmode(worldlist,"alphabetic") end @@ -148,12 +149,12 @@ end function update_menu() local formspec - + -- handle errors if gamedata.errormessage ~= nil then formspec = "size[12,5.2]" .. "field[1,2;10,2;;ERROR: " .. - gamedata.errormessage .. + gamedata.errormessage .. ";]".. "button[4.5,4.2;3,0.5;btn_error_confirm;" .. fgettext("Ok") .. "]" else @@ -166,14 +167,14 @@ end -------------------------------------------------------------------------------- function menu.render_world_list() local retval = "" - + local current_worldlist = filterlist.get_list(worldlist) - + for i,v in ipairs(current_worldlist) do if retval ~= "" then retval = retval .."," end - + retval = retval .. engine.formspec_escape(v.name) .. " \\[" .. engine.formspec_escape(v.gameid) .. "\\]" end @@ -196,24 +197,39 @@ function menu.render_texture_pack_list(list) return retval end +-------------------------------------------------------------------------------- +function menu.asyncOnlineFavourites() + menu.favorites = {} + engine.handle_async( + function(param) + return engine.get_favorites("online") + end, + nil, + function(result) + menu.favorites = result + engine.event_handler("Refresh") + end + ) +end + -------------------------------------------------------------------------------- function menu.init() --init menu data gamemgr.update_gamelist() - + menu.last_game = tonumber(engine.setting_get("main_menu_last_game_idx")) - + if type(menu.last_game) ~= "number" then menu.last_game = 1 end if engine.setting_getbool("public_serverlist") then - menu.favorites = engine.get_favorites("online") + menu.asyncOnlineFavourites() else menu.favorites = engine.get_favorites("local") end - - menu.defaulttexturedir = engine.get_texturepath() .. DIR_DELIM .. "base" .. + + menu.defaulttexturedir = engine.get_texturepath() .. DIR_DELIM .. "base" .. DIR_DELIM .. "pack" .. DIR_DELIM end @@ -222,12 +238,12 @@ function menu.lastgame() if menu.last_game > 0 and menu.last_game <= #gamemgr.games then return gamemgr.games[menu.last_game] end - + if #gamemgr.games >= 1 then menu.last_game = 1 return gamemgr.games[menu.last_game] end - + --error case!! return nil end @@ -238,11 +254,11 @@ function menu.update_last_game() local current_world = filterlist.get_raw_element(worldlist, engine.setting_get("mainmenu_last_selected_world") ) - + if current_world == nil then return end - + local gamespec, i = gamemgr.find_by_gameid(current_world.gameid) if i ~= nil then menu.last_game = i @@ -255,17 +271,17 @@ function menu.handle_key_up_down(fields,textlist,settingname) if fields["key_up"] then local oldidx = engine.get_textlist_index(textlist) - + if oldidx > 1 then local newidx = oldidx -1 engine.setting_set(settingname, filterlist.get_raw_index(worldlist,newidx)) end end - + if fields["key_down"] then local oldidx = engine.get_textlist_index(textlist) - + if oldidx < filterlist.size(worldlist) then local newidx = oldidx + 1 engine.setting_set(settingname, @@ -293,7 +309,7 @@ function tabbuilder.dialog_create_world() end mglist = mglist:sub(1, -2) - local retval = + local retval = "label[2,0;" .. fgettext("World name") .. "]".. "field[4.5,0.4;6,0.5;te_world_name;;]" .. @@ -335,7 +351,7 @@ function tabbuilder.gettab() if buildfunc ~= nil then retval = retval .. buildfunc() end - + retval = retval .. modmgr.gettab(tabbuilder.current_tab) retval = retval .. gamemgr.gettab(tabbuilder.current_tab) retval = retval .. modstore.gettab(tabbuilder.current_tab) @@ -345,18 +361,18 @@ end -------------------------------------------------------------------------------- function tabbuilder.handle_create_world_buttons(fields) - + if fields["world_create_confirm"] or fields["key_enter"] then - + local worldname = fields["te_world_name"] local gameindex = engine.get_textlist_index("games") - + if gameindex > 0 and worldname ~= "" then - + local message = nil - + if not filterlist.uid_exists_raw(worldlist,worldname) then engine.setting_set("mg_name",fields["dd_mapgen"]) message = engine.create_world(worldname,gameindex) @@ -365,28 +381,28 @@ function tabbuilder.handle_create_world_buttons(fields) end engine.setting_set("fixed_map_seed", fields["te_seed"]) - + if message ~= nil then gamedata.errormessage = message else menu.last_game = gameindex engine.setting_set("main_menu_last_game_idx",gameindex) - + filterlist.refresh(worldlist) engine.setting_set("mainmenu_last_selected_world", filterlist.raw_index_by_uid(worldlist,worldname)) end else - gamedata.errormessage = + gamedata.errormessage = fgettext("No worldname given or no game selected") end end - + if fields["games"] then tabbuilder.skipformupdate = true return end - + --close dialog tabbuilder.is_dialog = false tabbuilder.show_buttons = true @@ -395,16 +411,16 @@ end -------------------------------------------------------------------------------- function tabbuilder.handle_delete_world_buttons(fields) - + if fields["world_delete_confirm"] then - if menu.world_to_del > 0 and + if menu.world_to_del > 0 and menu.world_to_del <= #filterlist.get_raw_list(worldlist) then engine.delete_world(menu.world_to_del) menu.world_to_del = 0 filterlist.refresh(worldlist) end end - + tabbuilder.is_dialog = false tabbuilder.show_buttons = true tabbuilder.current_tab = engine.setting_get("main_menu_tab") @@ -412,12 +428,12 @@ end -------------------------------------------------------------------------------- function tabbuilder.handle_multiplayer_buttons(fields) - + if fields["te_name"] ~= nil then gamedata.playername = fields["te_name"] engine.setting_set("name", fields["te_name"]) end - + if fields["favourites"] ~= nil then local event = explode_textlist_event(fields["favourites"]) if event.typ == "DCL" then @@ -429,12 +445,12 @@ function tabbuilder.handle_multiplayer_buttons(fields) gamedata.password = fields["te_pwd"] end gamedata.selected_world = 0 - + if menu.favorites ~= nil then gamedata.servername = menu.favorites[event.index].name gamedata.serverdescription = menu.favorites[event.index].description end - + if gamedata.address ~= nil and gamedata.port ~= nil then engine.setting_set("address",gamedata.address) @@ -443,53 +459,53 @@ function tabbuilder.handle_multiplayer_buttons(fields) end end end - + if event.typ == "CHG" then if event.index <= #menu.favorites then local address = menu.favorites[event.index].address local port = menu.favorites[event.index].port - + if address ~= nil and port ~= nil then engine.setting_set("address",address) engine.setting_set("remote_port",port) end - + menu.fav_selected = event.index end end return end - + if fields["key_up"] ~= nil or fields["key_down"] ~= nil then - + local fav_idx = engine.get_textlist_index("favourites") - + if fields["key_up"] ~= nil and fav_idx > 1 then fav_idx = fav_idx -1 else if fields["key_down"] and fav_idx < #menu.favorites then fav_idx = fav_idx +1 end end - + local address = menu.favorites[fav_idx].address local port = menu.favorites[fav_idx].port - + if address ~= nil and port ~= nil then engine.setting_set("address",address) engine.setting_set("remote_port",port) end - + menu.fav_selected = fav_idx return end - + if fields["cb_public_serverlist"] ~= nil then engine.setting_set("public_serverlist", fields["cb_public_serverlist"]) - + if engine.setting_getbool("public_serverlist") then - menu.favorites = engine.get_favorites("online") + menu.asyncOnlineFavourites() else menu.favorites = engine.get_favorites("local") end @@ -502,27 +518,27 @@ function tabbuilder.handle_multiplayer_buttons(fields) engine.delete_favorite(current_favourite) menu.favorites = engine.get_favorites() menu.fav_selected = nil - + engine.setting_set("address","") engine.setting_set("remote_port","30000") - + return end if fields["btn_mp_connect"] ~= nil or fields["key_enter"] ~= nil then - + gamedata.playername = fields["te_name"] gamedata.password = fields["te_pwd"] gamedata.address = fields["te_address"] gamedata.port = fields["te_port"] - + local fav_idx = engine.get_textlist_index("favourites") - + if fav_idx > 0 and fav_idx <= #menu.favorites and menu.favorites[fav_idx].address == fields["te_address"] and menu.favorites[fav_idx].port == fields["te_port"] then - + gamedata.servername = menu.favorites[fav_idx].name gamedata.serverdescription = menu.favorites[fav_idx].description else @@ -531,10 +547,10 @@ function tabbuilder.handle_multiplayer_buttons(fields) end gamedata.selected_world = 0 - + engine.setting_set("address",fields["te_address"]) engine.setting_set("remote_port",fields["te_port"]) - + engine.start() return end @@ -547,7 +563,7 @@ function tabbuilder.handle_server_buttons(fields) if fields["srv_worlds"] ~= nil then local event = explode_textlist_event(fields["srv_worlds"]) - + if event.typ == "DCL" then world_doubleclick = true end @@ -556,13 +572,13 @@ function tabbuilder.handle_server_buttons(fields) filterlist.get_raw_index(worldlist,engine.get_textlist_index("srv_worlds"))) end end - + menu.handle_key_up_down(fields,"srv_worlds","mainmenu_last_selected_world") - + if fields["cb_creative_mode"] then engine.setting_set("creative_mode", fields["cb_creative_mode"]) end - + if fields["cb_enable_damage"] then engine.setting_set("enable_damage", fields["cb_enable_damage"]) end @@ -570,7 +586,7 @@ function tabbuilder.handle_server_buttons(fields) if fields["cb_server_announce"] then engine.setting_set("server_announce", fields["cb_server_announce"]) end - + if fields["start_server"] ~= nil or world_doubleclick or fields["key_enter"] then @@ -581,19 +597,20 @@ function tabbuilder.handle_server_buttons(fields) gamedata.port = fields["te_serverport"] gamedata.address = "" gamedata.selected_world = filterlist.get_raw_index(worldlist,selected) - + engine.setting_set("port",gamedata.port) + menu.update_last_game(gamedata.selected_world) engine.start() end end - + if fields["world_create"] ~= nil then tabbuilder.current_tab = "dialog_create_world" tabbuilder.is_dialog = true tabbuilder.show_buttons = false end - + if fields["world_delete"] ~= nil then local selected = engine.get_textlist_index("srv_worlds") if selected > 0 and @@ -611,7 +628,7 @@ function tabbuilder.handle_server_buttons(fields) end end end - + if fields["world_configure"] ~= nil then selected = engine.get_textlist_index("srv_worlds") if selected > 0 then @@ -639,7 +656,7 @@ function tabbuilder.handle_settings_buttons(fields) if fields["cb_opaque_water"] then engine.setting_set("opaque_water", fields["cb_opaque_water"]) end - + if fields["cb_mipmapping"] then engine.setting_set("mip_map", fields["cb_mipmapping"]) end @@ -652,7 +669,7 @@ function tabbuilder.handle_settings_buttons(fields) if fields["cb_trilinear"] then engine.setting_set("trilinear_filter", fields["cb_trilinear"]) end - + if fields["cb_shaders"] then if (engine.setting_get("video_driver") == "direct3d8" or engine.setting_get("video_driver") == "direct3d9") then engine.setting_set("enable_shaders", "false") @@ -683,23 +700,23 @@ function tabbuilder.handle_singleplayer_buttons(fields) if fields["sp_worlds"] ~= nil then local event = explode_textlist_event(fields["sp_worlds"]) - + if event.typ == "DCL" then world_doubleclick = true end - + if event.typ == "CHG" then engine.setting_set("mainmenu_last_selected_world", filterlist.get_raw_index(worldlist,engine.get_textlist_index("sp_worlds"))) end end - + menu.handle_key_up_down(fields,"sp_worlds","mainmenu_last_selected_world") - + if fields["cb_creative_mode"] then engine.setting_set("creative_mode", fields["cb_creative_mode"]) end - + if fields["cb_enable_damage"] then engine.setting_set("enable_damage", fields["cb_enable_damage"]) end @@ -711,19 +728,19 @@ function tabbuilder.handle_singleplayer_buttons(fields) if selected > 0 then gamedata.selected_world = filterlist.get_raw_index(worldlist,selected) gamedata.singleplayer = true - + menu.update_last_game(gamedata.selected_world) - + engine.start() end end - + if fields["world_create"] ~= nil then tabbuilder.current_tab = "dialog_create_world" tabbuilder.is_dialog = true tabbuilder.show_buttons = false end - + if fields["world_delete"] ~= nil then local selected = engine.get_textlist_index("sp_worlds") if selected > 0 and @@ -741,7 +758,7 @@ function tabbuilder.handle_singleplayer_buttons(fields) end end end - + if fields["world_configure"] ~= nil then selected = engine.get_textlist_index("sp_worlds") if selected > 0 then @@ -768,7 +785,7 @@ function tabbuilder.handle_texture_pack_buttons(fields) if #list >= current_index then local new_path = engine.get_texturepath()..DIR_DELIM..list[current_index] if list[current_index] == "None" then new_path = "" end - + engine.setting_set("texture_path", new_path) end end @@ -781,15 +798,15 @@ function tabbuilder.tab_header() if tabbuilder.last_tab_index == nil then tabbuilder.last_tab_index = 1 end - + local toadd = "" - + for i=1,#tabbuilder.current_buttons,1 do - + if toadd ~= "" then toadd = toadd .. "," end - + toadd = toadd .. tabbuilder.current_buttons[i].caption end return "tabheader[-0.3,-0.99;main_tab;" .. toadd ..";" .. tabbuilder.last_tab_index .. ";true;false]" @@ -802,21 +819,21 @@ function tabbuilder.handle_tab_buttons(fields) local index = tonumber(fields["main_tab"]) tabbuilder.last_tab_index = index tabbuilder.current_tab = tabbuilder.current_buttons[index].name - + engine.setting_set("main_menu_tab",tabbuilder.current_tab) end - + --handle tab changes if tabbuilder.current_tab ~= tabbuilder.old_tab then if tabbuilder.current_tab ~= "singleplayer" and not tabbuilder.is_dialog then menu.update_gametype(true) end end - + if tabbuilder.current_tab == "singleplayer" then menu.update_gametype() end - + tabbuilder.old_tab = tabbuilder.current_tab end @@ -832,24 +849,24 @@ function tabbuilder.tab_multiplayer() "field[6.75,5.25;2.25,0.5;te_port;;" ..engine.setting_get("remote_port") .."]" .. "checkbox[1,3.6;cb_public_serverlist;".. fgettext("Public Serverlist") .. ";" .. dump(engine.setting_getbool("public_serverlist")) .. "]" - + if not engine.setting_getbool("public_serverlist") then - retval = retval .. + retval = retval .. "button[6.45,3.95;2.25,0.5;btn_delete_favorite;".. fgettext("Delete") .. "]" end - + retval = retval .. "button[9,4.95;2.5,0.5;btn_mp_connect;".. fgettext("Connect") .. "]" .. "field[9.3,3.75;2.5,0.5;te_name;;" ..engine.setting_get("name") .."]" .. "pwdfield[9.3,4.5;2.5,0.5;te_pwd;]" .. "textarea[9.3,0.25;2.5,2.75;;" - if menu.fav_selected ~= nil and + if menu.fav_selected ~= nil and menu.favorites[menu.fav_selected].description ~= nil then - retval = retval .. + retval = retval .. engine.formspec_escape(menu.favorites[menu.fav_selected].description,true) end - - retval = retval .. + + retval = retval .. ";]" .. "textlist[1,0.35;7.5,3.35;favourites;" @@ -857,7 +874,7 @@ function tabbuilder.tab_multiplayer() if #menu.favorites > 0 then retval = retval .. menu.render_favorite(menu.favorites[1],render_details) - + for i=2,#menu.favorites,1 do retval = retval .. "," .. menu.render_favorite(menu.favorites[i],render_details) end @@ -878,8 +895,8 @@ function tabbuilder.tab_server() local index = filterlist.get_current_index(worldlist, tonumber(engine.setting_get("mainmenu_last_selected_world")) ) - - local retval = + + local retval = "button[4,4.15;2.6,0.5;world_delete;".. fgettext("Delete") .. "]" .. "button[6.5,4.15;2.8,0.5;world_create;".. fgettext("New") .. "]" .. "button[9.2,4.15;2.55,0.5;world_configure;".. fgettext("Configure") .. "]" .. @@ -895,27 +912,27 @@ function tabbuilder.tab_server() "field[0.8,3.2;3,0.5;te_playername;".. fgettext("Name") .. ";" .. engine.setting_get("name") .. "]" .. "pwdfield[0.8,4.2;3,0.5;te_passwd;".. fgettext("Password") .. "]" .. - "field[0.8,5.2;3,0.5;te_serverport;".. fgettext("Server Port") .. ";" .. + "field[0.8,5.2;3,0.5;te_serverport;".. fgettext("Server Port") .. ";" .. engine.setting_get("port") .."]" .. "textlist[4,0.25;7.5,3.7;srv_worlds;" .. menu.render_world_list() .. ";" .. index .. "]" - + return retval end -------------------------------------------------------------------------------- function tabbuilder.tab_settings() return "vertlabel[0,0;" .. fgettext("SETTINGS") .. "]" .. - "checkbox[1,0.75;cb_fancy_trees;".. fgettext("Fancy trees") .. ";" + "checkbox[1,0.75;cb_fancy_trees;".. fgettext("Fancy trees") .. ";" .. dump(engine.setting_getbool("new_style_leaves")) .. "]".. - "checkbox[1,1.25;cb_smooth_lighting;".. fgettext("Smooth Lighting") + "checkbox[1,1.25;cb_smooth_lighting;".. fgettext("Smooth Lighting") .. ";".. dump(engine.setting_getbool("smooth_lighting")) .. "]".. "checkbox[1,1.75;cb_3d_clouds;".. fgettext("3D Clouds") .. ";" .. dump(engine.setting_getbool("enable_3d_clouds")) .. "]".. "checkbox[1,2.25;cb_opaque_water;".. fgettext("Opaque Water") .. ";" .. dump(engine.setting_getbool("opaque_water")) .. "]".. - + "checkbox[4,0.75;cb_mipmapping;".. fgettext("Mip-Mapping") .. ";" .. dump(engine.setting_getbool("mip_map")) .. "]".. "checkbox[4,1.25;cb_anisotrophic;".. fgettext("Anisotropic Filtering") .. ";" @@ -924,7 +941,7 @@ function tabbuilder.tab_settings() .. dump(engine.setting_getbool("bilinear_filter")) .. "]".. "checkbox[4,2.25;cb_trilinear;".. fgettext("Tri-Linear Filtering") .. ";" .. dump(engine.setting_getbool("trilinear_filter")) .. "]".. - + "checkbox[7.5,0.75;cb_shaders;".. fgettext("Shaders") .. ";" .. dump(engine.setting_getbool("enable_shaders")) .. "]".. "checkbox[7.5,1.25;cb_pre_ivis;".. fgettext("Preload item visuals") .. ";" @@ -933,13 +950,13 @@ function tabbuilder.tab_settings() .. dump(engine.setting_getbool("enable_particles")) .. "]".. "checkbox[7.5,2.25;cb_finite_liquid;".. fgettext("Finite Liquid") .. ";" .. dump(engine.setting_getbool("liquid_finite")) .. "]".. - + "button[1,4.25;2.25,0.5;btn_change_keys;".. fgettext("Change keys") .. "]" end -------------------------------------------------------------------------------- function tabbuilder.tab_singleplayer() - + local index = filterlist.get_current_index(worldlist, tonumber(engine.setting_get("mainmenu_last_selected_world")) ) @@ -966,19 +983,19 @@ function tabbuilder.tab_texture_packs() "vertlabel[0,-0.25;".. fgettext("TEXTURE PACKS") .. "]" .. "textlist[4,0.25;7.5,5.0;TPs;" - local current_texture_path = engine.setting_get("texture_path") - local list = filter_texture_pack_list(engine.get_dirlist(engine.get_texturepath(), true)) + local current_texture_path = engine.setting_get("texture_path") + local list = filter_texture_pack_list(engine.get_dirlist(engine.get_texturepath(), true)) local index = tonumber(engine.setting_get("mainmenu_last_selected_TP")) - + if index == nil then index = 1 end - + if current_texture_path == "" then retval = retval .. menu.render_texture_pack_list(list) .. ";" .. index .. "]" return retval end - + local infofile = current_texture_path ..DIR_DELIM.."info.txt" local infotext = "" local f = io.open(infofile, "r") @@ -988,7 +1005,7 @@ function tabbuilder.tab_texture_packs() infotext = f:read("*all") f:close() end - + local screenfile = current_texture_path..DIR_DELIM.."screenshot.png" local no_screenshot = nil if not file_exists(screenfile) then @@ -1009,7 +1026,7 @@ function tabbuilder.tab_credits() local logofile = menu.defaulttexturedir .. "logo.png" return "vertlabel[0,-0.5;CREDITS]" .. "label[0.5,3;Minetest " .. engine.get_version() .. "]" .. - "label[0.5,3.3;http://minetest.net]" .. + "label[0.5,3.3;http://minetest.net]" .. "image[0.5,1;" .. engine.formspec_escape(logofile) .. "]" .. "textlist[3.5,-0.25;8.5,5.8;list_credits;" .. "#FFFF00" .. fgettext("Core Developers") .."," .. @@ -1064,40 +1081,40 @@ function tabbuilder.init() } tabbuilder.current_tab = engine.setting_get("main_menu_tab") - + if tabbuilder.current_tab == nil or tabbuilder.current_tab == "" then tabbuilder.current_tab = "singleplayer" engine.setting_set("main_menu_tab",tabbuilder.current_tab) end - + --initialize tab buttons tabbuilder.last_tab = nil tabbuilder.show_buttons = true - + tabbuilder.current_buttons = {} table.insert(tabbuilder.current_buttons,{name="singleplayer", caption=fgettext("Singleplayer")}) table.insert(tabbuilder.current_buttons,{name="multiplayer", caption=fgettext("Client")}) table.insert(tabbuilder.current_buttons,{name="server", caption=fgettext("Server")}) table.insert(tabbuilder.current_buttons,{name="settings", caption=fgettext("Settings")}) table.insert(tabbuilder.current_buttons,{name="texture_packs", caption=fgettext("Texture Packs")}) - + if engine.setting_getbool("main_menu_game_mgr") then table.insert(tabbuilder.current_buttons,{name="game_mgr", caption=fgettext("Games")}) end - + if engine.setting_getbool("main_menu_mod_mgr") then table.insert(tabbuilder.current_buttons,{name="mod_mgr", caption=fgettext("Mods")}) end table.insert(tabbuilder.current_buttons,{name="credits", caption=fgettext("Credits")}) - - + + for i=1,#tabbuilder.current_buttons,1 do if tabbuilder.current_buttons[i].name == tabbuilder.current_tab then tabbuilder.last_tab_index = i end end - + if tabbuilder.current_tab ~= "singleplayer" then menu.update_gametype(true) else @@ -1112,18 +1129,24 @@ function tabbuilder.checkretval(retval) if retval.current_tab ~= nil then tabbuilder.current_tab = retval.current_tab end - + if retval.is_dialog ~= nil then tabbuilder.is_dialog = retval.is_dialog end - + if retval.show_buttons ~= nil then tabbuilder.show_buttons = retval.show_buttons end - + if retval.skipformupdate ~= nil then tabbuilder.skipformupdate = retval.skipformupdate end + + if retval.ignore_menu_quit == true then + tabbuilder.ignore_menu_quit = true + else + tabbuilder.ignore_menu_quit = false + end end end @@ -1134,54 +1157,54 @@ end -------------------------------------------------------------------------------- engine.button_handler = function(fields) --print("Buttonhandler: tab: " .. tabbuilder.current_tab .. " fields: " .. dump(fields)) - + if fields["btn_error_confirm"] then gamedata.errormessage = nil end - + local retval = modmgr.handle_buttons(tabbuilder.current_tab,fields) tabbuilder.checkretval(retval) - + retval = gamemgr.handle_buttons(tabbuilder.current_tab,fields) tabbuilder.checkretval(retval) - + retval = modstore.handle_buttons(tabbuilder.current_tab,fields) tabbuilder.checkretval(retval) - + if tabbuilder.current_tab == "dialog_create_world" then tabbuilder.handle_create_world_buttons(fields) end - + if tabbuilder.current_tab == "dialog_delete_world" then tabbuilder.handle_delete_world_buttons(fields) end - + if tabbuilder.current_tab == "singleplayer" then tabbuilder.handle_singleplayer_buttons(fields) end - + if tabbuilder.current_tab == "texture_packs" then tabbuilder.handle_texture_pack_buttons(fields) end - + if tabbuilder.current_tab == "multiplayer" then tabbuilder.handle_multiplayer_buttons(fields) end - + if tabbuilder.current_tab == "settings" then tabbuilder.handle_settings_buttons(fields) end - + if tabbuilder.current_tab == "server" then tabbuilder.handle_server_buttons(fields) end - + --tab buttons tabbuilder.handle_tab_buttons(fields) - + --menubar buttons menubar.handle_buttons(fields) - + if not tabbuilder.skipformupdate then --update menu update_menu() @@ -1194,6 +1217,10 @@ end engine.event_handler = function(event) if event == "MenuQuit" then if tabbuilder.is_dialog then + if tabbuilder.ignore_menu_quit then + return + end + tabbuilder.is_dialog = false tabbuilder.show_buttons = true tabbuilder.current_tab = engine.setting_get("main_menu_tab") @@ -1203,6 +1230,10 @@ engine.event_handler = function(event) engine.close() end end + + if event == "Refresh" then + update_menu() + end end -------------------------------------------------------------------------------- diff --git a/builtin/modmgr.lua b/builtin/modmgr.lua index 1f19ac6..cc5e095 100644 --- a/builtin/modmgr.lua +++ b/builtin/modmgr.lua @@ -22,7 +22,7 @@ function get_mods(path,retval,modpack) for i=1,#mods,1 do local toadd = {} local modpackfile = nil - + toadd.name = mods[i] toadd.path = path .. DIR_DELIM .. mods[i] .. DIR_DELIM if modpack ~= nil and @@ -33,7 +33,7 @@ function get_mods(path,retval,modpack) local error = nil modpackfile,error = io.open(filename,"r") end - + if modpackfile ~= nil then modpackfile:close() toadd.is_modpack = true @@ -52,9 +52,9 @@ modmgr = {} function modmgr.extract(modfile) if modfile.type == "zip" then local tempfolder = os.tempfolder() - + if tempfolder ~= nil and - tempfodler ~= "" then + tempfolder ~= "" then engine.create_dir(tempfolder) engine.extract_zip(modfile.name,tempfolder) return tempfolder @@ -80,7 +80,7 @@ function modmgr.getbasefolder(temppath) path=temppath } end - + testfile = io.open(temppath .. DIR_DELIM .. "modpack.txt","r") if testfile ~= nil then testfile:close() @@ -89,9 +89,9 @@ function modmgr.getbasefolder(temppath) path=temppath } end - + local subdirs = engine.get_dirlist(temppath,true) - + --only single mod or modpack allowed if #subdirs ~= 1 then return { @@ -100,7 +100,7 @@ function modmgr.getbasefolder(temppath) } end - testfile = + testfile = io.open(temppath .. DIR_DELIM .. subdirs[1] ..DIR_DELIM .."init.lua","r") if testfile ~= nil then testfile:close() @@ -109,8 +109,8 @@ function modmgr.getbasefolder(temppath) path= temppath .. DIR_DELIM .. subdirs[1] } end - - testfile = + + testfile = io.open(temppath .. DIR_DELIM .. subdirs[1] ..DIR_DELIM .."modpack.txt","r") if testfile ~= nil then testfile:close() @@ -131,7 +131,7 @@ function modmgr.isValidModname(modpath) if modpath:find("-") ~= nil then return false end - + return true end @@ -142,20 +142,20 @@ function modmgr.parse_register_line(line) if pos1 ~= nil then pos2 = line:find("\"",pos1+1) end - + if pos1 ~= nil and pos2 ~= nil then local item = line:sub(pos1+1,pos2-1) - + if item ~= nil and item ~= "" then local pos3 = item:find(":") - + if pos3 ~= nil then local retval = item:sub(1,pos3-1) if retval ~= nil and retval ~= "" then return retval - end + end end end end @@ -169,10 +169,10 @@ function modmgr.parse_dofile_line(modpath,line) if pos1 ~= nil then pos2 = line:find("\"",pos1+1) end - + if pos1 ~= nil and pos2 ~= nil then local filename = line:sub(pos1+1,pos2-1) - + if filename ~= nil and filename ~= "" and filename:find(".lua") then @@ -187,37 +187,37 @@ function modmgr.identify_modname(modpath,filename) local testfile = io.open(modpath .. DIR_DELIM .. filename,"r") if testfile ~= nil then local line = testfile:read() - + while line~= nil do local modname = nil - + if line:find("minetest.register_tool") then modname = modmgr.parse_register_line(line) end - + if line:find("minetest.register_craftitem") then modname = modmgr.parse_register_line(line) end - - + + if line:find("minetest.register_node") then modname = modmgr.parse_register_line(line) end - + if line:find("dofile") then modname = modmgr.parse_dofile_line(modpath,line) end - + if modname ~= nil then testfile:close() return modname end - + line = testfile:read() end testfile:close() end - + return nil end @@ -231,29 +231,29 @@ function modmgr.tab() if modmgr.selected_mod == nil then modmgr.selected_mod = 1 end - - local retval = + + local retval = "vertlabel[0,-0.25;".. fgettext("MODS") .. "]" .. "label[0.8,-0.25;".. fgettext("Installed Mods:") .. "]" .. "textlist[0.75,0.25;4.5,4;modlist;" .. - modmgr.render_modlist(modmgr.global_mods) .. + modmgr.render_modlist(modmgr.global_mods) .. ";" .. modmgr.selected_mod .. "]" retval = retval .. - "label[0.8,4.2;" .. fgettext("Add mod:") .. "]" .. + "label[0.8,4.2;" .. fgettext("Add mod:") .. "]" .. -- TODO Disabled due to upcoming release 0.4.8 and irrlicht messing up localization -- "button[0.75,4.85;1.8,0.5;btn_mod_mgr_install_local;".. fgettext("Local install") .. "]" .. "button[2.45,4.85;3.05,0.5;btn_mod_mgr_download;".. fgettext("Online mod repository") .. "]" - + local selected_mod = nil - + if filterlist.size(modmgr.global_mods) >= modmgr.selected_mod then selected_mod = filterlist.get_list(modmgr.global_mods)[modmgr.selected_mod] end - + if selected_mod ~= nil then local modscreenshot = nil - + --check for screenshot beeing available local screenshotfilename = selected_mod.path .. DIR_DELIM .. "screenshot.png" local error = nil @@ -262,40 +262,40 @@ function modmgr.tab() screenshotfile:close() modscreenshot = screenshotfilename end - + if modscreenshot == nil then modscreenshot = modstore.basetexturedir .. "no_screenshot.png" end - - retval = retval + + retval = retval .. "image[5.5,0;3,2;" .. engine.formspec_escape(modscreenshot) .. "]" .. "label[8.25,0.6;" .. selected_mod.name .. "]" - + local descriptionlines = nil error = nil local descriptionfilename = selected_mod.path .. "description.txt" descriptionfile,error = io.open(descriptionfilename,"r") if error == nil then descriptiontext = descriptionfile:read("*all") - + descriptionlines = engine.splittext(descriptiontext,42) descriptionfile:close() else descriptionlines = {} table.insert(descriptionlines,fgettext("No mod description available")) end - - retval = retval .. + + retval = retval .. "label[5.5,1.7;".. fgettext("Mod information:") .. "]" .. "textlist[5.5,2.2;6.2,2.4;description;" - + for i=1,#descriptionlines,1 do retval = retval .. engine.formspec_escape(descriptionlines[i]) .. "," end - - + + if selected_mod.is_modpack then - retval = retval .. ";0]" .. + retval = retval .. ";0]" .. "button[10,4.85;2,0.5;btn_mod_mgr_rename_modpack;" .. fgettext("Rename") .. "]" retval = retval .. "button[5.5,4.85;4.5,0.5;btn_mod_mgr_delete_mod;" @@ -304,11 +304,11 @@ function modmgr.tab() --show dependencies retval = retval .. ",Depends:," - + toadd = modmgr.get_dependencies(selected_mod.path) - + retval = retval .. toadd .. ";0]" - + retval = retval .. "button[5.5,4.85;4.5,0.5;btn_mod_mgr_delete_mod;" .. fgettext("Uninstall selected mod") .. "]" end @@ -320,15 +320,15 @@ end function modmgr.dialog_rename_modpack() local mod = filterlist.get_list(modmgr.global_mods)[modmgr.selected_mod] - - local retval = + + local retval = "label[1.75,1;".. fgettext("Rename Modpack:") .. "]".. "field[4.5,1.4;6,0.5;te_modpack_name;;" .. mod.name .. "]" .. - "button[5,4.2;2.6,0.5;dlg_rename_modpack_confirm;".. + "button[5,4.2;2.6,0.5;dlg_rename_modpack_confirm;".. fgettext("Accept") .. "]" .. - "button[7.5,4.2;2.8,0.5;dlg_rename_modpack_cancel;".. + "button[7.5,4.2;2.8,0.5;dlg_rename_modpack_cancel;".. fgettext("Cancel") .. "]" return retval @@ -340,15 +340,15 @@ function modmgr.precheck() if modmgr.world_config_selected_world == nil then modmgr.world_config_selected_world = 1 end - + if modmgr.world_config_selected_mod == nil then modmgr.world_config_selected_mod = 1 end - + if modmgr.hide_gamemods == nil then modmgr.hide_gamemods = true end - + if modmgr.hide_modpackcontents == nil then modmgr.hide_modpackcontents = true end @@ -357,27 +357,27 @@ end -------------------------------------------------------------------------------- function modmgr.render_modlist(render_list) local retval = "" - + if render_list == nil then if modmgr.global_mods == nil then modmgr.refresh_globals() end render_list = modmgr.global_mods end - + local list = filterlist.get_list(render_list) local last_modpack = nil - + for i,v in ipairs(list) do if retval ~= "" then retval = retval .."," end local color = "" - + if v.is_modpack then local rawlist = filterlist.get_raw_list(render_list) - + local all_enabled = true for j=1,#rawlist,1 do if rawlist[j].modpack == list[i].name and @@ -386,14 +386,14 @@ function modmgr.render_modlist(render_list) break end end - + if all_enabled == false then color = mt_color_grey else color = mt_color_dark_green end end - + if v.typ == "game_mod" then color = mt_color_blue else @@ -408,34 +408,34 @@ function modmgr.render_modlist(render_list) end retval = retval .. v.name end - + return retval end -------------------------------------------------------------------------------- function modmgr.dialog_configure_world() modmgr.precheck() - + local worldspec = engine.get_worlds()[modmgr.world_config_selected_world] local mod = filterlist.get_list(modmgr.modlist)[modmgr.world_config_selected_mod] - + local retval = "size[11,6.5]" .. "label[0.5,-0.25;" .. fgettext("World:") .. "]" .. "label[1.75,-0.25;" .. worldspec.name .. "]" - + if modmgr.hide_gamemods then retval = retval .. "checkbox[0,5.75;cb_hide_gamemods;" .. fgettext("Hide Game") .. ";true]" else retval = retval .. "checkbox[0,5.75;cb_hide_gamemods;" .. fgettext("Hide Game") .. ";false]" end - + if modmgr.hide_modpackcontents then retval = retval .. "checkbox[2,5.75;cb_hide_mpcontent;" .. fgettext("Hide mp content") .. ";true]" else retval = retval .. "checkbox[2,5.75;cb_hide_mpcontent;" .. fgettext("Hide mp content") .. ";false]" end - + if mod == nil then mod = {name=""} end @@ -447,11 +447,11 @@ function modmgr.dialog_configure_world() modmgr.get_dependencies(mod.path) .. ";0]" .. "button[9.25,6.35;2,0.5;btn_config_world_save;" .. fgettext("Save") .. "]" .. "button[7.4,6.35;2,0.5;btn_config_world_cancel;" .. fgettext("Cancel") .. "]" - + if mod ~= nil and mod.name ~= "" and mod.typ ~= "game_mod" then if mod.is_modpack then local rawlist = filterlist.get_raw_list(modmgr.modlist) - + local all_enabled = true for j=1,#rawlist,1 do if rawlist[j].modpack == mod.name and @@ -460,7 +460,7 @@ function modmgr.dialog_configure_world() break end end - + if all_enabled == false then retval = retval .. "button[5.5,-0.125;2,0.5;btn_mp_enable;" .. fgettext("Enable MP") .. "]" else @@ -474,15 +474,15 @@ function modmgr.dialog_configure_world() end end end - + retval = retval .. "button[8.5,-0.125;2.5,0.5;btn_all_mods;" .. fgettext("Enable all") .. "]" .. "textlist[5.5,0.5;5.5,5.75;world_config_modlist;" - + retval = retval .. modmgr.render_modlist(modmgr.modlist) - + retval = retval .. ";" .. modmgr.world_config_selected_mod .."]" - + return retval end @@ -490,23 +490,23 @@ end function modmgr.handle_buttons(tab,fields) local retval = nil - + if tab == "mod_mgr" then retval = modmgr.handle_modmgr_buttons(fields) end - + if tab == "dialog_rename_modpack" then retval = modmgr.handle_rename_modpack_buttons(fields) end - + if tab == "dialog_delete_mod" then retval = modmgr.handle_delete_mod_buttons(fields) end - + if tab == "dialog_configure_world" then retval = modmgr.handle_configure_world_buttons(fields) end - + return retval end @@ -516,13 +516,13 @@ function modmgr.get_dependencies(modfolder) if modfolder ~= nil then local filename = modfolder .. DIR_DELIM .. "depends.txt" - + local dependencyfile = io.open(filename,"r") - + if dependencyfile then local dependency = dependencyfile:read("*l") while dependency do - if toadd ~= "" then + if toadd ~= "" then toadd = toadd .. "," end toadd = toadd .. dependency @@ -542,11 +542,11 @@ function modmgr.get_worldconfig(worldpath) DIR_DELIM .. "world.mt" local worldfile = Settings(filename) - + local worldconfig = {} worldconfig.global_mods = {} worldconfig.game_mods = {} - + for key,value in pairs(worldfile:to_table()) do if key == "gameid" then worldconfig.id = value @@ -554,7 +554,7 @@ function modmgr.get_worldconfig(worldpath) worldconfig.global_mods[key] = engine.is_yes(value) end end - + --read gamemods local gamespec = gamemgr.find_by_gameid(worldconfig.id) gamemgr.get_game_mods(gamespec, worldconfig.game_mods) @@ -573,11 +573,11 @@ function modmgr.handle_modmgr_buttons(fields) local event = explode_textlist_event(fields["modlist"]) modmgr.selected_mod = event.index end - + if fields["btn_mod_mgr_install_local"] ~= nil then engine.show_file_open_dialog("mod_mgt_open_dlg",fgettext("Select Mod File:")) end - + if fields["btn_mod_mgr_download"] ~= nil then modstore.update_modlist() retval.current_tab = "dialog_modstore_unsorted" @@ -585,26 +585,26 @@ function modmgr.handle_modmgr_buttons(fields) retval.show_buttons = false return retval end - + if fields["btn_mod_mgr_rename_modpack"] ~= nil then retval.current_tab = "dialog_rename_modpack" retval.is_dialog = true retval.show_buttons = false return retval end - + if fields["btn_mod_mgr_delete_mod"] ~= nil then retval.current_tab = "dialog_delete_mod" retval.is_dialog = true retval.show_buttons = false return retval end - + if fields["mod_mgt_open_dlg_accepted"] ~= nil and fields["mod_mgt_open_dlg_accepted"] ~= "" then modmgr.installmod(fields["mod_mgt_open_dlg_accepted"],nil) end - + return nil; end @@ -612,27 +612,27 @@ end function modmgr.installmod(modfilename,basename) local modfile = modmgr.identify_filetype(modfilename) local modpath = modmgr.extract(modfile) - + if modpath == nil then gamedata.errormessage = fgettext("Install Mod: file: \"$1\"", modfile.name) .. fgettext("\nInstall Mod: unsupported filetype \"$1\"", modfile.type) return end - - + + local basefolder = modmgr.getbasefolder(modpath) - + if basefolder.type == "modpack" then local clean_path = nil - + if basename ~= nil then clean_path = "mp_" .. basename end - + if clean_path == nil then clean_path = get_last_folder(cleanup_path(basefolder.path)) end - + if clean_path ~= nil then local targetpath = engine.get_modpath() .. DIR_DELIM .. clean_path if not engine.copy_dir(basefolder.path,targetpath) then @@ -642,19 +642,19 @@ function modmgr.installmod(modfilename,basename) gamedata.errormessage = fgettext("Install Mod: unable to find suitable foldername for modpack $1", modfilename) end end - + if basefolder.type == "mod" then local targetfolder = basename - + if targetfolder == nil then targetfolder = modmgr.identify_modname(basefolder.path,"init.lua") end - + --if heuristic failed try to use current foldername if targetfolder == nil then targetfolder = get_last_folder(basefolder.path) - end - + end + if targetfolder ~= nil and modmgr.isValidModname(targetfolder) then local targetpath = engine.get_modpath() .. DIR_DELIM .. targetfolder engine.copy_dir(basefolder.path,targetpath) @@ -662,7 +662,7 @@ function modmgr.installmod(modfilename,basename) gamedata.errormessage = fgettext("Install Mod: unable to find real modname for: $1", modfilename) end end - + engine.delete_dir(modpath) modmgr.refresh_globals() @@ -671,7 +671,7 @@ end -------------------------------------------------------------------------------- function modmgr.handle_rename_modpack_buttons(fields) - + if fields["dlg_rename_modpack_confirm"] ~= nil then local mod = filterlist.get_list(modmgr.global_mods)[modmgr.selected_mod] local oldpath = engine.get_modpath() .. DIR_DELIM .. mod.name @@ -681,7 +681,7 @@ function modmgr.handle_rename_modpack_buttons(fields) modmgr.selected_mod = filterlist.get_current_index(modmgr.global_mods, filterlist.raw_index_by_uid(modmgr.global_mods, fields["te_modpack_name"])) end - + return { is_dialog = false, show_buttons = true, @@ -698,25 +698,25 @@ function modmgr.handle_configure_world_buttons(fields) modmgr.world_config_enable_mod(nil) end end - + if fields["key_enter"] ~= nil then modmgr.world_config_enable_mod(nil) end - + if fields["cb_mod_enable"] ~= nil then local toset = engine.is_yes(fields["cb_mod_enable"]) modmgr.world_config_enable_mod(toset) end - + if fields["btn_mp_enable"] ~= nil or fields["btn_mp_disable"] then local toset = (fields["btn_mp_enable"] ~= nil) modmgr.world_config_enable_mod(toset) end - + if fields["cb_hide_gamemods"] ~= nil then local current = filterlist.get_filtercriteria(modmgr.modlist) - + if current == nil then current = {} end @@ -728,13 +728,13 @@ function modmgr.handle_configure_world_buttons(fields) current.hide_game = false modmgr.hide_gamemods = false end - + filterlist.set_filtercriteria(modmgr.modlist,current) end - + if fields["cb_hide_mpcontent"] ~= nil then local current = filterlist.get_filtercriteria(modmgr.modlist) - + if current == nil then current = {} end @@ -746,21 +746,21 @@ function modmgr.handle_configure_world_buttons(fields) current.hide_modpackcontents = false modmgr.hide_modpackcontents = false end - + filterlist.set_filtercriteria(modmgr.modlist,current) end - + if fields["btn_config_world_save"] then local worldspec = engine.get_worlds()[modmgr.world_config_selected_world] - + local filename = worldspec.path .. DIR_DELIM .. "world.mt" - + local worldfile = Settings(filename) local mods = worldfile:to_table() - + local rawlist = filterlist.get_raw_list(modmgr.modlist) - + local i,mod for i,mod in ipairs(rawlist) do if not mod.is_modpack and @@ -773,42 +773,42 @@ function modmgr.handle_configure_world_buttons(fields) mods["load_mod_"..mod.name] = nil end end - + -- Remove mods that are not present anymore for key,value in pairs(mods) do if key:sub(1,9) == "load_mod_" then worldfile:remove(key) end end - + if not worldfile:write() then engine.log("error", "Failed to write world config file") end - + modmgr.modlist = nil modmgr.worldconfig = nil - + return { is_dialog = false, show_buttons = true, current_tab = engine.setting_get("main_menu_tab") } end - + if fields["btn_config_world_cancel"] then - + modmgr.worldconfig = nil - + return { is_dialog = false, show_buttons = true, current_tab = engine.setting_get("main_menu_tab") } end - + if fields["btn_all_mods"] then local list = filterlist.get_raw_list(modmgr.modlist) - + for i=1,#list,1 do if list[i].typ ~= "game_mod" and not list[i].is_modpack then @@ -816,9 +816,9 @@ function modmgr.handle_configure_world_buttons(fields) end end end - - + + return nil end -------------------------------------------------------------------------------- @@ -849,9 +849,9 @@ end -------------------------------------------------------------------------------- function modmgr.handle_delete_mod_buttons(fields) local mod = filterlist.get_list(modmgr.global_mods)[modmgr.selected_mod] - + if fields["dlg_delete_mod_confirm"] ~= nil then - + if mod.path ~= nil and mod.path ~= "" and mod.path ~= engine.get_modpath() then @@ -863,7 +863,7 @@ function modmgr.handle_delete_mod_buttons(fields) gamedata.errormessage = fgettext("Modmgr: invalid modpath \"$1\"", mod.path) end end - + return { is_dialog = false, show_buttons = true, @@ -875,8 +875,8 @@ end function modmgr.dialog_delete_mod() local mod = filterlist.get_list(modmgr.global_mods)[modmgr.selected_mod] - - local retval = + + local retval = "field[1.75,1;10,3;;" .. fgettext("Are you sure you want to delete \"$1\"?", mod.name) .. ";]".. "button[4,4.2;1,0.5;dlg_delete_mod_confirm;" .. fgettext("Yes") .. "]" .. "button[6.5,4.2;3,0.5;dlg_delete_mod_cancel;" .. fgettext("No of course not!") .. "]" @@ -887,10 +887,10 @@ end -------------------------------------------------------------------------------- function modmgr.preparemodlist(data) local retval = {} - + local global_mods = {} local game_mods = {} - + --read global mods local modpath = engine.get_modpath() @@ -898,31 +898,31 @@ function modmgr.preparemodlist(data) modpath ~= "" then get_mods(modpath,global_mods) end - + for i=1,#global_mods,1 do global_mods[i].typ = "global_mod" table.insert(retval,global_mods[i]) end - + --read game mods local gamespec = gamemgr.find_by_gameid(data.gameid) gamemgr.get_game_mods(gamespec, game_mods) - + for i=1,#game_mods,1 do game_mods[i].typ = "game_mod" table.insert(retval,game_mods[i]) end - + if data.worldpath == nil then return retval end - + --read world mod configuration local filename = data.worldpath .. DIR_DELIM .. "world.mt" local worldfile = Settings(filename) - + for key,value in pairs(worldfile:to_table()) do if key:sub(1, 9) == "load_mod_" then key = key:sub(10) @@ -948,17 +948,17 @@ end function modmgr.init_worldconfig() modmgr.precheck() local worldspec = engine.get_worlds()[modmgr.world_config_selected_world] - + if worldspec ~= nil then --read worldconfig modmgr.worldconfig = modmgr.get_worldconfig(worldspec.path) - + if modmgr.worldconfig.id == nil or modmgr.worldconfig.id == "" then modmgr.worldconfig = nil return false end - + modmgr.modlist = filterlist.create( modmgr.preparemodlist, --refresh modmgr.comparemod, --compare @@ -966,13 +966,13 @@ function modmgr.init_worldconfig() if element.name == uid then return true end - end, + end, function(element,criteria) if criteria.hide_game and element.typ == "game_mod" then return false end - + if criteria.hide_modpackcontents and element.modpack ~= nil then return false @@ -982,15 +982,15 @@ function modmgr.init_worldconfig() { worldpath= worldspec.path, gameid = worldspec.gameid } ) - + filterlist.set_filtercriteria(modmgr.modlist, { hide_game=modmgr.hide_gamemods, hide_modpackcontents= modmgr.hide_modpackcontents }) filterlist.add_sort_mechanism(modmgr.modlist, "alphabetic", sort_mod_list) filterlist.set_sortmode(modmgr.modlist, "alphabetic") - - return true + + return true end return false @@ -1013,34 +1013,34 @@ function modmgr.comparemod(elem1,elem2) if elem1.modpack ~= elem2.modpack then return false end - + if elem1.path ~= elem2.path then return false end - + return true end -------------------------------------------------------------------------------- function modmgr.gettab(name) local retval = "" - + if name == "mod_mgr" then retval = retval .. modmgr.tab() end - + if name == "dialog_rename_modpack" then retval = retval .. modmgr.dialog_rename_modpack() end - + if name == "dialog_delete_mod" then retval = retval .. modmgr.dialog_delete_mod() end - + if name == "dialog_configure_world" then retval = retval .. modmgr.dialog_configure_world() end - + return retval end @@ -1054,7 +1054,7 @@ function modmgr.mod_exists(basename) if filterlist.raw_index_by_uid(modmgr.global_mods,basename) > 0 then return true end - + return false end @@ -1064,7 +1064,7 @@ function modmgr.get_global_mod(idx) if modmgr.global_mods == nil then return nil end - + if idx < 1 or idx > filterlist.size(modmgr.global_mods) then return nil end @@ -1081,7 +1081,7 @@ function modmgr.refresh_globals() if element.name == uid then return true end - end, + end, nil, --filter {} ) @@ -1098,7 +1098,7 @@ function modmgr.identify_filetype(name) type = "zip" } end - + if name:sub(-6):lower() == "tar.gz" or name:sub(-3):lower() == "tgz"then return { @@ -1106,14 +1106,14 @@ function modmgr.identify_filetype(name) type = "tgz" } end - + if name:sub(-6):lower() == "tar.bz2" then return { name = name, type = "tbz" } end - + if name:sub(-2):lower() == "7z" then return { name = name, diff --git a/builtin/modstore.lua b/builtin/modstore.lua index b364ce6..acaff87 100644 --- a/builtin/modstore.lua +++ b/builtin/modstore.lua @@ -23,19 +23,20 @@ modstore = {} -------------------------------------------------------------------------------- function modstore.init() modstore.tabnames = {} - + table.insert(modstore.tabnames,"dialog_modstore_unsorted") table.insert(modstore.tabnames,"dialog_modstore_search") - + modstore.modsperpage = 5 - - modstore.basetexturedir = engine.get_texturepath() .. DIR_DELIM .. "base" .. + + modstore.basetexturedir = engine.get_texturepath() .. DIR_DELIM .. "base" .. DIR_DELIM .. "pack" .. DIR_DELIM - + + modstore.lastmodtitle = "" + modstore.current_list = nil - - modstore.details_cache = {} end + -------------------------------------------------------------------------------- function modstore.nametoindex(name) @@ -51,30 +52,34 @@ end -------------------------------------------------------------------------------- function modstore.gettab(tabname) local retval = "" - + local is_modstore_tab = false - + if tabname == "dialog_modstore_unsorted" then retval = modstore.getmodlist(modstore.modlist_unsorted) is_modstore_tab = true end - + if tabname == "dialog_modstore_search" then - - + retval = modstore.getsearchpage() is_modstore_tab = true end - + if is_modstore_tab then return modstore.tabheader(tabname) .. retval end - + if tabname == "modstore_mod_installed" then - return "size[6,2]label[0.25,0.25;Mod: " .. modstore.lastmodtitle .. + return "size[6,2]label[0.25,0.25;Mod(s): " .. modstore.lastmodtitle .. " installed successfully]" .. "button[2.5,1.5;1,0.5;btn_confirm_mod_successfull;ok]" end - + + if tabname == "modstore_downloading" then + return "size[6,2]label[0.25,0.25;Dowloading " .. modstore.lastmodtitle .. + " please wait]" + end + return "" end @@ -84,18 +89,16 @@ function modstore.tabheader(tabname) retval = retval .. "tabheader[-0.3,-0.99;modstore_tab;" .. "Unsorted,Search;" .. modstore.nametoindex(tabname) .. ";true;false]" - + return retval end -------------------------------------------------------------------------------- function modstore.handle_buttons(current_tab,fields) - modstore.lastmodtitle = "" - if fields["modstore_tab"] then local index = tonumber(fields["modstore_tab"]) - + if index > 0 and index <= #modstore.tabnames then return { @@ -104,59 +107,102 @@ function modstore.handle_buttons(current_tab,fields) show_buttons = false } end - + modstore.modlist_page = 0 end - + if fields["btn_modstore_page_up"] then if modstore.current_list ~= nil and modstore.current_list.page > 0 then modstore.current_list.page = modstore.current_list.page - 1 end end - + if fields["btn_modstore_page_down"] then - if modstore.current_list ~= nil and + if modstore.current_list ~= nil and modstore.current_list.page #list.data) then endmod = #list.data end for i=(list.page * modstore.modsperpage) +1, endmod, 1 do --getmoddetails - local details = modstore.get_details(list.data[i].id) - + local details = list.data[i].details + +-- if details == nil then +-- details = modstore.get_details(list.data[i].id) +-- end + + if details == nil then + details = {} + details.title = list.data[i].title + details.author = "" + details.rating = -1 + details.description = "" + end + if details ~= nil then local screenshot_ypos = (i-1 - (list.page * modstore.modsperpage))*1.9 +0.2 - + retval = retval .. "box[0," .. screenshot_ypos .. ";11.4,1.75;#FFFFFF]" - - --screenshot - if details.screenshot_url ~= nil and - details.screenshot_url ~= "" then - if list.data[i].texturename == nil then - local fullurl = engine.setting_get("modstore_download_url") .. - details.screenshot_url - local filename = os.tempfolder() - - if engine.download_file(fullurl,filename) then - list.data[i].texturename = filename + + if details.basename then + --screenshot + if details.screenshot_url ~= nil and + details.screenshot_url ~= "" then + if list.data[i].texturename == nil then + local fullurl = engine.setting_get("modstore_download_url") .. + details.screenshot_url + local filename = os.tempfolder() .. "_MID_" .. list.data[i].id + list.data[i].texturename = "in progress" + engine.handle_async( + function(param) + param.successfull = engine.download_file(param.fullurl,param.filename) + return param + end, + { + fullurl = fullurl, + filename = filename, + listindex = i, + modid = list.data[i].id + }, + function(result) + if modstore.modlist_unsorted and + modstore.modlist_unsorted.data and + #modstore.modlist_unsorted.data >= result.listindex and + modstore.modlist_unsorted.data[result.listindex].id == result.modid then + if result.successfull then + modstore.modlist_unsorted.data[result.listindex].texturename = result.filename + else + modstore.modlist_unsorted.data[result.listindex].texturename = modstore.basetexturedir .. "no_screenshot.png" + end + engine.event_handler("Refresh") + end + end + ) + end + else + if list.data[i].texturename == nil then + list.data[i].texturename = modstore.basetexturedir .. "no_screenshot.png" end end + + if list.data[i].texturename ~= nil and + list.data[i].texturename ~= "in progress" then + retval = retval .. "image[0,".. screenshot_ypos .. ";3,2;" .. + engine.formspec_escape(list.data[i].texturename) .. "]" + end end - - if list.data[i].texturename == nil then - list.data[i].texturename = modstore.basetexturedir .. "no_screenshot.png" - end - - retval = retval .. "image[0,".. screenshot_ypos .. ";3,2;" .. - engine.formspec_escape(list.data[i].texturename) .. "]" - + --title + author - retval = retval .."label[2.75," .. screenshot_ypos .. ";" .. + retval = retval .."label[2.75," .. screenshot_ypos .. ";" .. engine.formspec_escape(details.title) .. " (" .. details.author .. ")]" - + --description local descriptiony = screenshot_ypos + 0.5 - retval = retval .. "textarea[3," .. descriptiony .. ";6.5,1.55;;" .. + retval = retval .. "textarea[3," .. descriptiony .. ";6.5,1.55;;" .. engine.formspec_escape(details.description) .. ";]" --rating local ratingy = screenshot_ypos + 0.6 - retval = retval .."label[10.1," .. ratingy .. ";" .. - fgettext("Rating") .. ": " .. details.rating .."]" - - --install button - local buttony = screenshot_ypos + 1.2 - local buttonnumber = (i - (list.page * modstore.modsperpage)) - retval = retval .."button[9.6," .. buttony .. ";2,0.5;btn_install_mod_" .. buttonnumber .. ";" - - if modmgr.mod_exists(details.basename) then - retval = retval .. fgettext("re-Install") .."]" - else - retval = retval .. fgettext("Install") .."]" + retval = retval .."label[9.1," .. ratingy .. ";" .. + fgettext("Rating") .. ":]" + retval = retval .. "label[11.1," .. ratingy .. ";" .. details.rating .."]" + + if details.basename then + --install button + local buttony = screenshot_ypos + 1.2 + local buttonnumber = (i - (list.page * modstore.modsperpage)) + retval = retval .."button[9.1," .. buttony .. ";2.5,0.5;btn_install_mod_" .. buttonnumber .. ";" + + if modmgr.mod_exists(details.basename) then + retval = retval .. fgettext("re-Install") .."]" + else + retval = retval .. fgettext("Install") .."]" + end end end end - + modstore.current_list = list - + return retval end -------------------------------------------------------------------------------- -function modstore.get_details(modid) +function modstore.getsearchpage() + local retval = "" - if modstore.details_cache[modid] ~= nil then - return modstore.details_cache[modid] - end - - local retval = engine.get_modstore_details(tostring(modid)) - modstore.details_cache[modid] = retval - return retval + --TODO implement search! + + return retval; end