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