]> git.lizzy.rs Git - dragonfireclient.git/blob - builtin/mainmenu.lua
Replace C++ mainmenu by formspec powered one
[dragonfireclient.git] / builtin / mainmenu.lua
1 local scriptpath = engine.get_scriptdir()
2
3 dofile(scriptpath .. DIR_DELIM .. "modmgr.lua")
4 dofile(scriptpath .. DIR_DELIM .. "modstore.lua")
5 dofile(scriptpath .. DIR_DELIM .. "gamemgr.lua")
6
7 local menu = {}
8 local tabbuilder = {}
9 local menubar = {}
10
11 --------------------------------------------------------------------------------
12 function render_favourite(spec)
13         local text = ""
14         
15         if spec.name ~= nil then
16                 text = text .. spec.name:trim()
17                 
18                 if spec.description ~= nil then
19                         --TODO make sure there's no invalid chat in spec.description
20                         text = text .. " (" .. fs_escape_string(spec.description) .. ")"
21                 end
22         else
23                 if spec.address ~= nil then
24                         text = text .. spec.address:trim()
25                 end
26         end
27         
28         local details = ""
29         if spec.password == true then
30                 details = " *"
31         else
32                 details = "  "
33         end
34         
35         if spec.creative then
36                 details = details .. "C"
37         else
38                 details = details .. " "
39         end
40         
41         if spec.damage then
42                 details = details .. "D"
43         else
44                 details = details .. " "
45         end
46         
47         if spec.pvp then
48                 details = details .. "P"
49         else
50                 details = details .. " "
51         end
52         
53         text = text .. ":" .. spec.port:trim()
54         
55         return text
56 end
57
58 --------------------------------------------------------------------------------
59 os.tempfolder = function()
60         local filetocheck = os.tmpname()
61         os.remove(filetocheck)
62         
63         local randname = "MTTempModFolder_" .. math.random(0,10000)
64         if DIR_DELIM == "\\" then
65                 local tempfolder = os.getenv("TEMP")
66                 return tempfolder .. filetocheck
67         else
68                 local backstring = filetocheck:reverse()
69                 return filetocheck:sub(0,filetocheck:len()-backstring:find(DIR_DELIM)+1) ..randname
70         end
71
72 end
73
74 --------------------------------------------------------------------------------
75 function cleanup_path(temppath)
76         
77         local parts = temppath:split("-")
78         temppath = ""   
79         for i=1,#parts,1 do
80                 if temppath ~= "" then
81                         temppath = temppath .. "_"
82                 end
83                 temppath = temppath .. parts[i]
84         end
85         
86         parts = temppath:split(".")
87         temppath = ""   
88         for i=1,#parts,1 do
89                 if temppath ~= "" then
90                         temppath = temppath .. "_"
91                 end
92                 temppath = temppath .. parts[i]
93         end
94         
95         parts = temppath:split("'")
96         temppath = ""   
97         for i=1,#parts,1 do
98                 if temppath ~= "" then
99                         temppath = temppath .. ""
100                 end
101                 temppath = temppath .. parts[i]
102         end
103         
104         parts = temppath:split(" ")
105         temppath = ""   
106         for i=1,#parts,1 do
107                 if temppath ~= "" then
108                         temppath = temppath
109                 end
110                 temppath = temppath .. parts[i]
111         end
112         
113         return temppath
114 end
115
116 --------------------------------------------------------------------------------
117 function menu.update_gametype()
118         if (menu.game_last_check == nil or
119                 menu.game_last_check ~= menu.last_game) and
120                 tabbuilder.current_tab == "singleplayer" then
121                 
122                 local gamedetails = menu.lastgame()
123                 engine.set_topleft_text(gamedetails.name)
124                 
125                 --background
126                 local path_background_texture = gamedetails.path .. DIR_DELIM .."menu" .. 
127                                                                                                  DIR_DELIM .. "background.png"
128                 if engine.set_background("background",path_background_texture) then
129                         engine.set_clouds(false)
130                 else
131                         engine.set_clouds(true)
132                 end
133                 
134                 --overlay
135                 local path_overlay_texture = gamedetails.path .. DIR_DELIM .."menu" .. 
136                                                                                                  DIR_DELIM .. "overlay.png"
137                 engine.set_background("overlay",path_overlay_texture)
138                 
139                 --header
140                 local path_overlay_texture = gamedetails.path .. DIR_DELIM .."menu" .. 
141                                                                                                  DIR_DELIM .. "header.png"
142                 engine.set_background("header",path_overlay_texture)
143                 
144                 --footer
145                 local path_overlay_texture = gamedetails.path .. DIR_DELIM .."menu" .. 
146                                                                                                  DIR_DELIM .. "footer.png"
147                 engine.set_background("footer",path_overlay_texture)
148                 
149                 menu.game_last_check = menu.last_game
150         else
151                 if menu.game_last_check ~= menu.last_game then
152                         menu.game_last_check = menu.last_game
153                         menu.reset_gametype()
154                 end
155         end
156 end
157
158 --------------------------------------------------------------------------------
159 function menu.reset_gametype()
160         menu.game_last_check = nil
161         engine.set_clouds(true)
162         engine.set_background("background","")
163         engine.set_background("overlay",menu.basetexturedir .. "menu_overlay.png")
164         engine.set_background("header",menu.basetexturedir .. "menu_header.png")
165         engine.set_background("footer",menu.basetexturedir .. "menu_footer.png")
166         engine.set_topleft_text("")
167 end
168
169 --------------------------------------------------------------------------------
170 function get_last_folder(text,count)
171         local parts = text:split(DIR_DELIM)
172         
173         if count == nil then
174                 return parts[#parts]
175         end
176         
177         local retval = ""
178         for i=1,count,1 do
179                 retval = retval .. parts[#parts - (count-i)] .. DIR_DELIM
180         end
181         
182         return retval
183 end
184
185 --------------------------------------------------------------------------------
186 function init_globals()
187         --init gamedata
188         gamedata.worldindex = 0
189 end
190
191 --------------------------------------------------------------------------------
192 function identify_filetype(name)
193
194         if name:sub(-3):lower() == "zip" then
195                 return {
196                                 name = name,
197                                 type = "zip"
198                                 }
199         end
200         
201         if name:sub(-6):lower() == "tar.gz" or
202                 name:sub(-3):lower() == "tgz"then
203                 return {
204                                 name = name,
205                                 type = "tgz"
206                                 }
207         end
208         
209         if name:sub(-6):lower() == "tar.bz2" then
210                 return {
211                                 name = name,
212                                 type = "tbz"
213                                 }
214         end
215         
216         if name:sub(-2):lower() == "7z" then
217                 return {
218                                 name = name,
219                                 type = "7z"
220                                 }
221         end
222
223         return {
224                 name = name,
225                 type = "ukn"
226         }
227 end
228
229 --------------------------------------------------------------------------------
230 function update_menu()
231
232         local formspec = "size[12,5.2]"
233         
234         -- handle errors
235         if gamedata.errormessage ~= nil then
236                 formspec = formspec ..
237                         "field[1,2;10,2;;ERROR: " ..
238                         gamedata.errormessage .. 
239                         ";]"..
240                         "button[4.5,4.2;3,0.5;btn_error_confirm;Ok]"
241         else
242                 formspec = formspec .. tabbuilder.gettab()
243         end
244
245         engine.update_formspec(formspec)
246 end
247
248 --------------------------------------------------------------------------------
249 function menu.filtered_game_list()
250         local retval = ""
251
252         local current_game = menu.lastgame()
253         
254         for i=1,#menu.worldlist,1 do
255                 if menu.worldlist[i].gameid == current_game.id then
256                         if retval ~= "" then
257                                 retval = retval ..","
258                         end
259                         
260                         retval = retval .. menu.worldlist[i].name .. 
261                                                 " [[" .. menu.worldlist[i].gameid .. "]]"
262                 end
263         end
264         
265         return retval
266 end
267
268 --------------------------------------------------------------------------------
269 function menu.filtered_game_list_raw()
270         local retval =  {}
271
272         local current_game = menu.lastgame()
273         
274         for i=1,#menu.worldlist,1 do
275                 if menu.worldlist[i].gameid == current_game.id then
276                         table.insert(retval,menu.worldlist[i])
277                 end
278         end
279         
280         return retval
281 end
282
283 --------------------------------------------------------------------------------
284 function menu.filtered_index_to_plain(filtered_index)
285
286         local current_game = menu.lastgame()
287         
288         local temp_idx = 0
289         
290         for i=1,#menu.worldlist,1 do
291                 if menu.worldlist[i].gameid == current_game.id then
292                         temp_idx = temp_idx +1
293                 end
294                 
295                 if temp_idx == filtered_index then
296                         return i
297                 end
298         end
299         return -1
300 end
301
302 --------------------------------------------------------------------------------
303 function menu.init()
304         --init menu data
305         gamemgr.update_gamelist()
306
307         menu.worldlist = engine.get_worlds()
308         
309         menu.last_world = tonumber(engine.setting_get("main_menu_last_world_idx"))
310         menu.last_game  = tonumber(engine.setting_get("main_menu_last_game_idx"))
311         
312         if type(menu.last_world) ~= "number" then
313                 menu.last_world = 1
314         end
315         
316         if type(menu.last_game) ~= "number" then
317                 menu.last_game = 1
318         end
319
320         if engine.setting_getbool("public_serverlist") then
321                 menu.favorites = engine.get_favorites("online")
322         else
323                 menu.favorites = engine.get_favorites("local")
324         end
325         
326         
327         menu.basetexturedir = engine.get_gamepath() .. DIR_DELIM .. ".." ..
328                                                 DIR_DELIM .. "textures" .. DIR_DELIM .. "base" .. 
329                                                 DIR_DELIM .. "pack" .. DIR_DELIM
330 end
331
332 --------------------------------------------------------------------------------
333 function menu.lastgame()
334         if menu.last_game > 0 and menu.last_game <= #gamemgr.games then
335                 return gamemgr.games[menu.last_game]
336         end
337         
338         if #gamemgr.games >= 1 then
339                 menu.last_game = 1
340                 return gamemgr.games[menu.last_game]
341         end
342         
343         --error case!!
344         return nil
345 end
346
347 --------------------------------------------------------------------------------
348 function menu.lastworld()
349         if menu.last_world ~= nil and 
350                 menu.last_world > 0 and 
351                 menu.last_world <= #menu.worldlist then
352                 return menu.worldlist[menu.last_world]
353         end
354         
355         if #menu.worldlist >= 1 then
356                 menu.last_world = 1
357                 return menu.worldlist[menu.last_world]
358         end
359         
360         --error case!!
361         return nil
362 end
363
364 --------------------------------------------------------------------------------
365 function menu.update_last_game(world_idx)
366         if gamedata.selected_world <= #menu.worldlist then
367                 local world = menu.worldlist[gamedata.selected_world]
368                 
369                 for i=1,#gamemgr.games,1 do             
370                         if gamemgr.games[i].id == world.gameid then
371                                 menu.last_game = i
372                                 engine.setting_set("main_menu_last_game_idx",menu.last_game)
373                                 break
374                         end
375                 end
376         end
377 end
378
379 --------------------------------------------------------------------------------
380 function menubar.handle_buttons(fields)
381         for i=1,#menubar.buttons,1 do
382                 if fields[menubar.buttons[i].btn_name] ~= nil then
383                         menu.last_game = menubar.buttons[i].index
384                         engine.setting_set("main_menu_last_game_idx",menu.last_game)
385                         menu.update_gametype()
386                 end
387         end
388 end
389
390 --------------------------------------------------------------------------------
391 function menubar.refresh()
392         menubar.formspec = "box[-2,7.625;15.75,1.75;BLK]"
393         menubar.buttons = {}
394
395         local button_base = -1.8
396         
397         local maxbuttons = #gamemgr.games
398         
399         if maxbuttons > 12 then
400                 maxbuttons = 12
401         end
402         
403         for i=1,maxbuttons,1 do
404
405                 local btn_name = "menubar_btn_" .. gamemgr.games[i].id
406                 local buttonpos = button_base + (i-1) * 1.3
407                 if gamemgr.games[i].menuicon_path ~= nil and
408                         gamemgr.games[i].menuicon_path ~= "" then
409
410                         menubar.formspec = menubar.formspec ..
411                                 "image_button[" .. buttonpos ..  ",7.9;1.3,1.3;"  ..
412                                 gamemgr.games[i].menuicon_path .. ";" .. btn_name .. ";;true;false]"
413                 else
414                 
415                         local part1 = gamemgr.games[i].id:sub(1,5)
416                         local part2 = gamemgr.games[i].id:sub(6,10)
417                         local part3 = gamemgr.games[i].id:sub(11)
418                         
419                         local text = part1 .. "\n" .. part2
420                         if part3 ~= nil and
421                                 part3 ~= "" then
422                                 text = text .. "\n" .. part3
423                         end
424                         menubar.formspec = menubar.formspec ..
425                                 "image_button[" .. buttonpos ..  ",7.9;1.3,1.3;;" ..btn_name ..
426                                 ";" .. text .. ";true;true]"
427                 end
428                 
429                 local toadd = {
430                         btn_name = btn_name,
431                         index = i,
432                 }
433                 
434                 table.insert(menubar.buttons,toadd)
435         end
436 end
437
438 --------------------------------------------------------------------------------
439 function tabbuilder.dialog_create_world()
440         local retval = 
441                 "label[2,0;World name]"..
442                 "label[2,1;Mapgen]"..
443                 "field[4.5,0.4;6,0.5;te_world_name;;]" ..
444                 "label[2,2;Game]"..
445                 "button[5,4.5;2.6,0.5;world_create_confirm;Create]" ..
446                 "button[7.5,4.5;2.8,0.5;world_create_cancel;Cancel]" ..
447                 "dropdown[4.2,1;6.3;dd_mapgen;v6,v7,indev,singlenode,math;1]" .. --TODO read from minetest
448                 "textlist[4.2,1.9;5.8,2.3;games;" ..
449                 gamemgr.gamelist() ..
450                 ";" .. menu.last_game .. ";true]"
451
452         return retval
453 end
454
455 --------------------------------------------------------------------------------
456 function tabbuilder.dialog_delete_world()
457         return  "label[2,2;Delete World \"" .. menu.lastworld().name .. "\"?]"..
458                         "button[3.5,4.2;2.6,0.5;world_delete_confirm;Yes]" ..
459                         "button[6,4.2;2.8,0.5;world_delete_cancel;No]"
460 end
461
462 --------------------------------------------------------------------------------
463 function tabbuilder.gettab()
464         local retval = ""
465         
466         if tabbuilder.show_buttons then
467                 retval = retval .. tabbuilder.tab_header()
468         end
469
470         if tabbuilder.current_tab == "singleplayer" then
471                 retval = retval .. tabbuilder.tab_singleplayer()
472         end
473         
474         if tabbuilder.current_tab == "multiplayer" then
475                 retval = retval .. tabbuilder.tab_multiplayer()
476         end
477
478         if tabbuilder.current_tab == "server" then
479                 retval = retval .. tabbuilder.tab_server()
480         end
481         
482         if tabbuilder.current_tab == "settings" then
483                 retval = retval .. tabbuilder.tab_settings()
484         end
485         
486         if tabbuilder.current_tab == "credits" then
487                 retval = retval .. tabbuilder.tab_credits()
488         end
489         
490         if tabbuilder.current_tab == "dialog_create_world" then
491                 retval = retval .. tabbuilder.dialog_create_world()
492         end
493         
494         if tabbuilder.current_tab == "dialog_delete_world" then
495                 retval = retval .. tabbuilder.dialog_delete_world()
496         end
497         
498         retval = retval .. modmgr.gettab(tabbuilder.current_tab)
499         retval = retval .. gamemgr.gettab(tabbuilder.current_tab)
500         retval = retval .. modstore.gettab(tabbuilder.current_tab)
501
502         return retval
503 end
504
505 --------------------------------------------------------------------------------
506 function tabbuilder.handle_create_world_buttons(fields)
507         
508         if fields["world_create_confirm"] then
509                 
510                 local worldname = fields["te_world_name"]
511                 local gameindex = engine.get_textlist_index("games")
512                 
513                 if gameindex > 0 and
514                         worldname ~= "" then
515                         engine.setting_set("mg_name",fields["dd_mapgen"])
516                         local message = engine.create_world(worldname,gameindex)
517                         
518                         menu.last_game = gameindex
519                         engine.setting_set("main_menu_last_game_idx",gameindex)
520                         
521                         if message ~= nil then
522                                 gamedata.errormessage = message
523                         else
524                                 menu.worldlist = engine.get_worlds()
525                                 
526                                 local worldlist = menu.worldlist
527                                 
528                                 if tabbuilder.current_tab == "singleplayer" then
529                                         worldlist = menu.filtered_game_list_raw()
530                                 end
531                                 
532                                 local index = 0
533                                 
534                                 for i=1,#worldlist,1 do
535                                         if worldlist[i].name == worldname then
536                                                 index = i
537                                                 print("found new world index: " .. index)
538                                                 break
539                                         end
540                                 end
541                                 
542                                 if tabbuilder.current_tab == "singleplayer" then
543                                         engine.setting_set("main_menu_singleplayer_world_idx",index)
544                                 else
545                                         menu.last_world = index
546                                 end
547                         end
548                 else
549                         gamedata.errormessage = "No worldname given or no game selected"
550                 end
551         end
552         
553         if fields["games"] then
554                 tabbuilder.skipformupdate = true
555                 return
556         end
557         
558         tabbuilder.is_dialog = false
559         tabbuilder.show_buttons = true
560         tabbuilder.current_tab = engine.setting_get("main_menu_tab")
561 end
562
563 --------------------------------------------------------------------------------
564 function tabbuilder.handle_delete_world_buttons(fields)
565         
566         if fields["world_delete_confirm"] then
567                 if menu.last_world > 0 and 
568                         menu.last_world < #menu.worldlist then
569                         engine.delete_world(menu.last_world)
570                         menu.worldlist = engine.get_worlds()
571                         menu.last_world = 1
572                 end
573         end
574         
575         tabbuilder.is_dialog = false
576         tabbuilder.show_buttons = true
577         tabbuilder.current_tab = engine.setting_get("main_menu_tab")
578 end
579
580 --------------------------------------------------------------------------------
581 function tabbuilder.handle_multiplayer_buttons(fields)
582         if fields["favourites"] ~= nil then
583                 local event = explode_textlist_event(fields["favourites"])
584                 if event.typ == "DCL" then
585                         gamedata.address = menu.favorites[event.index].name
586                         if gamedata.address == nil then
587                                 gamedata.address = menu.favorites[event.index].address
588                         end
589                         gamedata.port = menu.favorites[event.index].port
590                         gamedata.playername             = fields["te_name"]
591                         gamedata.password               = fields["te_pwd"]
592                         gamedata.selected_world = 0
593                         
594                         if gamedata.address ~= nil and
595                                 gamedata.port ~= nil then
596                                 
597                                 engine.start()
598                         end
599                 end
600                 
601                 if event.typ == "CHG" then
602                         local address = menu.favorites[event.index].name
603                         if address == nil then
604                                 address = menu.favorites[event.index].address
605                         end
606                         local port = menu.favorites[event.index].port
607                         
608                         if address ~= nil and
609                                 port ~= nil then
610                                 engine.setting_set("address",address)
611                                 engine.setting_set("port",port)
612                         end
613                 end
614                 return
615         end
616         
617         if fields["cb_public_serverlist"] ~= nil then
618                 engine.setting_setbool("public_serverlist",
619                         tabbuilder.tobool(fields["cb_public_serverlist"]))
620                         
621                 if engine.setting_getbool("public_serverlist") then
622                         menu.favorites = engine.get_favorites("online")
623                 else
624                         menu.favorites = engine.get_favorites("local")
625                 end
626         end
627
628         if fields["btn_delete_favorite"] ~= nil then
629                 local current_favourite = engine.get_textlist_index("favourites")
630                 engine.delete_favorite(current_favourite)
631                 menu.favorites = engine.get_favorites()
632                 
633                 engine.setting_set("address","")
634                 engine.setting_get("port","")
635                 
636                 return
637         end
638
639         if fields["btn_mp_connect"] ~= nil then
640                 gamedata.playername             = fields["te_name"]
641                 gamedata.password               = fields["te_pwd"]
642                 gamedata.address                = fields["te_address"]
643                 gamedata.port                   = fields["te_port"]
644                 gamedata.selected_world = 0
645
646                 engine.start()
647                 return
648         end
649 end
650
651 --------------------------------------------------------------------------------
652 function tabbuilder.handle_server_buttons(fields)
653
654         local world_doubleclick = false
655
656         if fields["worlds"] ~= nil then
657                 local event = explode_textlist_event(fields["worlds"])
658                 
659                 if event.typ == "DBL" then
660                         world_doubleclick = true
661                 end
662         end
663         
664         if fields["cb_creative_mode"] then
665                 engine.setting_setbool("creative_mode",tabbuilder.tobool(fields["cb_creative_mode"]))
666         end
667         
668         if fields["cb_enable_damage"] then
669                 engine.setting_setbool("enable_damage",tabbuilder.tobool(fields["cb_enable_damage"]))
670         end
671
672         if fields["start_server"] ~= nil or
673                 world_doubleclick then
674                 local selected = engine.get_textlist_index("srv_worlds")
675                 if selected > 0 then
676                         gamedata.playername             = fields["te_playername"]
677                         gamedata.password               = fields["te_pwd"]
678                         gamedata.address                = ""
679                         gamedata.port                   = fields["te_serverport"]
680                         gamedata.selected_world = selected
681                         
682                         engine.setting_set("main_menu_tab",tabbuilder.current_tab)
683                         engine.setting_set("main_menu_last_world_idx",gamedata.selected_world)
684                         
685                         menu.update_last_game(gamedata.selected_world)
686                         engine.start()
687                 end
688         end
689         
690         if fields["world_create"] ~= nil then
691                 tabbuilder.current_tab = "dialog_create_world"
692                 tabbuilder.is_dialog = true
693                 tabbuilder.show_buttons = false
694         end
695         
696         if fields["world_delete"] ~= nil then
697                 local selected = engine.get_textlist_index("srv_worlds")
698                 if selected > 0 then
699                         menu.last_world = engine.get_textlist_index("worlds")
700                         if menu.lastworld() ~= nil and
701                                 menu.lastworld().name ~= nil and
702                                 menu.lastworld().name ~= "" then
703                                 tabbuilder.current_tab = "dialog_delete_world"
704                                 tabbuilder.is_dialog = true
705                                 tabbuilder.show_buttons = false
706                         else
707                                 menu.last_world = 0
708                         end
709                 end
710         end
711         
712         if fields["world_configure"] ~= nil then
713                 selected = engine.get_textlist_index("srv_worlds")
714                 if selected > 0 then
715                         modmgr.world_config_selected_world = selected
716                         if modmgr.init_worldconfig() then
717                                 tabbuilder.current_tab = "dialog_configure_world"
718                                 tabbuilder.is_dialog = true
719                                 tabbuilder.show_buttons = false
720                         end
721                 end
722         end
723 end
724
725 --------------------------------------------------------------------------------
726 function tabbuilder.tobool(text)
727         if text == "true" then
728                 return true
729         else
730                 return false
731         end
732 end
733
734 --------------------------------------------------------------------------------
735 function tabbuilder.handle_settings_buttons(fields)
736         if fields["cb_fancy_trees"] then
737                 engine.setting_setbool("new_style_leaves",tabbuilder.tobool(fields["cb_fancy_trees"]))
738         end
739                 
740         if fields["cb_smooth_lighting"] then
741                 engine.setting_setbool("smooth_lighting",tabbuilder.tobool(fields["cb_smooth_lighting"]))
742         end
743         if fields["cb_3d_clouds"] then
744                 engine.setting_setbool("enable_3d_clouds",tabbuilder.tobool(fields["cb_3d_clouds"]))
745         end
746         if fields["cb_opaque_water"] then
747                 engine.setting_setbool("opaque_water",tabbuilder.tobool(fields["cb_opaque_water"]))
748         end
749                         
750         if fields["cb_mipmapping"] then
751                 engine.setting_setbool("mip_map",tabbuilder.tobool(fields["cb_mipmapping"]))
752         end
753         if fields["cb_anisotrophic"] then
754                 engine.setting_setbool("anisotropic_filter",tabbuilder.tobool(fields["cb_anisotrophic"]))
755         end
756         if fields["cb_bilinear"] then
757                 engine.setting_setbool("bilinear_filter",tabbuilder.tobool(fields["cb_bilinear"]))
758         end
759         if fields["cb_trilinear"] then
760                 engine.setting_setbool("trilinear_filter",tabbuilder.tobool(fields["cb_trilinear"]))
761         end
762                         
763         if fields["cb_shaders"] then
764                 engine.setting_setbool("enable_shaders",tabbuilder.tobool(fields["cb_shaders"]))
765         end
766         if fields["cb_pre_ivis"] then
767                 engine.setting_setbool("preload_item_visuals",tabbuilder.tobool(fields["cb_pre_ivis"]))
768         end
769         if fields["cb_particles"] then
770                 engine.setting_setbool("enable_particles",tabbuilder.tobool(fields["cb_particles"]))
771         end
772         if fields["cb_finite_liquid"] then
773                 engine.setting_setbool("liquid_finite",tabbuilder.tobool(fields["cb_finite_liquid"]))
774         end
775
776         if fields["btn_change_keys"] ~= nil then
777                 engine.show_keys_menu()
778         end
779 end
780
781 --------------------------------------------------------------------------------
782 function tabbuilder.handle_singleplayer_buttons(fields)
783
784         local world_doubleclick = false
785
786         if fields["sp_worlds"] ~= nil then
787                 local event = explode_textlist_event(fields["sp_worlds"])
788                 
789                 if event.typ == "DCL" then
790                         world_doubleclick = true
791                 end
792         end
793         
794         if fields["cb_creative_mode"] then
795                 engine.setting_setbool("creative_mode",tabbuilder.tobool(fields["cb_creative_mode"]))
796         end
797         
798         if fields["cb_enable_damage"] then
799                 engine.setting_setbool("enable_damage",tabbuilder.tobool(fields["cb_enable_damage"]))
800         end
801
802         if fields["play"] ~= nil or
803                 world_doubleclick then
804                 local selected = engine.get_textlist_index("sp_worlds")
805                 if selected > 0 then
806                         gamedata.selected_world = menu.filtered_index_to_plain(selected)
807                         gamedata.singleplayer   = true
808                         
809                         engine.setting_set("main_menu_tab",tabbuilder.current_tab)
810                         engine.setting_set("main_menu_singleplayer_world_idx",selected)
811                         
812                         menu.update_last_game(gamedata.selected_world)
813                         
814                         engine.start()
815                 end
816         end
817         
818         if fields["world_create"] ~= nil then
819                 tabbuilder.current_tab = "dialog_create_world"
820                 tabbuilder.is_dialog = true
821                 tabbuilder.show_buttons = false
822         end
823         
824         if fields["world_delete"] ~= nil then
825                 local selected = engine.get_textlist_index("sp_worlds")
826                 if selected > 0 then
827                         menu.last_world = menu.filtered_index_to_plain(selected)
828                         if menu.lastworld() ~= nil and
829                                 menu.lastworld().name ~= nil and
830                                 menu.lastworld().name ~= "" then
831                                 tabbuilder.current_tab = "dialog_delete_world"
832                                 tabbuilder.is_dialog = true
833                                 tabbuilder.show_buttons = false
834                         else
835                                 menu.last_world = 0
836                         end
837                 end
838         end
839         
840         if fields["world_configure"] ~= nil then
841                 selected = engine.get_textlist_index("sp_worlds")
842                 if selected > 0 then
843                         modmgr.world_config_selected_world = menu.filtered_index_to_plain(selected)
844                         if modmgr.init_worldconfig() then
845                                 tabbuilder.current_tab = "dialog_configure_world"
846                                 tabbuilder.is_dialog = true
847                                 tabbuilder.show_buttons = false
848                         end
849                 end
850         end
851 end
852
853 --------------------------------------------------------------------------------
854 function tabbuilder.tab_header()
855
856         if tabbuilder.last_tab_index == nil then
857                 tabbuilder.last_tab_index = 1
858         end
859         
860         local toadd = ""
861         
862         for i=1,#tabbuilder.current_buttons,1 do
863                 
864                 if toadd ~= "" then
865                         toadd = toadd .. ","
866                 end
867                 
868                 toadd = toadd .. tabbuilder.current_buttons[i].caption
869         end
870         return "tabheader[-0.3,-0.99;main_tab;" .. toadd ..";" .. tabbuilder.last_tab_index .. ";true;false]"
871 end
872
873 --------------------------------------------------------------------------------
874 function tabbuilder.handle_tab_buttons(fields)
875
876         if fields["main_tab"] then
877                 local index = tonumber(fields["main_tab"])
878                 tabbuilder.last_tab_index = index
879                 tabbuilder.current_tab = tabbuilder.current_buttons[index].name
880                 
881                 engine.setting_set("main_menu_tab",tabbuilder.current_tab)
882         end
883         
884         --handle tab changes
885         if tabbuilder.current_tab ~= tabbuilder.old_tab then
886                 if tabbuilder.current_tab ~= "singleplayer" then
887                         menu.reset_gametype()
888                 end
889         end
890         
891         if tabbuilder.current_tab == "singleplayer" then
892                 menu.update_gametype()
893         end
894         
895         tabbuilder.old_tab = tabbuilder.current_tab
896 end
897
898 --------------------------------------------------------------------------------
899 function tabbuilder.init()
900         tabbuilder.current_tab = engine.setting_get("main_menu_tab")
901         
902         if tabbuilder.current_tab == nil or
903                 tabbuilder.current_tab == "" then
904                 tabbuilder.current_tab = "singleplayer"
905                 engine.setting_set("main_menu_tab",tabbuilder.current_tab)
906         end
907         
908         
909         --initialize tab buttons
910         tabbuilder.last_tab = nil
911         tabbuilder.show_buttons = true
912         
913         tabbuilder.current_buttons = {}
914         table.insert(tabbuilder.current_buttons,{name="singleplayer", caption="Singleplayer"})
915         table.insert(tabbuilder.current_buttons,{name="multiplayer", caption="Client"})
916         table.insert(tabbuilder.current_buttons,{name="server", caption="Server"})
917         table.insert(tabbuilder.current_buttons,{name="settings", caption="Settings"})
918         
919         if engine.setting_getbool("main_menu_game_mgr") then
920                 table.insert(tabbuilder.current_buttons,{name="game_mgr", caption="Games"})
921         end
922         
923         if engine.setting_getbool("main_menu_mod_mgr") then
924                 table.insert(tabbuilder.current_buttons,{name="mod_mgr", caption="Mods"})
925         end
926         table.insert(tabbuilder.current_buttons,{name="credits", caption="Credits"})
927         
928         
929         for i=1,#tabbuilder.current_buttons,1 do
930                 if tabbuilder.current_buttons[i].name == tabbuilder.current_tab then
931                         tabbuilder.last_tab_index = i
932                 end
933         end
934         
935         menu.update_gametype()
936 end
937
938 --------------------------------------------------------------------------------
939 function tabbuilder.tab_multiplayer()
940         local retval =
941                 "vertlabel[0,-0.25;CLIENT]" ..
942                 "label[1,-0.25;Favorites:]"..
943                 "label[1,4.25;Address/Port]"..
944                 "label[9,0;Name/Password]" ..
945                 "field[1.25,5.25;5.5,0.5;te_address;;" ..engine.setting_get("address") .."]" ..
946                 "field[6.75,5.25;2.25,0.5;te_port;;" ..engine.setting_get("port") .."]" ..
947                 "button[6.45,3.95;2.25,0.5;btn_delete_favorite;Delete]" ..
948                 "button[9,4.95;2.5,0.5;btn_mp_connect;Connect]" ..
949                 "field[9.25,1;2.5,0.5;te_name;;" ..engine.setting_get("name") .."]" ..
950                 "pwdfield[9.25,1.75;2.5,0.5;te_pwd;]" ..
951                 "checkbox[1,3.6;cb_public_serverlist;Public Serverlist;" ..
952                 dump(engine.setting_getbool("public_serverlist")) .. "]" ..
953                 "textlist[1,0.35;7.5,3.35;favourites;"
954
955         if #menu.favorites > 0 then
956                 retval = retval .. render_favourite(menu.favorites[1])
957                 
958                 for i=2,#menu.favorites,1 do
959                         retval = retval .. "," .. render_favourite(menu.favorites[i])
960                 end
961         end
962
963         retval = retval .. ";1]"
964
965         return retval
966 end
967
968 --------------------------------------------------------------------------------
969 function tabbuilder.tab_server()
970         local retval = 
971                 "button[4,4.15;2.6,0.5;world_delete;Delete]" ..
972                 "button[6.5,4.15;2.8,0.5;world_create;New]" ..
973                 "button[9.2,4.15;2.55,0.5;world_configure;Configure]" ..
974                 "button[8.5,4.9;3.25,0.5;start_server;Start Game]" ..
975                 "label[4,-0.25;Select World:]"..
976                 "vertlabel[0,-0.25;START SERVER]" ..
977                 "checkbox[0.5,0.25;cb_creative_mode;Creative Mode;" ..
978                 dump(engine.setting_getbool("creative_mode")) .. "]"..
979                 "checkbox[0.5,0.7;cb_enable_damage;Enable Damage;" ..
980                 dump(engine.setting_getbool("enable_damage")) .. "]"..
981                 "field[0.8,2.2;3,0.5;te_playername;Name;" ..
982                 engine.setting_get("name") .. "]" ..
983                 "pwdfield[0.8,3.2;3,0.5;te_passwd;Password]" ..
984                 "field[0.8,5.2;3,0.5;te_serverport;Server Port;30000]" ..
985                 "textlist[4,0.25;7.5,3.7;srv_worlds;"
986         
987         if #menu.worldlist > 0 then
988                 retval = retval .. menu.worldlist[1].name .. 
989                                                 " [[" .. menu.worldlist[1].gameid .. "]]"
990                                 
991                 for i=2,#menu.worldlist,1 do
992                         retval = retval .. "," .. menu.worldlist[i].name .. 
993                                                 " [[" .. menu.worldlist[i].gameid .. "]]"
994                 end
995         end
996                                 
997         retval = retval .. ";" .. menu.last_world .. "]"
998                 
999         return retval
1000 end
1001
1002 --------------------------------------------------------------------------------
1003 function tabbuilder.tab_settings()
1004         return  "vertlabel[0,0;SETTINGS]" ..
1005                         "checkbox[1,0.75;cb_fancy_trees;Fancy trees;"           .. dump(engine.setting_getbool("new_style_leaves"))     .. "]"..
1006                         "checkbox[1,1.25;cb_smooth_lighting;Smooth Lighting;".. dump(engine.setting_getbool("smooth_lighting")) .. "]"..
1007                         "checkbox[1,1.75;cb_3d_clouds;3D Clouds;"                       .. dump(engine.setting_getbool("enable_3d_clouds"))     .. "]"..
1008                         "checkbox[1,2.25;cb_opaque_water;Opaque Water;"                 .. dump(engine.setting_getbool("opaque_water"))         .. "]"..
1009                         
1010                         "checkbox[4,0.75;cb_mipmapping;Mip-Mapping;"            .. dump(engine.setting_getbool("mip_map"))                      .. "]"..
1011                         "checkbox[4,1.25;cb_anisotrophic;Anisotropic Filtering;".. dump(engine.setting_getbool("anisotropic_filter"))   .. "]"..
1012                         "checkbox[4,1.75;cb_bilinear;Bi-Linear Filtering;"      .. dump(engine.setting_getbool("bilinear_filter"))      .. "]"..
1013                         "checkbox[4,2.25;cb_trilinear;Tri-Linear Filtering;"    .. dump(engine.setting_getbool("trilinear_filter"))     .. "]"..
1014                         
1015                         "checkbox[7.5,0.75;cb_shaders;Shaders;"                         .. dump(engine.setting_getbool("enable_shaders"))               .. "]"..
1016                         "checkbox[7.5,1.25;cb_pre_ivis;Preload item visuals;".. dump(engine.setting_getbool("preload_item_visuals"))    .. "]"..
1017                         "checkbox[7.5,1.75;cb_particles;Enable Particles;"      .. dump(engine.setting_getbool("enable_particles"))     .. "]"..
1018                         "checkbox[7.5,2.25;cb_finite_liquid;Finite Liquid;"     .. dump(engine.setting_getbool("liquid_finite"))                .. "]"..
1019                         
1020                         "button[1,3.75;2.25,0.5;btn_change_keys;Change keys]"
1021 end
1022
1023 --------------------------------------------------------------------------------
1024 function tabbuilder.tab_singleplayer()
1025         local index = engine.setting_get("main_menu_singleplayer_world_idx")
1026         
1027         if index == nil then
1028                 index = 0
1029         end
1030
1031         return  "button[4,4.15;2.6,0.5;world_delete;Delete]" ..
1032                         "button[6.5,4.15;2.8,0.5;world_create;New]" ..
1033                         "button[9.2,4.15;2.55,0.5;world_configure;Configure]" ..
1034                         "button[8.5,4.95;3.25,0.5;play;Play]" ..
1035                         "label[4,-0.25;Select World:]"..
1036                         "vertlabel[0,-0.25;SINGLE PLAYER]" ..
1037                         "checkbox[0.5,0.25;cb_creative_mode;Creative Mode;" ..
1038                         dump(engine.setting_getbool("creative_mode")) .. "]"..
1039                         "checkbox[0.5,0.7;cb_enable_damage;Enable Damage;" ..
1040                         dump(engine.setting_getbool("enable_damage")) .. "]"..
1041                         "textlist[4,0.25;7.5,3.7;sp_worlds;" ..
1042                         menu.filtered_game_list() ..
1043                         ";" .. index .. "]" ..
1044                         menubar.formspec
1045 end
1046
1047 --------------------------------------------------------------------------------
1048 function tabbuilder.tab_credits()
1049         return  "vertlabel[0,-0.5;CREDITS]" ..
1050                         "label[0.5,3;Minetest " .. engine.get_version() .. "]" ..
1051                         "label[0.5,3.3;http://minetest.net]" .. 
1052                         "image[0.5,1;" .. menu.basetexturedir .. "logo.png]" ..
1053                         "textlist[3.5,-0.25;8.5,5.8;list_credits;" ..
1054                         "#YLWCore Developers," ..
1055                         "Perttu Ahola (celeron55) <celeron55@gmail.com>,"..
1056                         "Ryan Kwolek (kwolekr) <kwolekr@minetest.net>,"..
1057                         "PilzAdam <pilzadam@minetest.net>," ..
1058                         "IIya Zhuravlev (thexyz) <xyz@minetest.net>,"..
1059                         "Lisa Milne (darkrose) <lisa@ltmnet.com>,"..
1060                         "Maciej Kasatkin (RealBadAngel) <mk@realbadangel.pl>,"..
1061                         "proller <proler@gmail.com>,"..
1062                         "sfan5 <sfan5@live.de>,"..
1063                         "kahrl <kahrl@gmx.net>,"..
1064                         ","..
1065                         "#YLWActive Contributors," ..
1066                         "sapier,"..
1067                         "Vanessa Ezekowitz (VanessaE) <vanessaezekowitz@gmail.com>,"..
1068                         "Jurgen Doser (doserj) <jurgen.doser@gmail.com>,"..
1069                         "Jeija <jeija@mesecons.net>,"..
1070                         "MirceaKitsune <mirceakitsune@gmail.com>,"..
1071                         "ShadowNinja"..
1072                         "dannydark <the_skeleton_of_a_child@yahoo.co.uk>"..
1073                         "0gb.us <0gb.us@0gb.us>,"..
1074                         "," ..
1075                         "#YLWPrevious Contributors," ..
1076                         "Guiseppe Bilotta (Oblomov) <guiseppe.bilotta@gmail.com>,"..
1077                         "Jonathan Neuschafer <j.neuschaefer@gmx.net>,"..
1078                         "Nils Dagsson Moskopp (erlehmann) <nils@dieweltistgarnichtso.net>,"..
1079                         "Constantin Wenger (SpeedProg) <constantin.wenger@googlemail.com>,"..
1080                         "matttpt <matttpt@gmail.com>,"..
1081                         "JacobF <queatz@gmail.com>,"..
1082                         ";0;true]"
1083 end
1084
1085 --------------------------------------------------------------------------------
1086 function tabbuilder.checkretval(retval)
1087
1088         if retval ~= nil then
1089                 if retval.current_tab ~= nil then
1090                         tabbuilder.current_tab = retval.current_tab
1091                 end
1092                 
1093                 if retval.is_dialog ~= nil then
1094                         tabbuilder.is_dialog = retval.is_dialog
1095                 end
1096                 
1097                 if retval.show_buttons ~= nil then
1098                         tabbuilder.show_buttons = retval.show_buttons
1099                 end
1100                 
1101                 if retval.skipformupdate ~= nil then
1102                         tabbuilder.skipformupdate = retval.skipformupdate
1103                 end
1104         end
1105 end
1106
1107 --------------------------------------------------------------------------------
1108 --------------------------------------------------------------------------------
1109 -- initialize callbacks
1110 --------------------------------------------------------------------------------
1111 --------------------------------------------------------------------------------
1112 engine.button_handler = function(fields)
1113         --print("Buttonhandler: tab: " .. tabbuilder.current_tab .. " fields: " .. dump(fields))
1114         
1115         if fields["btn_error_confirm"] then
1116                 gamedata.errormessage = nil
1117         end
1118         
1119         local retval = modmgr.handle_buttons(tabbuilder.current_tab,fields)
1120         tabbuilder.checkretval(retval)
1121         
1122         retval = gamemgr.handle_buttons(tabbuilder.current_tab,fields)
1123         tabbuilder.checkretval(retval)
1124         
1125         retval = modstore.handle_buttons(tabbuilder.current_tab,fields)
1126         tabbuilder.checkretval(retval)
1127         
1128         if tabbuilder.current_tab == "dialog_create_world" then
1129                 tabbuilder.handle_create_world_buttons(fields)
1130         end
1131         
1132         if tabbuilder.current_tab == "dialog_delete_world" then
1133                 tabbuilder.handle_delete_world_buttons(fields)
1134         end
1135         
1136         if tabbuilder.current_tab == "singleplayer" then
1137                 tabbuilder.handle_singleplayer_buttons(fields)
1138         end
1139         
1140         if tabbuilder.current_tab == "multiplayer" then
1141                 tabbuilder.handle_multiplayer_buttons(fields)
1142         end
1143         
1144         if tabbuilder.current_tab == "settings" then
1145                 tabbuilder.handle_settings_buttons(fields)
1146         end
1147         
1148         if tabbuilder.current_tab == "server" then
1149                 tabbuilder.handle_server_buttons(fields)
1150         end
1151         
1152         --tab buttons
1153         tabbuilder.handle_tab_buttons(fields)
1154         
1155         --menubar buttons
1156         menubar.handle_buttons(fields)
1157         
1158         if not tabbuilder.skipformupdate then
1159                 --update menu
1160                 update_menu()
1161         else
1162                 tabbuilder.skipformupdate = false
1163         end
1164 end
1165
1166 --------------------------------------------------------------------------------
1167 engine.event_handler = function(event)
1168         if event == "MenuQuit" then
1169                 if tabbuilder.is_dialog then
1170                         tabbuilder.is_dialog = false
1171                         tabbuilder.show_buttons = true
1172                         tabbuilder.current_tab = engine.setting_get("main_menu_tab")
1173                         update_menu()
1174                 else
1175                         engine.close()
1176                 end
1177         end
1178 end
1179
1180 --------------------------------------------------------------------------------
1181 --------------------------------------------------------------------------------
1182 -- menu startup
1183 --------------------------------------------------------------------------------
1184 --------------------------------------------------------------------------------
1185 init_globals()
1186 menu.init()
1187 tabbuilder.init()
1188 menubar.refresh()
1189 modstore.init()
1190 update_menu()