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