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