2 --Copyright (C) 2013 sapier
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.
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.
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.
18 --------------------------------------------------------------------------------
20 --modstore implementation
23 --------------------------------------------------------------------------------
24 -- @function [parent=#modstore] init
25 function modstore.init(size, unsortedmods, searchmods)
27 modstore.mods_on_unsorted_page = unsortedmods
28 modstore.mods_on_search_page = searchmods
29 modstore.modsperpage = modstore.mods_on_unsorted_page
31 modstore.basetexturedir = core.get_texturepath() .. DIR_DELIM .. "base" ..
32 DIR_DELIM .. "pack" .. DIR_DELIM
34 modstore.lastmodtitle = ""
35 modstore.last_search = ""
37 modstore.searchlist = filterlist.create(
39 if modstore.modlist_unsorted ~= nil and
40 modstore.modlist_unsorted.data ~= nil then
41 return modstore.modlist_unsorted.data
45 function(element,modid)
46 if element.id == modid then
52 function(element,substring)
53 if substring == nil or
57 substring = substring:upper()
59 if element.title ~= nil and
60 element.title:upper():find(substring) ~= nil then
64 if element.details ~= nil and
65 element.details.author ~= nil and
66 element.details.author:upper():find(substring) ~= nil then
70 if element.details ~= nil and
71 element.details.description ~= nil and
72 element.details.description:upper():find(substring) ~= nil then
79 modstore.current_list = nil
81 modstore.tv_store = tabview_create("modstore",size,{x=-0.3,y=-0.99})
83 modstore.tv_store:set_global_event_handler(modstore.handle_events)
85 modstore.tv_store:add(
88 caption = fgettext("Unsorted"),
89 cbf_formspec = modstore.unsorted_tab,
90 cbf_button_handler = modstore.handle_buttons,
92 function() modstore.modsperpage = modstore.mods_on_unsorted_page end
96 modstore.tv_store:add(
99 caption = fgettext("Search"),
100 cbf_formspec = modstore.getsearchpage,
101 cbf_button_handler = modstore.handle_buttons,
102 on_change = modstore.activate_search_tab
107 --------------------------------------------------------------------------------
108 -- @function [parent=#modstore] nametoindex
109 function modstore.nametoindex(name)
111 for i=1,#modstore.tabnames,1 do
112 if modstore.tabnames[i] == name then
120 --------------------------------------------------------------------------------
121 -- @function [parent=#modstore] showdownloading
122 function modstore.showdownloading(title)
123 local new_dlg = dialog_create("store_downloading",
125 return "size[6,2]label[0.25,0.75;" .. fgettext("Downloading") ..
126 " " .. data.title .. " " ..
127 fgettext("please wait...") .. "]"
129 function(this,fields)
130 if fields["btn_hidden_close_download"] ~= nil then
131 if fields["btn_hidden_close_download"].successfull then
132 modstore.lastmodentry = fields["btn_hidden_close_download"]
133 modstore.successfulldialog()
135 modstore.lastmodtitle = ""
147 new_dlg.data.title = title
151 --------------------------------------------------------------------------------
152 -- @function [parent=#modstore] successfulldialog
153 function modstore.successfulldialog()
154 local new_dlg = dialog_create("store_downloading",
157 retval = retval .. "size[6,2,true]"
158 if modstore.lastmodentry ~= nil then
159 retval = retval .. "label[0,0.25;" .. fgettext("Successfully installed:") .. "]"
160 retval = retval .. "label[3,0.25;" .. modstore.lastmodentry.moddetails.title .. "]"
163 retval = retval .. "label[0,0.75;" .. fgettext("Shortname:") .. "]"
164 retval = retval .. "label[3,0.75;" .. core.formspec_escape(modstore.lastmodentry.moddetails.basename) .. "]"
167 retval = retval .. "button[2.5,1.5;1,0.5;btn_confirm_mod_successfull;" .. fgettext("ok") .. "]"
169 function(this,fields)
170 if fields["btn_confirm_mod_successfull"] ~= nil then
183 new_dlg.data.title = title
187 --------------------------------------------------------------------------------
188 -- @function [parent=#modstore] handle_buttons
189 function modstore.handle_buttons(parent, fields, name, data)
191 if fields["btn_modstore_page_up"] then
192 if modstore.current_list ~= nil and modstore.current_list.page > 0 then
193 modstore.current_list.page = modstore.current_list.page - 1
198 if fields["btn_modstore_page_down"] then
199 if modstore.current_list ~= nil and
200 modstore.current_list.page <modstore.current_list.pagecount-1 then
201 modstore.current_list.page = modstore.current_list.page +1
206 if fields["btn_modstore_search"] or
207 (fields["key_enter"] and fields["te_modstore_search"] ~= nil) then
208 modstore.last_search = fields["te_modstore_search"]
209 filterlist.set_filtercriteria(modstore.searchlist,fields["te_modstore_search"])
210 filterlist.refresh(modstore.searchlist)
211 modstore.currentlist = {
213 pagecount = math.ceil(filterlist.size(modstore.searchlist) / modstore.modsperpage),
214 data = filterlist.get_list(modstore.searchlist),
219 if fields["btn_modstore_close"] then
224 for key,value in pairs(fields) do
225 local foundat = key:find("btn_install_mod_")
226 if ( foundat == 1) then
227 local modid = tonumber(key:sub(17))
228 for i=1,#modstore.modlist_unsorted.data,1 do
229 if modstore.modlist_unsorted.data[i].id == modid then
230 local moddetails = modstore.modlist_unsorted.data[i].details
232 if modstore.lastmodtitle ~= "" then
233 modstore.lastmodtitle = modstore.lastmodtitle .. ", "
236 modstore.lastmodtitle = modstore.lastmodtitle .. moddetails.title
238 if not core.handle_async(
240 local fullurl = core.setting_get("modstore_download_url") ..
241 param.moddetails.download_url
243 if param.version ~= nil then
245 for i=1,#param.moddetails.versions, 1 do
246 if param.moddetails.versions[i].date:sub(1,10) == param.version then
247 fullurl = core.setting_get("modstore_download_url") ..
248 param.moddetails.versions[i].download_url
254 core.log("error","no download url found for version " .. dump(param.version))
256 moddetails = param.moddetails,
262 if core.download_file(fullurl,param.filename) then
264 texturename = param.texturename,
265 moddetails = param.moddetails,
266 filename = param.filename,
270 core.log("error","downloading " .. dump(fullurl) .. " failed")
272 moddetails = param.moddetails,
278 moddetails = moddetails,
279 version = fields["dd_version" .. modid],
280 filename = os.tempfolder() .. "_MODNAME_" .. moddetails.basename .. ".zip",
281 texturename = modstore.modlist_unsorted.data[i].texturename
284 print("Result from async: " .. dump(result.successfull))
285 if result.successfull then
286 modmgr.installmod(result.filename,result.moddetails.basename)
287 os.remove(result.filename)
289 gamedata.errormessage = "Failed to download " .. result.moddetails.title
292 if gamedata.errormessage == nil then
293 core.button_handler({btn_hidden_close_download=result})
295 core.button_handler({btn_hidden_close_download={successfull=false}})
299 print("ERROR: async event failed")
300 gamedata.errormessage = "Failed to download " .. modstore.lastmodtitle
303 modstore.showdownloading(modstore.lastmodtitle)
314 --------------------------------------------------------------------------------
315 -- @function [parent=#modstore] handle_events
316 function modstore.handle_events(this,event)
317 if (event == "MenuQuit") then
323 --------------------------------------------------------------------------------
324 -- @function [parent=#modstore] update_modlist
325 function modstore.update_modlist()
326 modstore.modlist_unsorted = {}
327 modstore.modlist_unsorted.data = {}
328 modstore.modlist_unsorted.pagecount = 1
329 modstore.modlist_unsorted.page = 0
333 return core.get_modstore_list()
337 if result ~= nil then
338 modstore.modlist_unsorted = {}
339 modstore.modlist_unsorted.data = result
341 if modstore.modlist_unsorted.data ~= nil then
342 modstore.modlist_unsorted.pagecount =
343 math.ceil((#modstore.modlist_unsorted.data / modstore.modsperpage))
345 modstore.modlist_unsorted.data = {}
346 modstore.modlist_unsorted.pagecount = 1
348 modstore.modlist_unsorted.page = 0
349 modstore.fetchdetails()
350 core.event_handler("Refresh")
356 --------------------------------------------------------------------------------
357 -- @function [parent=#modstore] fetchdetails
358 function modstore.fetchdetails()
360 for i=1,#modstore.modlist_unsorted.data,1 do
363 param.details = core.get_modstore_details(tostring(param.modid))
367 modid=modstore.modlist_unsorted.data[i].id,
372 modstore.modlist_unsorted ~= nil
373 and modstore.modlist_unsorted.data ~= nil and
374 modstore.modlist_unsorted.data[result.listindex] ~= nil and
375 modstore.modlist_unsorted.data[result.listindex].id ~= nil then
377 modstore.modlist_unsorted.data[result.listindex].details = result.details
378 core.event_handler("Refresh")
385 --------------------------------------------------------------------------------
386 -- @function [parent=#modstore] getscreenshot
387 function modstore.getscreenshot(ypos,listentry)
389 if listentry.details ~= nil and
390 (listentry.details.screenshot_url == nil or
391 listentry.details.screenshot_url == "") then
393 if listentry.texturename == nil then
394 listentry.texturename = modstore.basetexturedir .. "no_screenshot.png"
397 return "image[0,".. ypos .. ";3,2;" ..
398 core.formspec_escape(listentry.texturename) .. "]"
401 if listentry.details ~= nil and
402 listentry.texturename == nil then
403 --make sure we don't download multiple times
404 listentry.texturename = "in progress"
406 --prepare url and filename
407 local fullurl = core.setting_get("modstore_download_url") ..
408 listentry.details.screenshot_url
409 local filename = os.tempfolder() .. "_MID_" .. listentry.id
413 --first param is downloadfct
415 param.successfull = core.download_file(param.fullurl,param.filename)
418 --second parameter is data passed to async job
424 --integrate result to raw list
426 if result.successfull then
428 for i=1,#modstore.modlist_unsorted.data,1 do
429 if modstore.modlist_unsorted.data[i].id == result.modid then
431 modstore.modlist_unsorted.data[i].texturename = result.filename
436 core.event_handler("Refresh")
438 core.log("error","got screenshot but didn't find matching mod: " .. result.modid)
445 if listentry.texturename ~= nil and
446 listentry.texturename ~= "in progress" then
447 return "image[0,".. ypos .. ";3,2;" ..
448 core.formspec_escape(listentry.texturename) .. "]"
454 --------------------------------------------------------------------------------
455 --@function [parent=#modstore] getshortmodinfo
456 function modstore.getshortmodinfo(ypos,listentry,details)
459 retval = retval .. "box[0," .. ypos .. ";11.4,1.75;#FFFFFF]"
462 retval = retval .. modstore.getscreenshot(ypos,listentry)
465 retval = retval .."label[2.75," .. ypos .. ";" ..
466 core.formspec_escape(details.title) .. " (" .. details.author .. ")]"
469 local descriptiony = ypos + 0.5
470 retval = retval .. "textarea[3," .. descriptiony .. ";6.5,1.55;;" ..
471 core.formspec_escape(details.description) .. ";]"
475 retval = retval .."label[7," .. ratingy .. ";" ..
476 fgettext("Rating") .. ":]"
477 retval = retval .. "label[8.7," .. ratingy .. ";" .. details.rating .."]"
479 --versions (IMPORTANT has to be defined AFTER rating)
480 if details.versions ~= nil and
481 #details.versions > 1 then
482 local versiony = ypos + 0.05
483 retval = retval .. "dropdown[9.1," .. versiony .. ";2.48,0.25;dd_version" .. details.id .. ";"
485 for i=1,#details.versions , 1 do
486 if versions ~= "" then
487 versions = versions .. ","
490 versions = versions .. details.versions[i].date:sub(1,10)
492 retval = retval .. versions .. ";1]"
495 if details.basename then
497 local buttony = ypos + 1.2
498 retval = retval .."button[9.1," .. buttony .. ";2.5,0.5;btn_install_mod_" .. details.id .. ";"
500 if modmgr.mod_exists(details.basename) then
501 retval = retval .. fgettext("re-Install") .."]"
503 retval = retval .. fgettext("Install") .."]"
510 --------------------------------------------------------------------------------
511 --@function [parent=#modstore] getmodlist
512 function modstore.getmodlist(list,yoffset)
513 modstore.current_list = list
515 if yoffset == nil then
519 local sb_y_start = 0.2 + yoffset
520 local sb_y_end = (modstore.modsperpage * 1.75) + ((modstore.modsperpage-1) * 0.15)
521 local close_button = "button[4," .. (sb_y_end + 0.3 + yoffset) ..
522 ";4,0.5;btn_modstore_close;" .. fgettext("Close store") .. "]"
524 if #list.data == 0 then
529 scrollbar = scrollbar .. "label[0.1,".. (sb_y_end + 0.25 + yoffset) ..";"
530 .. fgettext("Page $1 of $2", list.page+1, list.pagecount) .. "]"
531 scrollbar = scrollbar .. "box[11.6," .. sb_y_start .. ";0.28," .. sb_y_end .. ";#000000]"
532 local scrollbarpos = (sb_y_start + 0.5) +
533 ((sb_y_end -1.6)/(list.pagecount-1)) * list.page
534 scrollbar = scrollbar .. "box[11.6," ..scrollbarpos .. ";0.28,0.5;#32CD32]"
535 scrollbar = scrollbar .. "button[11.6," .. (sb_y_start)
536 .. ";0.5,0.5;btn_modstore_page_up;^]"
537 scrollbar = scrollbar .. "button[11.6," .. (sb_y_start + sb_y_end - 0.5)
538 .. ";0.5,0.5;btn_modstore_page_down;v]"
542 local endmod = (list.page * modstore.modsperpage) + modstore.modsperpage
544 if (endmod > #list.data) then
548 for i=(list.page * modstore.modsperpage) +1, endmod, 1 do
550 local details = list.data[i].details
552 if details == nil then
554 details.title = list.data[i].title
557 details.description = ""
560 if details ~= nil then
561 local screenshot_ypos =
562 yoffset +(i-1 - (list.page * modstore.modsperpage))*1.9 +0.2
564 retval = retval .. modstore.getshortmodinfo(screenshot_ypos,
570 return retval .. scrollbar .. close_button
573 --------------------------------------------------------------------------------
574 --@function [parent=#modstore] getsearchpage
575 function modstore.getsearchpage(tabview, name, tabdata)
579 if modstore.last_search ~= nil then
580 search = modstore.last_search
584 "button[9.5,0.2;2.5,0.5;btn_modstore_search;".. fgettext("Search") .. "]" ..
585 "field[0.5,0.5;9,0.5;te_modstore_search;;" .. search .. "]"
589 modstore.currentlist,
595 --------------------------------------------------------------------------------
596 --@function [parent=#modstore] unsorted_tab
597 function modstore.unsorted_tab()
598 return modstore.getmodlist(modstore.modlist_unsorted)
601 --------------------------------------------------------------------------------
602 --@function [parent=#modstore] activate_search_tab
603 function modstore.activate_search_tab(type, old_tab, new_tab)
605 if old_tab == new_tab then
608 filterlist.set_filtercriteria(modstore.searchlist,modstore.last_search)
609 filterlist.refresh(modstore.searchlist)
610 modstore.modsperpage = modstore.mods_on_search_page
611 modstore.currentlist = {
614 math.ceil(filterlist.size(modstore.searchlist) / modstore.modsperpage),
615 data = filterlist.get_list(modstore.searchlist),