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-------------------------------------------------------------------------------- 19 20--modstore implementation 21modstore = {} 22 23-------------------------------------------------------------------------------- 24-- @function [parent=#modstore] init 25function modstore.init() 26 modstore.tabnames = {} 27 28 table.insert(modstore.tabnames,"dialog_modstore_unsorted") 29 table.insert(modstore.tabnames,"dialog_modstore_search") 30 31 modstore.modsperpage = 5 32 33 modstore.basetexturedir = core.get_texturepath() .. DIR_DELIM .. "base" .. 34 DIR_DELIM .. "pack" .. DIR_DELIM 35 36 modstore.lastmodtitle = "" 37 modstore.last_search = "" 38 39 modstore.searchlist = filterlist.create( 40 function() 41 if modstore.modlist_unsorted ~= nil and 42 modstore.modlist_unsorted.data ~= nil then 43 return modstore.modlist_unsorted.data 44 end 45 return {} 46 end, 47 function(element,modid) 48 if element.id == modid then 49 return true 50 end 51 return false 52 end, --compare fct 53 nil, --uid match fct 54 function(element,substring) 55 if substring == nil or 56 substring == "" then 57 return false 58 end 59 substring = substring:upper() 60 61 if element.title ~= nil and 62 element.title:upper():find(substring) ~= nil then 63 return true 64 end 65 66 if element.details ~= nil and 67 element.details.author ~= nil and 68 element.details.author:upper():find(substring) ~= nil then 69 return true 70 end 71 72 if element.details ~= nil and 73 element.details.description ~= nil and 74 element.details.description:upper():find(substring) ~= nil then 75 return true 76 end 77 return false 78 end --filter fct 79 ) 80 81 modstore.current_list = nil 82end 83 84-------------------------------------------------------------------------------- 85-- @function [parent=#modstore] nametoindex 86function modstore.nametoindex(name) 87 88 for i=1,#modstore.tabnames,1 do 89 if modstore.tabnames[i] == name then 90 return i 91 end 92 end 93 94 return 1 95end 96 97-------------------------------------------------------------------------------- 98-- @function [parent=#modstore] getsuccessfuldialog 99function modstore.getsuccessfuldialog() 100 local retval = "" 101 retval = retval .. "size[6,2,true]" 102 if modstore.lastmodentry ~= nil then 103 retval = retval .. "label[0,0.25;" .. fgettext("Successfully installed:") .. "]" 104 retval = retval .. "label[3,0.25;" .. modstore.lastmodentry.moddetails.title .. "]" 105 106 107 retval = retval .. "label[0,0.75;" .. fgettext("Shortname:") .. "]" 108 retval = retval .. "label[3,0.75;" .. core.formspec_escape(modstore.lastmodentry.moddetails.basename) .. "]" 109 110 end 111 retval = retval .. "button[2.5,1.5;1,0.5;btn_confirm_mod_successfull;" .. fgettext("ok") .. "]" 112 113 114 return retval 115end 116 117-------------------------------------------------------------------------------- 118-- @function [parent=#modstore] gettab 119function modstore.gettab(tabname) 120 local retval = "" 121 122 local is_modstore_tab = false 123 124 if tabname == "dialog_modstore_unsorted" then 125 modstore.modsperpage = 5 126 retval = modstore.getmodlist(modstore.modlist_unsorted) 127 is_modstore_tab = true 128 end 129 130 if tabname == "dialog_modstore_search" then 131 retval = modstore.getsearchpage() 132 is_modstore_tab = true 133 end 134 135 if is_modstore_tab then 136 return modstore.tabheader(tabname) .. retval 137 end 138 139 if tabname == "modstore_mod_installed" then 140 return modstore.getsuccessfuldialog() 141 end 142 143 if tabname == "modstore_downloading" then 144 return "size[6,2]label[0.25,0.75;" .. fgettext("Downloading") .. 145 " " .. modstore.lastmodtitle .. " " .. 146 fgettext("please wait...") .. "]" 147 end 148 149 return "" 150end 151 152-------------------------------------------------------------------------------- 153-- @function [parent=#modstore] tabheader 154function modstore.tabheader(tabname) 155 local retval = "size[12,10.25,true]" 156 retval = retval .. "tabheader[-0.3,-0.99;modstore_tab;" .. 157 "Unsorted,Search;" .. 158 modstore.nametoindex(tabname) .. ";true;false]" .. 159 "button[4,9.9;4,0.5;btn_modstore_close;" .. 160 fgettext("Close modstore") .. "]" 161 162 return retval 163end 164 165-------------------------------------------------------------------------------- 166-- @function [parent=#modstore] handle_buttons 167function modstore.handle_buttons(current_tab,fields) 168 169 if fields["modstore_tab"] then 170 local index = tonumber(fields["modstore_tab"]) 171 172 if index > 0 and 173 index <= #modstore.tabnames then 174 if modstore.tabnames[index] == "dialog_modstore_search" then 175 filterlist.set_filtercriteria(modstore.searchlist,modstore.last_search) 176 filterlist.refresh(modstore.searchlist) 177 modstore.modsperpage = 4 178 modstore.currentlist = { 179 page = 0, 180 pagecount = 181 math.ceil(filterlist.size(modstore.searchlist) / modstore.modsperpage), 182 data = filterlist.get_list(modstore.searchlist), 183 } 184 end 185 186 return { 187 current_tab = modstore.tabnames[index], 188 is_dialog = true, 189 show_buttons = false 190 } 191 end 192 193 end 194 195 if fields["btn_modstore_page_up"] then 196 if modstore.current_list ~= nil and modstore.current_list.page > 0 then 197 modstore.current_list.page = modstore.current_list.page - 1 198 end 199 end 200 201 if fields["btn_modstore_page_down"] then 202 if modstore.current_list ~= nil and 203 modstore.current_list.page <modstore.current_list.pagecount-1 then 204 modstore.current_list.page = modstore.current_list.page +1 205 end 206 end 207 208 if fields["btn_hidden_close_download"] ~= nil then 209 if fields["btn_hidden_close_download"].successfull then 210 modstore.lastmodentry = fields["btn_hidden_close_download"] 211 return { 212 current_tab = "modstore_mod_installed", 213 is_dialog = true, 214 show_buttons = false 215 } 216 else 217 modstore.lastmodtitle = "" 218 return { 219 current_tab = modstore.tabnames[1], 220 is_dialog = true, 221 show_buttons = false 222 } 223 end 224 end 225 226 if fields["btn_confirm_mod_successfull"] then 227 modstore.lastmodentry = nil 228 modstore.lastmodtitle = "" 229 return { 230 current_tab = modstore.tabnames[1], 231 is_dialog = true, 232 show_buttons = false 233 } 234 end 235 236 if fields["btn_modstore_search"] or 237 (fields["key_enter"] and fields["te_modstore_search"] ~= nil) then 238 modstore.last_search = fields["te_modstore_search"] 239 filterlist.set_filtercriteria(modstore.searchlist,fields["te_modstore_search"]) 240 filterlist.refresh(modstore.searchlist) 241 modstore.currentlist = { 242 page = 0, 243 pagecount = math.ceil(filterlist.size(modstore.searchlist) / modstore.modsperpage), 244 data = filterlist.get_list(modstore.searchlist), 245 } 246 end 247 248 249 if fields["btn_modstore_close"] then 250 return { 251 is_dialog = false, 252 show_buttons = true, 253 current_tab = core.setting_get("main_menu_tab") 254 } 255 end 256 257 for key,value in pairs(fields) do 258 local foundat = key:find("btn_install_mod_") 259 if ( foundat == 1) then 260 local modid = tonumber(key:sub(17)) 261 for i=1,#modstore.modlist_unsorted.data,1 do 262 if modstore.modlist_unsorted.data[i].id == modid then 263 local moddetails = modstore.modlist_unsorted.data[i].details 264 265 if modstore.lastmodtitle ~= "" then 266 modstore.lastmodtitle = modstore.lastmodtitle .. ", " 267 end 268 269 modstore.lastmodtitle = modstore.lastmodtitle .. moddetails.title 270 271 core.handle_async( 272 function(param) 273 274 local fullurl = core.setting_get("modstore_download_url") .. 275 param.moddetails.download_url 276 277 if param.version ~= nil then 278 local found = false 279 for i=1,#param.moddetails.versions, 1 do 280 if param.moddetails.versions[i].date:sub(1,10) == param.version then 281 fullurl = core.setting_get("modstore_download_url") .. 282 param.moddetails.versions[i].download_url 283 found = true 284 end 285 end 286 287 if not found then 288 return { 289 moddetails = param.moddetails, 290 successfull = false 291 } 292 end 293 end 294 295 if core.download_file(fullurl,param.filename) then 296 return { 297 texturename = param.texturename, 298 moddetails = param.moddetails, 299 filename = param.filename, 300 successfull = true 301 } 302 else 303 return { 304 moddetails = param.moddetails, 305 successfull = false 306 } 307 end 308 end, 309 { 310 moddetails = moddetails, 311 version = fields["dd_version" .. modid], 312 filename = os.tempfolder() .. "_MODNAME_" .. moddetails.basename .. ".zip", 313 texturename = modstore.modlist_unsorted.data[i].texturename 314 }, 315 function(result) 316 if result.successfull then 317 modmgr.installmod(result.filename,result.moddetails.basename) 318 os.remove(result.filename) 319 else 320 gamedata.errormessage = "Failed to download " .. result.moddetails.title 321 end 322 323 if gamedata.errormessage == nil then 324 core.button_handler({btn_hidden_close_download=result}) 325 else 326 core.button_handler({btn_hidden_close_download={successfull=false}}) 327 end 328 end 329 ) 330 331 return { 332 current_tab = "modstore_downloading", 333 is_dialog = true, 334 show_buttons = false, 335 ignore_menu_quit = true 336 } 337 end 338 end 339 break 340 end 341 end 342end 343 344-------------------------------------------------------------------------------- 345-- @function [parent=#modstore] update_modlist 346function modstore.update_modlist() 347 modstore.modlist_unsorted = {} 348 modstore.modlist_unsorted.data = {} 349 modstore.modlist_unsorted.pagecount = 1 350 modstore.modlist_unsorted.page = 0 351 352 core.handle_async( 353 function(param) 354 return core.get_modstore_list() 355 end, 356 nil, 357 function(result) 358 if result ~= nil then 359 modstore.modlist_unsorted = {} 360 modstore.modlist_unsorted.data = result 361 362 if modstore.modlist_unsorted.data ~= nil then 363 modstore.modlist_unsorted.pagecount = 364 math.ceil((#modstore.modlist_unsorted.data / modstore.modsperpage)) 365 else 366 modstore.modlist_unsorted.data = {} 367 modstore.modlist_unsorted.pagecount = 1 368 end 369 modstore.modlist_unsorted.page = 0 370 modstore.fetchdetails() 371 core.event_handler("Refresh") 372 end 373 end 374 ) 375end 376 377-------------------------------------------------------------------------------- 378-- @function [parent=#modstore] fetchdetails 379function modstore.fetchdetails() 380 381 for i=1,#modstore.modlist_unsorted.data,1 do 382 core.handle_async( 383 function(param) 384 param.details = core.get_modstore_details(tostring(param.modid)) 385 return param 386 end, 387 { 388 modid=modstore.modlist_unsorted.data[i].id, 389 listindex=i 390 }, 391 function(result) 392 if result ~= nil and 393 modstore.modlist_unsorted ~= nil 394 and modstore.modlist_unsorted.data ~= nil and 395 modstore.modlist_unsorted.data[result.listindex] ~= nil and 396 modstore.modlist_unsorted.data[result.listindex].id ~= nil then 397 398 modstore.modlist_unsorted.data[result.listindex].details = result.details 399 core.event_handler("Refresh") 400 end 401 end 402 ) 403 end 404end 405 406-------------------------------------------------------------------------------- 407-- @function [parent=#modstore] getscreenshot 408function modstore.getscreenshot(ypos,listentry) 409 410 if listentry.details ~= nil and 411 (listentry.details.screenshot_url == nil or 412 listentry.details.screenshot_url == "") then 413 414 if listentry.texturename == nil then 415 listentry.texturename = modstore.basetexturedir .. "no_screenshot.png" 416 end 417 418 return "image[0,".. ypos .. ";3,2;" .. 419 core.formspec_escape(listentry.texturename) .. "]" 420 end 421 422 if listentry.details ~= nil and 423 listentry.texturename == nil then 424 --make sure we don't download multiple times 425 listentry.texturename = "in progress" 426 427 --prepare url and filename 428 local fullurl = core.setting_get("modstore_download_url") .. 429 listentry.details.screenshot_url 430 local filename = os.tempfolder() .. "_MID_" .. listentry.id 431 432 --trigger download 433 core.handle_async( 434 --first param is downloadfct 435 function(param) 436 param.successfull = core.download_file(param.fullurl,param.filename) 437 return param 438 end, 439 --second parameter is data passed to async job 440 { 441 fullurl = fullurl, 442 filename = filename, 443 modid = listentry.id 444 }, 445 --integrate result to raw list 446 function(result) 447 if result.successfull then 448 local found = false 449 for i=1,#modstore.modlist_unsorted.data,1 do 450 if modstore.modlist_unsorted.data[i].id == result.modid then 451 found = true 452 modstore.modlist_unsorted.data[i].texturename = result.filename 453 break 454 end 455 end 456 if found then 457 core.event_handler("Refresh") 458 else 459 core.log("error","got screenshot but didn't find matching mod: " .. result.modid) 460 end 461 end 462 end 463 ) 464 end 465 466 if listentry.texturename ~= nil and 467 listentry.texturename ~= "in progress" then 468 return "image[0,".. ypos .. ";3,2;" .. 469 core.formspec_escape(listentry.texturename) .. "]" 470 end 471 472 return "" 473end 474 475-------------------------------------------------------------------------------- 476--@function [parent=#modstore] getshortmodinfo 477function modstore.getshortmodinfo(ypos,listentry,details) 478 local retval = "" 479 480 retval = retval .. "box[0," .. ypos .. ";11.4,1.75;#FFFFFF]" 481 482 --screenshot 483 retval = retval .. modstore.getscreenshot(ypos,listentry) 484 485 --title + author 486 retval = retval .."label[2.75," .. ypos .. ";" .. 487 core.formspec_escape(details.title) .. " (" .. details.author .. ")]" 488 489 --description 490 local descriptiony = ypos + 0.5 491 retval = retval .. "textarea[3," .. descriptiony .. ";6.5,1.55;;" .. 492 core.formspec_escape(details.description) .. ";]" 493 494 --rating 495 local ratingy = ypos 496 retval = retval .."label[7," .. ratingy .. ";" .. 497 fgettext("Rating") .. ":]" 498 retval = retval .. "label[8.7," .. ratingy .. ";" .. details.rating .."]" 499 500 --versions (IMPORTANT has to be defined AFTER rating) 501 if details.versions ~= nil and 502 #details.versions > 1 then 503 local versiony = ypos + 0.05 504 retval = retval .. "dropdown[9.1," .. versiony .. ";2.48,0.25;dd_version" .. details.id .. ";" 505 local versions = "" 506 for i=1,#details.versions , 1 do 507 if versions ~= "" then 508 versions = versions .. "," 509 end 510 511 versions = versions .. details.versions[i].date:sub(1,10) 512 end 513 retval = retval .. versions .. ";1]" 514 end 515 516 if details.basename then 517 --install button 518 local buttony = ypos + 1.2 519 retval = retval .."button[9.1," .. buttony .. ";2.5,0.5;btn_install_mod_" .. details.id .. ";" 520 521 if modmgr.mod_exists(details.basename) then 522 retval = retval .. fgettext("re-Install") .."]" 523 else 524 retval = retval .. fgettext("Install") .."]" 525 end 526 end 527 528 return retval 529end 530 531-------------------------------------------------------------------------------- 532--@function [parent=#modstore] getmodlist 533function modstore.getmodlist(list,yoffset) 534 535 modstore.current_list = list 536 537 if #list.data == 0 then 538 return "" 539 end 540 541 if yoffset == nil then 542 yoffset = 0 543 end 544 545 local scrollbar = "" 546 scrollbar = scrollbar .. "label[0.1,9.5;" 547 .. fgettext("Page $1 of $2", list.page+1, list.pagecount) .. "]" 548 scrollbar = scrollbar .. "box[11.6," .. (yoffset + 0.35) .. ";0.28," 549 .. (8.6 - yoffset) .. ";#000000]" 550 local scrollbarpos = (yoffset + 0.75) + 551 ((7.7 -yoffset)/(list.pagecount-1)) * list.page 552 scrollbar = scrollbar .. "box[11.6," ..scrollbarpos .. ";0.28,0.5;#32CD32]" 553 scrollbar = scrollbar .. "button[11.6," .. (yoffset + (0.3)) 554 .. ";0.5,0.5;btn_modstore_page_up;^]" 555 scrollbar = scrollbar .. "button[11.6," .. 9.0 556 .. ";0.5,0.5;btn_modstore_page_down;v]" 557 558 local retval = "" 559 560 local endmod = (list.page * modstore.modsperpage) + modstore.modsperpage 561 562 if (endmod > #list.data) then 563 endmod = #list.data 564 end 565 566 for i=(list.page * modstore.modsperpage) +1, endmod, 1 do 567 --getmoddetails 568 local details = list.data[i].details 569 570 if details == nil then 571 details = {} 572 details.title = list.data[i].title 573 details.author = "" 574 details.rating = -1 575 details.description = "" 576 end 577 578 if details ~= nil then 579 local screenshot_ypos = 580 yoffset +(i-1 - (list.page * modstore.modsperpage))*1.9 +0.2 581 582 retval = retval .. modstore.getshortmodinfo(screenshot_ypos, 583 list.data[i], 584 details) 585 end 586 end 587 588 return retval .. scrollbar 589end 590 591-------------------------------------------------------------------------------- 592--@function [parent=#modstore] getsearchpage 593function modstore.getsearchpage() 594 local retval = "" 595 local search = "" 596 597 if modstore.last_search ~= nil then 598 search = modstore.last_search 599 end 600 601 retval = retval .. 602 "button[9.5,0.2;2.5,0.5;btn_modstore_search;".. fgettext("Search") .. "]" .. 603 "field[0.5,0.5;9,0.5;te_modstore_search;;" .. search .. "]" 604 605 606 --show 4 mods only 607 modstore.modsperpage = 4 608 retval = retval .. 609 modstore.getmodlist( 610 modstore.currentlist, 611 1.75) 612 613 return retval; 614end 615 616