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,y=0})
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;" ..
126 fgettext("Downloading $1, please wait...", data.title) .. "]"
128 function(this,fields)
129 if fields["btn_hidden_close_download"] ~= nil then
130 if fields["btn_hidden_close_download"].successfull then
131 modstore.lastmodentry = fields["btn_hidden_close_download"]
132 modstore.successfulldialog(this)
136 modstore.lastmodtitle = ""
146 new_dlg:set_parent(modstore.tv_store)
147 modstore.tv_store:hide()
148 new_dlg.data.title = title
152 --------------------------------------------------------------------------------
153 -- @function [parent=#modstore] successfulldialog
154 function modstore.successfulldialog(downloading_dlg)
155 local new_dlg = dialog_create("store_downloading",
158 retval = retval .. "size[6,2,true]"
159 if modstore.lastmodentry ~= nil then
160 retval = retval .. "label[0,0.25;" .. fgettext("Successfully installed:") .. "]"
161 retval = retval .. "label[3,0.25;" .. modstore.lastmodentry.moddetails.title .. "]"
162 retval = retval .. "label[0,0.75;" .. fgettext("Shortname:") .. "]"
163 retval = retval .. "label[3,0.75;" .. core.formspec_escape(modstore.lastmodentry.moddetails.basename) .. "]"
165 retval = retval .. "button[2.2,1.5;1.5,0.5;btn_confirm_mod_successfull;" .. fgettext("Ok") .. "]"
168 function(this,fields)
169 if fields["btn_confirm_mod_successfull"] ~= nil then
171 downloading_dlg:delete()
181 new_dlg:set_parent(modstore.tv_store)
182 modstore.tv_store:hide()
186 --------------------------------------------------------------------------------
187 -- @function [parent=#modstore] handle_buttons
188 function modstore.handle_buttons(parent, fields, name, data)
190 if fields["btn_modstore_page_up"] then
191 if modstore.current_list ~= nil and modstore.current_list.page > 0 then
192 modstore.current_list.page = modstore.current_list.page - 1
197 if fields["btn_modstore_page_down"] then
198 if modstore.current_list ~= nil and
199 modstore.current_list.page <modstore.current_list.pagecount-1 then
200 modstore.current_list.page = modstore.current_list.page +1
205 if fields["btn_modstore_search"] or
206 (fields["key_enter"] and fields["te_modstore_search"] ~= nil) then
207 modstore.last_search = fields["te_modstore_search"]
208 filterlist.set_filtercriteria(modstore.searchlist,fields["te_modstore_search"])
209 filterlist.refresh(modstore.searchlist)
210 modstore.currentlist = {
212 pagecount = math.ceil(filterlist.size(modstore.searchlist) / modstore.modsperpage),
213 data = filterlist.get_list(modstore.searchlist),
218 if fields["btn_modstore_close"] then
219 local maintab = ui.find_by_name("maintab")
225 for key,value in pairs(fields) do
226 local foundat = key:find("btn_install_mod_")
227 if ( foundat == 1) then
228 local modid = tonumber(key:sub(17))
229 for i=1,#modstore.modlist_unsorted.data,1 do
230 if modstore.modlist_unsorted.data[i].id == modid then
231 local moddetails = modstore.modlist_unsorted.data[i].details
232 modstore.lastmodtitle = moddetails.title
234 if not core.handle_async(
236 local fullurl = core.setting_get("modstore_download_url") ..
237 param.moddetails.download_url
239 if param.version ~= nil then
241 for i=1,#param.moddetails.versions, 1 do
242 if param.moddetails.versions[i].date:sub(1,10) == param.version then
243 fullurl = core.setting_get("modstore_download_url") ..
244 param.moddetails.versions[i].download_url
250 core.log("error","no download url found for version " .. dump(param.version))
252 moddetails = param.moddetails,
258 if core.download_file(fullurl,param.filename) then
260 texturename = param.texturename,
261 moddetails = param.moddetails,
262 filename = param.filename,
266 core.log("error","downloading " .. dump(fullurl) .. " failed")
268 moddetails = param.moddetails,
274 moddetails = moddetails,
275 version = fields["dd_version" .. modid],
276 filename = os.tempfolder() .. "_MODNAME_" .. moddetails.basename .. ".zip",
277 texturename = modstore.modlist_unsorted.data[i].texturename
280 --print("Result from async: " .. dump(result.successfull))
281 if result.successfull then
282 modmgr.installmod(result.filename,result.moddetails.basename)
283 os.remove(result.filename)
285 gamedata.errormessage = "Failed to download " .. result.moddetails.title
288 if gamedata.errormessage == nil then
289 core.button_handler({btn_hidden_close_download=result})
291 core.button_handler({btn_hidden_close_download={successfull=false}})
295 print("ERROR: async event failed")
296 gamedata.errormessage = "Failed to download " .. modstore.lastmodtitle
299 modstore.showdownloading(modstore.lastmodtitle)
310 --------------------------------------------------------------------------------
311 -- @function [parent=#modstore] handle_events
312 function modstore.handle_events(this,event)
313 if (event == "MenuQuit") then
319 --------------------------------------------------------------------------------
320 -- @function [parent=#modstore] update_modlist
321 function modstore.update_modlist()
322 modstore.modlist_unsorted = {}
323 modstore.modlist_unsorted.data = {}
324 modstore.modlist_unsorted.pagecount = 1
325 modstore.modlist_unsorted.page = 0
329 return core.get_modstore_list()
333 if result ~= nil then
334 modstore.modlist_unsorted = {}
335 modstore.modlist_unsorted.data = result
337 if modstore.modlist_unsorted.data ~= nil then
338 modstore.modlist_unsorted.pagecount =
339 math.ceil((#modstore.modlist_unsorted.data / modstore.modsperpage))
341 modstore.modlist_unsorted.data = {}
342 modstore.modlist_unsorted.pagecount = 1
344 modstore.modlist_unsorted.page = 0
345 modstore.fetchdetails()
346 core.event_handler("Refresh")
352 --------------------------------------------------------------------------------
353 -- @function [parent=#modstore] fetchdetails
354 function modstore.fetchdetails()
356 for i=1,#modstore.modlist_unsorted.data,1 do
359 param.details = core.get_modstore_details(tostring(param.modid))
363 modid=modstore.modlist_unsorted.data[i].id,
368 modstore.modlist_unsorted ~= nil
369 and modstore.modlist_unsorted.data ~= nil and
370 modstore.modlist_unsorted.data[result.listindex] ~= nil and
371 modstore.modlist_unsorted.data[result.listindex].id ~= nil then
373 modstore.modlist_unsorted.data[result.listindex].details = result.details
374 core.event_handler("Refresh")
381 --------------------------------------------------------------------------------
382 -- @function [parent=#modstore] getscreenshot
383 function modstore.getscreenshot(ypos,listentry)
385 if listentry.details ~= nil and
386 (listentry.details.screenshot_url == nil or
387 listentry.details.screenshot_url == "") then
389 if listentry.texturename == nil then
390 listentry.texturename = defaulttexturedir .. "no_screenshot.png"
393 return "image[0,".. ypos .. ";3,2;" ..
394 core.formspec_escape(listentry.texturename) .. "]"
397 if listentry.details ~= nil and
398 listentry.texturename == nil then
399 --make sure we don't download multiple times
400 listentry.texturename = "in progress"
402 --prepare url and filename
403 local fullurl = core.setting_get("modstore_download_url") ..
404 listentry.details.screenshot_url
405 local filename = os.tempfolder() .. "_MID_" .. listentry.id
409 --first param is downloadfct
411 param.successfull = core.download_file(param.fullurl,param.filename)
414 --second parameter is data passed to async job
420 --integrate result to raw list
422 if result.successfull then
424 for i=1,#modstore.modlist_unsorted.data,1 do
425 if modstore.modlist_unsorted.data[i].id == result.modid then
427 modstore.modlist_unsorted.data[i].texturename = result.filename
432 core.event_handler("Refresh")
434 core.log("error","got screenshot but didn't find matching mod: " .. result.modid)
441 if listentry.texturename ~= nil and
442 listentry.texturename ~= "in progress" then
443 return "image[0,".. ypos .. ";3,2;" ..
444 core.formspec_escape(listentry.texturename) .. "]"
450 --------------------------------------------------------------------------------
451 --@function [parent=#modstore] getshortmodinfo
452 function modstore.getshortmodinfo(ypos,listentry,details)
455 retval = retval .. "box[0," .. ypos .. ";11.4,1.75;#FFFFFF]"
458 retval = retval .. modstore.getscreenshot(ypos,listentry)
461 retval = retval .."label[2.75," .. ypos .. ";" ..
462 core.formspec_escape(details.title) .. " (" .. details.author .. ")]"
465 local descriptiony = ypos + 0.5
466 retval = retval .. "textarea[3," .. descriptiony .. ";6.5,1.55;;" ..
467 core.formspec_escape(details.description) .. ";]"
471 retval = retval .."label[7," .. ratingy .. ";" ..
472 fgettext("Rating") .. ":]"
473 retval = retval .. "label[8.7," .. ratingy .. ";" .. details.rating .."]"
475 --versions (IMPORTANT has to be defined AFTER rating)
476 if details.versions ~= nil and
477 #details.versions > 1 then
478 local versiony = ypos + 0.05
479 retval = retval .. "dropdown[9.1," .. versiony .. ";2.48,0.25;dd_version" .. details.id .. ";"
481 for i=1,#details.versions , 1 do
482 if versions ~= "" then
483 versions = versions .. ","
486 versions = versions .. details.versions[i].date:sub(1,10)
488 retval = retval .. versions .. ";1]"
491 if details.basename then
493 local buttony = ypos + 1.2
494 retval = retval .."button[9.1," .. buttony .. ";2.5,0.5;btn_install_mod_" .. details.id .. ";"
496 if modmgr.mod_exists(details.basename) then
497 retval = retval .. fgettext("re-Install") .."]"
499 retval = retval .. fgettext("Install") .."]"
506 --------------------------------------------------------------------------------
507 --@function [parent=#modstore] getmodlist
508 function modstore.getmodlist(list,yoffset)
509 modstore.current_list = list
511 if yoffset == nil then
515 local sb_y_start = 0.2 + yoffset
516 local sb_y_end = (modstore.modsperpage * 1.75) + ((modstore.modsperpage-1) * 0.15)
517 local close_button = "button[4," .. (sb_y_end + 0.3 + yoffset) ..
518 ";4,0.5;btn_modstore_close;" .. fgettext("Close store") .. "]"
520 if #list.data == 0 then
525 scrollbar = scrollbar .. "label[0.1,".. (sb_y_end + 0.25 + yoffset) ..";"
526 .. fgettext("Page $1 of $2", list.page+1, list.pagecount) .. "]"
527 scrollbar = scrollbar .. "box[11.6," .. sb_y_start .. ";0.28," .. sb_y_end .. ";#000000]"
528 local scrollbarpos = (sb_y_start + 0.5) +
529 ((sb_y_end -1.6)/(list.pagecount-1)) * list.page
530 scrollbar = scrollbar .. "box[11.6," ..scrollbarpos .. ";0.28,0.5;#32CD32]"
531 scrollbar = scrollbar .. "button[11.6," .. (sb_y_start)
532 .. ";0.5,0.5;btn_modstore_page_up;^]"
533 scrollbar = scrollbar .. "button[11.6," .. (sb_y_start + sb_y_end - 0.5)
534 .. ";0.5,0.5;btn_modstore_page_down;v]"
538 local endmod = (list.page * modstore.modsperpage) + modstore.modsperpage
540 if (endmod > #list.data) then
544 for i=(list.page * modstore.modsperpage) +1, endmod, 1 do
546 local details = list.data[i].details
548 if details == nil then
550 details.title = list.data[i].title
553 details.description = ""
556 if details ~= nil then
557 local screenshot_ypos =
558 yoffset +(i-1 - (list.page * modstore.modsperpage))*1.9 +0.2
560 retval = retval .. modstore.getshortmodinfo(screenshot_ypos,
566 return retval .. scrollbar .. close_button
569 --------------------------------------------------------------------------------
570 --@function [parent=#modstore] getsearchpage
571 function modstore.getsearchpage(tabview, name, tabdata)
575 if modstore.last_search ~= nil then
576 search = modstore.last_search
580 "button[9.5,0.2;2.5,0.5;btn_modstore_search;".. fgettext("Search") .. "]" ..
581 "field[0.5,0.5;9,0.5;te_modstore_search;;" .. search .. "]"
585 modstore.currentlist,
591 --------------------------------------------------------------------------------
592 --@function [parent=#modstore] unsorted_tab
593 function modstore.unsorted_tab()
594 return modstore.getmodlist(modstore.modlist_unsorted)
597 --------------------------------------------------------------------------------
598 --@function [parent=#modstore] activate_search_tab
599 function modstore.activate_search_tab(type, old_tab, new_tab)
601 if old_tab == new_tab then
604 filterlist.set_filtercriteria(modstore.searchlist,modstore.last_search)
605 filterlist.refresh(modstore.searchlist)
606 modstore.modsperpage = modstore.mods_on_search_page
607 modstore.currentlist = {
610 math.ceil(filterlist.size(modstore.searchlist) / modstore.modsperpage),
611 data = filterlist.get_list(modstore.searchlist),