Add cloud menu background by Krisi, configurable with the menu_clouds option.
[oweals/minetest.git] / src / guiMainMenu.cpp
1 /*
2 Minetest
3 Copyright (C) 2010-2013 celeron55, Perttu Ahola <celeron55@gmail.com>
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU Lesser General Public License as published by
7 the Free Software Foundation; either version 2.1 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 GNU Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public License along
16 with this program; if not, write to the Free Software Foundation, Inc.,
17 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19
20 #include "guiMainMenu.h"
21 #include "guiKeyChangeMenu.h"
22 #include "guiCreateWorld.h"
23 #include "guiConfigureWorld.h"
24 #include "guiMessageMenu.h"
25 #include "guiConfirmMenu.h"
26 #include "debug.h"
27 #include "serialization.h"
28 #include <string>
29 #include <IGUICheckBox.h>
30 #include <IGUIEditBox.h>
31 #include <IGUIButton.h>
32 #include <IGUIStaticText.h>
33 #include <IGUIFont.h>
34 #include <IGUIListBox.h>
35 #include <IGUITabControl.h>
36 #include <IGUIImage.h>
37 // For IGameCallback
38 #include "guiPauseMenu.h"
39 #include "gettext.h"
40 #include "tile.h" // getTexturePath
41 #include "filesys.h"
42 #include "util/string.h"
43 #include "subgame.h"
44
45 struct CreateWorldDestMainMenu : public CreateWorldDest
46 {
47         CreateWorldDestMainMenu(GUIMainMenu *menu):
48                 m_menu(menu)
49         {}
50         void accepted(std::wstring name, std::string gameid)
51         {
52                 std::string name_narrow = wide_to_narrow(name);
53                 if(!string_allowed_blacklist(name_narrow, WORLDNAME_BLACKLISTED_CHARS))
54                 {
55                         m_menu->displayMessageMenu(wgettext("Cannot create world: Name contains invalid characters"));
56                         return;
57                 }
58                 std::vector<WorldSpec> worlds = getAvailableWorlds();
59                 for(std::vector<WorldSpec>::iterator i = worlds.begin();
60                     i != worlds.end(); i++)
61                 {
62                         if((*i).name == name_narrow)
63                         {
64                                 m_menu->displayMessageMenu(wgettext("Cannot create world: A world by this name already exists"));
65                                 return;
66                         }
67                 }
68                 m_menu->createNewWorld(name, gameid);
69         }
70         GUIMainMenu *m_menu;
71 };
72
73 struct ConfirmDestDeleteWorld : public ConfirmDest
74 {
75         ConfirmDestDeleteWorld(WorldSpec spec, GUIMainMenu *menu,
76                         const std::vector<std::string> &paths):
77                 m_spec(spec),
78                 m_menu(menu),
79                 m_paths(paths)
80         {}
81         void answer(bool answer)
82         {
83                 if(answer == false)
84                         return;
85                 m_menu->deleteWorld(m_paths);
86         }
87         WorldSpec m_spec;
88         GUIMainMenu *m_menu;
89         std::vector<std::string> m_paths;
90 };
91
92 enum
93 {
94         GUI_ID_QUIT_BUTTON = 101,
95         GUI_ID_NAME_INPUT,
96         GUI_ID_ADDRESS_INPUT,
97         GUI_ID_PORT_INPUT,
98         GUI_ID_FANCYTREE_CB,
99         GUI_ID_SMOOTH_LIGHTING_CB,
100         GUI_ID_3D_CLOUDS_CB,
101         GUI_ID_OPAQUE_WATER_CB,
102         GUI_ID_MIPMAP_CB,
103         GUI_ID_ANISOTROPIC_CB,
104         GUI_ID_BILINEAR_CB,
105         GUI_ID_TRILINEAR_CB,
106         GUI_ID_SHADERS_CB,
107         GUI_ID_PRELOAD_ITEM_VISUALS_CB,
108         GUI_ID_ENABLE_PARTICLES_CB,
109         GUI_ID_DAMAGE_CB,
110         GUI_ID_CREATIVE_CB,
111         GUI_ID_PUBLIC_CB,
112         GUI_ID_JOIN_GAME_BUTTON,
113         GUI_ID_CHANGE_KEYS_BUTTON,
114         GUI_ID_DELETE_WORLD_BUTTON,
115         GUI_ID_CREATE_WORLD_BUTTON,
116         GUI_ID_CONFIGURE_WORLD_BUTTON,
117         GUI_ID_WORLD_LISTBOX,
118         GUI_ID_TAB_CONTROL,
119         GUI_ID_SERVERLIST,
120         GUI_ID_SERVERLIST_TOGGLE,
121         GUI_ID_SERVERLIST_DELETE,
122 };
123
124 enum
125 {
126         TAB_SINGLEPLAYER=0,
127         TAB_MULTIPLAYER,
128         TAB_ADVANCED,
129         TAB_SETTINGS,
130         TAB_CREDITS
131 };
132
133 GUIMainMenu::GUIMainMenu(gui::IGUIEnvironment* env,
134                 gui::IGUIElement* parent, s32 id,
135                 IMenuManager *menumgr,
136                 MainMenuData *data,
137                 IGameCallback *gamecallback
138 ):
139         GUIModalMenu(env, parent, id, menumgr),
140         m_data(data),
141         m_accepted(false),
142         m_gamecallback(gamecallback),
143         m_is_regenerating(false)
144 {
145         assert(m_data);
146         this->env = env;
147         this->parent = parent;
148         this->id = id;
149         this->menumgr = menumgr;
150 }
151
152 GUIMainMenu::~GUIMainMenu()
153 {
154         removeChildren();
155 }
156
157 void GUIMainMenu::removeChildren()
158 {
159         const core::list<gui::IGUIElement*> &children = getChildren();
160         core::list<gui::IGUIElement*> children_copy;
161         for(core::list<gui::IGUIElement*>::ConstIterator
162                         i = children.begin(); i != children.end(); i++)
163         {
164                 children_copy.push_back(*i);
165         }
166         for(core::list<gui::IGUIElement*>::Iterator
167                         i = children_copy.begin();
168                         i != children_copy.end(); i++)
169         {
170                 (*i)->remove();
171         }
172 }
173
174 void GUIMainMenu::regenerateGui(v2u32 screensize)
175 {
176         m_is_regenerating = true;
177         /*
178                 Read stuff from elements into m_data
179         */
180         readInput(m_data);
181
182         /*
183                 Remove stuff
184         */
185         removeChildren();
186         
187         /*
188                 Calculate new sizes and positions
189         */
190         
191         v2s32 size(screensize.X, screensize.Y);
192
193         core::rect<s32> rect(
194                         screensize.X/2 - size.X/2,
195                         screensize.Y/2 - size.Y/2,
196                         screensize.X/2 + size.X/2,
197                         screensize.Y/2 + size.Y/2
198         );
199
200         DesiredRect = rect;
201         recalculateAbsolutePosition(false);
202
203         //v2s32 size = rect.getSize();
204
205         /*
206                 Add stuff
207         */
208
209         changeCtype("");
210
211         // Version
212         {
213                 core::rect<s32> rect(0, 0, size.X, 40);
214                 rect += v2s32(4, 0);
215                 Environment->addStaticText(narrow_to_wide(
216                                 "Minetest " VERSION_STRING).c_str(),
217                                 rect, false, true, this, -1);
218         }
219
220         //v2s32 center(size.X/2, size.Y/2);
221         v2s32 c800(size.X/2-400, size.Y/2-270);
222         
223         m_topleft_client = c800 + v2s32(90, 70+50+30);
224         m_size_client = v2s32(620, 270);
225
226         m_size_server = v2s32(620, 140);
227
228         if(m_data->selected_tab == TAB_ADVANCED)
229         {
230                 m_topleft_client = c800 + v2s32(90, 70+50+30);
231                 m_size_client = v2s32(620, 200);
232
233                 m_size_server = v2s32(620, 140);
234         }
235
236         m_topleft_server = m_topleft_client + v2s32(0, m_size_client.Y+20);
237         
238         // Tabs
239         {
240                 core::rect<s32> rect(0, 0, m_size_client.X, 30);
241                 rect += m_topleft_client + v2s32(0, -30);
242                 gui::IGUITabControl *e = Environment->addTabControl(
243                                 rect, this, true, true, GUI_ID_TAB_CONTROL);
244                 e->addTab(wgettext("Singleplayer"));
245                 e->addTab(wgettext("Multiplayer"));
246                 e->addTab(wgettext("Advanced"));
247                 e->addTab(wgettext("Settings"));
248                 e->addTab(wgettext("Credits"));
249                 e->setActiveTab(m_data->selected_tab);
250         }
251         
252         if(m_data->selected_tab == TAB_SINGLEPLAYER)
253         {
254                 // HYBRID
255                 {
256                         core::rect<s32> rect(0, 0, 10, m_size_client.Y);
257                         rect += m_topleft_client + v2s32(15, 0);
258                         //const wchar_t *text = L"H\nY\nB\nR\nI\nD";
259                         const wchar_t *text = L"T\nA\nP\nE\n\nA\nN\nD\n\nG\nL\nU\nE";
260                         gui::IGUIStaticText *t =
261                         Environment->addStaticText(text, rect, false, true, this, -1);
262                         t->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_CENTER);
263                 }
264                 u32 bs = 5;
265                 // World selection listbox
266                 u32 world_sel_h = 160;
267                 u32 world_sel_w = 365;
268                 //s32 world_sel_x = 50;
269                 s32 world_sel_x = m_size_client.X-world_sel_w-30;
270                 s32 world_sel_y = 30;
271                 u32 world_button_count = 3;
272                 u32 world_button_w = (world_sel_w)/world_button_count - bs
273                                 + bs/(world_button_count-1);
274                 {
275                         core::rect<s32> rect(0, 0, world_sel_w-4, 20);
276                         rect += m_topleft_client + v2s32(world_sel_x+4, world_sel_y-20);
277                         /*gui::IGUIStaticText *e =*/ Environment->addStaticText(
278                                         wgettext("Select World:"), 
279                                         rect, false, true, this, -1);
280                         /*e->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_CENTER);*/
281                 }
282                 {
283                         core::rect<s32> rect(0, 0, world_sel_w, world_sel_h);
284                         rect += m_topleft_client + v2s32(world_sel_x, world_sel_y);
285                         gui::IGUIListBox *e = Environment->addListBox(rect, this,
286                                         GUI_ID_WORLD_LISTBOX);
287                         e->setDrawBackground(true);
288                         for(std::vector<WorldSpec>::const_iterator i = m_data->worlds.begin();
289                                         i != m_data->worlds.end(); i++){
290                                 e->addItem(narrow_to_wide(i->name+" ["+i->gameid+"]").c_str());
291                         }
292                         e->setSelected(m_data->selected_world);
293                         Environment->setFocus(e);
294                 }
295                 // Delete world button
296                 {
297                         core::rect<s32> rect(0, 0, world_button_w, 30);
298                         rect += m_topleft_client + v2s32(world_sel_x, world_sel_y+world_sel_h+0);
299                         Environment->addButton(rect, this, GUI_ID_DELETE_WORLD_BUTTON,
300                                   wgettext("Delete"));
301                 }
302                 // Create world button
303                 {
304                         core::rect<s32> rect(0, 0, world_button_w, 30);
305                         rect += m_topleft_client + v2s32(world_sel_x+world_button_w+bs, world_sel_y+world_sel_h+0);
306                         Environment->addButton(rect, this, GUI_ID_CREATE_WORLD_BUTTON,
307                                   wgettext("New"));
308                 }
309                 // Configure world button
310                 {
311                         core::rect<s32> rect(0, 0, world_button_w, 30);
312                         rect += m_topleft_client + v2s32(world_sel_x+(world_button_w+bs)*2,
313                                         world_sel_y+world_sel_h+0);
314                         Environment->addButton(rect, this, GUI_ID_CONFIGURE_WORLD_BUTTON,
315                                   wgettext("Configure"));
316                 }
317                 // Start game button
318                 {
319                         /*core::rect<s32> rect(0, 0, world_button_w, 30);
320                         rect += m_topleft_client + v2s32(world_sel_x+(world_button_w+bs)*3,
321                                         world_sel_y+world_sel_h+0);*/
322                         u32 bw = 160;
323                         /*core::rect<s32> rect(0, 0, bw, 30);
324                         rect += m_topleft_client + v2s32(m_size_client.X-bw-30,
325                                         m_size_client.Y-30-15);*/
326                         core::rect<s32> rect(0, 0, bw, 30);
327                         rect += m_topleft_client + v2s32(world_sel_x+world_sel_w-bw,
328                                         world_sel_y+world_sel_h+30+bs);
329                         Environment->addButton(rect, this,
330                                         GUI_ID_JOIN_GAME_BUTTON, wgettext("Play"));
331                 }
332                 // Options
333                 s32 option_x = 50;
334                 //s32 option_x = 50+world_sel_w+20;
335                 s32 option_y = 30;
336                 u32 option_w = 150;
337                 {
338                         core::rect<s32> rect(0, 0, option_w, 30);
339                         rect += m_topleft_client + v2s32(option_x, option_y+20*0);
340                         Environment->addCheckBox(m_data->creative_mode, rect, this,
341                                         GUI_ID_CREATIVE_CB, wgettext("Creative Mode"));
342                 }
343                 {
344                         core::rect<s32> rect(0, 0, option_w, 30);
345                         rect += m_topleft_client + v2s32(option_x, option_y+20*1);
346                         Environment->addCheckBox(m_data->enable_damage, rect, this,
347                                         GUI_ID_DAMAGE_CB, wgettext("Enable Damage"));
348                 }
349                 changeCtype("C");
350         }
351         else if(m_data->selected_tab == TAB_MULTIPLAYER)
352         {
353                 changeCtype("");
354                 // CLIENT
355                 {
356                         core::rect<s32> rect(0, 0, 10, m_size_client.Y);
357                         rect += m_topleft_client + v2s32(15, 0);
358                         const wchar_t *text = L"C\nL\nI\nE\nN\nT";
359                         gui::IGUIStaticText *t =
360                         Environment->addStaticText(text, rect, false, true, this, -1);
361                         t->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_CENTER);
362                 }
363                 // Nickname + password
364                 {
365                         core::rect<s32> rect(0, 0, 110, 20);
366                         rect += m_topleft_client + v2s32(m_size_client.X-60-100, 10+6);
367                         Environment->addStaticText(wgettext("Name/Password"), 
368                                 rect, false, true, this, -1);
369                 }
370                 changeCtype("C");
371                 {
372                         core::rect<s32> rect(0, 0, 120, 30);
373                         rect += m_topleft_client + v2s32(m_size_client.X-60-100, 50);
374                         gui::IGUIElement *e = 
375                         Environment->addEditBox(m_data->name.c_str(), rect, true, this, GUI_ID_NAME_INPUT);
376                         if(m_data->name == L"")
377                                 Environment->setFocus(e);
378                 }
379                 {
380                         core::rect<s32> rect(0, 0, 120, 30);
381                         rect += m_topleft_client + v2s32(m_size_client.X-60-100, 90);
382                         gui::IGUIEditBox *e =
383                         Environment->addEditBox(L"", rect, true, this, 264);
384                         e->setPasswordBox(true);
385                         if(m_data->name != L"" && m_data->address != L"")
386                                 Environment->setFocus(e);
387
388                 }
389                 changeCtype("");
390                 // Server List
391                 {
392                         core::rect<s32> rect(0, 0, 390, 160);
393                         rect += m_topleft_client + v2s32(50, 10);
394                         gui::IGUIListBox *e = Environment->addListBox(rect, this,
395                                         GUI_ID_SERVERLIST);
396                         e->setDrawBackground(true);
397                         if (m_data->serverlist_show_available == false)
398                                 m_data->servers = ServerList::getLocal();
399                         updateGuiServerList();
400                         e->setSelected(0);
401                 }
402                 // Address + port
403                 {
404                         core::rect<s32> rect(0, 0, 110, 20);
405                         rect += m_topleft_client + v2s32(50, m_size_client.Y-50-15+6);
406                         Environment->addStaticText(wgettext("Address/Port"),
407                                 rect, false, true, this, -1);
408                 }
409                 changeCtype("C");
410                 {
411                         core::rect<s32> rect(0, 0, 260, 30);
412                         rect += m_topleft_client + v2s32(50, m_size_client.Y-25-15);
413                         gui::IGUIElement *e = 
414                         Environment->addEditBox(m_data->address.c_str(), rect, true,
415                                         this, GUI_ID_ADDRESS_INPUT);
416                         if(m_data->name != L"" && m_data->address == L"")
417                                 Environment->setFocus(e);
418                 }
419                 {
420                         core::rect<s32> rect(0, 0, 120, 30);
421                         rect += m_topleft_client + v2s32(50+260+10, m_size_client.Y-25-15);
422                         Environment->addEditBox(m_data->port.c_str(), rect, true,
423                                         this, GUI_ID_PORT_INPUT);
424                 }
425                 changeCtype("");
426                 #if USE_CURL
427                 // Toggle Serverlist (Favorites/Online)
428                 {
429                         core::rect<s32> rect(0, 0, 260, 30);
430                         rect += m_topleft_client + v2s32(50,
431                                         180);
432                         gui::IGUIButton *e = Environment->addButton(rect, this, GUI_ID_SERVERLIST_TOGGLE,
433                                 wgettext("Show Public"));
434                         e->setIsPushButton(true);
435                         if (m_data->serverlist_show_available)
436                         {
437                                 e->setText(wgettext("Show Favorites"));
438                                 e->setPressed();
439                         }
440                 }
441                 #endif
442                 // Delete Local Favorite
443                 {
444                         core::rect<s32> rect(0, 0, 120, 30);
445                         rect += m_topleft_client + v2s32(50+260+10, 180);
446                         gui::IGUIButton *e = Environment->addButton(rect, this, GUI_ID_SERVERLIST_DELETE,
447                                 wgettext("Delete"));
448                         if (m_data->serverlist_show_available) // Hidden on Show-Online mode
449                                 e->setVisible(false);
450                 }
451                 // Start game button
452                 {
453                         core::rect<s32> rect(0, 0, 120, 30);
454                         rect += m_topleft_client + v2s32(m_size_client.X-130-30,
455                                         m_size_client.Y-25-15);
456                         Environment->addButton(rect, this, GUI_ID_JOIN_GAME_BUTTON,
457                                 wgettext("Connect"));
458                 }
459                 changeCtype("C");
460         }
461         else if(m_data->selected_tab == TAB_ADVANCED)
462         {
463                 changeCtype("");
464                 // CLIENT
465                 {
466                         core::rect<s32> rect(0, 0, 10, m_size_client.Y);
467                         rect += m_topleft_client + v2s32(15, 0);
468                         const wchar_t *text = L"C\nL\nI\nE\nN\nT";
469                         gui::IGUIStaticText *t =
470                         Environment->addStaticText(text, rect, false, true, this, -1);
471                         t->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_CENTER);
472                 }
473                 // Nickname + password
474                 {
475                         core::rect<s32> rect(0, 0, 110, 20);
476                         rect += m_topleft_client + v2s32(35+30, 35+6);
477                         Environment->addStaticText(wgettext("Name/Password"), 
478                                 rect, false, true, this, -1);
479                 }
480                 changeCtype("C");
481                 {
482                         core::rect<s32> rect(0, 0, 230, 30);
483                         rect += m_topleft_client + v2s32(160+30, 35);
484                         gui::IGUIElement *e = 
485                         Environment->addEditBox(m_data->name.c_str(), rect, true, this, GUI_ID_NAME_INPUT);
486                         if(m_data->name == L"")
487                                 Environment->setFocus(e);
488                 }
489                 {
490                         core::rect<s32> rect(0, 0, 120, 30);
491                         rect += m_topleft_client + v2s32(m_size_client.X-60-100, 35);
492                         gui::IGUIEditBox *e =
493                         Environment->addEditBox(L"", rect, true, this, 264);
494                         e->setPasswordBox(true);
495                         if(m_data->name != L"" && m_data->address != L"")
496                                 Environment->setFocus(e);
497
498                 }
499                 changeCtype("");
500                 // Address + port
501                 {
502                         core::rect<s32> rect(0, 0, 110, 20);
503                         rect += m_topleft_client + v2s32(35+30, 75+6);
504                         Environment->addStaticText(wgettext("Address/Port"),
505                                 rect, false, true, this, -1);
506                 }
507                 changeCtype("C");
508                 {
509                         core::rect<s32> rect(0, 0, 230, 30);
510                         rect += m_topleft_client + v2s32(160+30, 75);
511                         gui::IGUIElement *e = 
512                         Environment->addEditBox(m_data->address.c_str(), rect, true,
513                                         this, GUI_ID_ADDRESS_INPUT);
514                         if(m_data->name != L"" && m_data->address == L"")
515                                 Environment->setFocus(e);
516                 }
517                 {
518                         core::rect<s32> rect(0, 0, 120, 30);
519                         rect += m_topleft_client + v2s32(m_size_client.X-60-100, 75);
520                         Environment->addEditBox(m_data->port.c_str(), rect, true,
521                                         this, GUI_ID_PORT_INPUT);
522                 }
523                 changeCtype("");
524                 {
525                         core::rect<s32> rect(0, 0, 400, 20);
526                         rect += m_topleft_client + v2s32(160+30, 75+35);
527                         Environment->addStaticText(wgettext("Leave address blank to start a local server."),
528                                 rect, false, true, this, -1);
529                 }
530                 // Start game button
531                 {
532                         core::rect<s32> rect(0, 0, 180, 30);
533                         rect += m_topleft_client + v2s32(m_size_client.X-180-30,
534                                         m_size_client.Y-30-20);
535                         Environment->addButton(rect, this, GUI_ID_JOIN_GAME_BUTTON,
536                                 wgettext("Start Game / Connect"));
537                 }
538                 /*
539                         Server section
540                 */
541                 // SERVER
542                 {
543                         core::rect<s32> rect(0, 0, 10, m_size_server.Y);
544                         rect += m_topleft_server + v2s32(15, 0);
545                         const wchar_t *text = L"S\nE\nR\nV\nE\nR";
546                         gui::IGUIStaticText *t =
547                         Environment->addStaticText(text, rect, false, true, this, -1);
548                         t->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_CENTER);
549                 }
550                 // Server parameters
551                 {
552                         core::rect<s32> rect(0, 0, 250, 30);
553                         rect += m_topleft_server + v2s32(30+20+250+20, 20);
554                         Environment->addCheckBox(m_data->creative_mode, rect, this, GUI_ID_CREATIVE_CB,
555                                 wgettext("Creative Mode"));
556                 }
557                 {
558                         core::rect<s32> rect(0, 0, 250, 30);
559                         rect += m_topleft_server + v2s32(30+20+250+20, 40);
560                         Environment->addCheckBox(m_data->enable_damage, rect, this, GUI_ID_DAMAGE_CB,
561                                 wgettext("Enable Damage"));
562                 }
563                 #if USE_CURL
564                 {
565                         core::rect<s32> rect(0, 0, 250, 30);
566                         rect += m_topleft_server + v2s32(30+20+250+20, 60);
567                         Environment->addCheckBox(m_data->enable_public, rect, this, GUI_ID_PUBLIC_CB,
568                                 wgettext("Public"));
569                 }
570                 #endif
571                 // Delete world button
572                 {
573                         core::rect<s32> rect(0, 0, 130, 30);
574                         rect += m_topleft_server + v2s32(30+20+250+20, 90);
575                         Environment->addButton(rect, this, GUI_ID_DELETE_WORLD_BUTTON,
576                                   wgettext("Delete world"));
577                 }
578                 // Create world button
579                 {
580                         core::rect<s32> rect(0, 0, 130, 30);
581                         rect += m_topleft_server + v2s32(30+20+250+20+140, 90);
582                         Environment->addButton(rect, this, GUI_ID_CREATE_WORLD_BUTTON,
583                                   wgettext("Create world"));
584                 }
585                 // World selection listbox
586                 {
587                         core::rect<s32> rect(0, 0, 250, 120);
588                         rect += m_topleft_server + v2s32(30+20, 10);
589                         gui::IGUIListBox *e = Environment->addListBox(rect, this,
590                                         GUI_ID_WORLD_LISTBOX);
591                         e->setDrawBackground(true);
592                         for(std::vector<WorldSpec>::const_iterator i = m_data->worlds.begin();
593                                         i != m_data->worlds.end(); i++){
594                                 e->addItem(narrow_to_wide(i->name+" ["+i->gameid+"]").c_str());
595                         }
596                         e->setSelected(m_data->selected_world);
597                 }
598                 changeCtype("C");
599         }
600         else if(m_data->selected_tab == TAB_SETTINGS)
601         {
602                 {
603                         core::rect<s32> rect(0, 0, 10, m_size_client.Y);
604                         rect += m_topleft_client + v2s32(15, 0);
605                         const wchar_t *text = L"S\nE\nT\nT\nI\nN\nG\nS";
606                         gui::IGUIStaticText *t =
607                         Environment->addStaticText(text, rect, false, true, this, -1);
608                         t->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_CENTER);
609                 }
610                 s32 option_x = 70;
611                 s32 option_y = 50;
612                 u32 option_w = 150;
613                 {
614                         core::rect<s32> rect(0, 0, option_w, 30);
615                         rect += m_topleft_client + v2s32(option_x, option_y);
616                         Environment->addCheckBox(m_data->fancy_trees, rect, this,
617                                         GUI_ID_FANCYTREE_CB, wgettext("Fancy trees")); 
618                 }
619                 {
620                         core::rect<s32> rect(0, 0, option_w, 30);
621                         rect += m_topleft_client + v2s32(option_x, option_y+20);
622                         Environment->addCheckBox(m_data->smooth_lighting, rect, this,
623                                         GUI_ID_SMOOTH_LIGHTING_CB, wgettext("Smooth Lighting"));
624                 }
625                 {
626                         core::rect<s32> rect(0, 0, option_w, 30);
627                         rect += m_topleft_client + v2s32(option_x, option_y+20*2);
628                         Environment->addCheckBox(m_data->clouds_3d, rect, this,
629                                         GUI_ID_3D_CLOUDS_CB, wgettext("3D Clouds"));
630                 }
631                 {
632                         core::rect<s32> rect(0, 0, option_w, 30);
633                         rect += m_topleft_client + v2s32(option_x, option_y+20*3);
634                         Environment->addCheckBox(m_data->opaque_water, rect, this,
635                                         GUI_ID_OPAQUE_WATER_CB, wgettext("Opaque water"));
636                 }
637
638
639                 // Anisotropic/mipmap/bi-/trilinear settings
640
641                 {
642                         core::rect<s32> rect(0, 0, option_w+20, 30);
643                         rect += m_topleft_client + v2s32(option_x+175, option_y);
644                         Environment->addCheckBox(m_data->mip_map, rect, this,
645                                        GUI_ID_MIPMAP_CB, wgettext("Mip-Mapping"));
646                 }
647
648                 {
649                         core::rect<s32> rect(0, 0, option_w+20, 30);
650                         rect += m_topleft_client + v2s32(option_x+175, option_y+20);
651                         Environment->addCheckBox(m_data->anisotropic_filter, rect, this,
652                                        GUI_ID_ANISOTROPIC_CB, wgettext("Anisotropic Filtering"));
653                 }
654
655                 {
656                         core::rect<s32> rect(0, 0, option_w+20, 30);
657                         rect += m_topleft_client + v2s32(option_x+175, option_y+20*2);
658                         Environment->addCheckBox(m_data->bilinear_filter, rect, this,
659                                        GUI_ID_BILINEAR_CB, wgettext("Bi-Linear Filtering"));
660                 }
661
662                 {
663                         core::rect<s32> rect(0, 0, option_w+20, 30);
664                         rect += m_topleft_client + v2s32(option_x+175, option_y+20*3);
665                         Environment->addCheckBox(m_data->trilinear_filter, rect, this,
666                                        GUI_ID_TRILINEAR_CB, wgettext("Tri-Linear Filtering"));
667                 }
668
669                 // shader/on demand image loading/particles settings
670                 {
671                         core::rect<s32> rect(0, 0, option_w+20, 30);
672                         rect += m_topleft_client + v2s32(option_x+175*2, option_y);
673                         Environment->addCheckBox(m_data->enable_shaders, rect, this,
674                                         GUI_ID_SHADERS_CB, wgettext("Shaders"));
675                 }
676
677                 {
678                         core::rect<s32> rect(0, 0, option_w+20+20, 30);
679                         rect += m_topleft_client + v2s32(option_x+175*2, option_y+20);
680                         Environment->addCheckBox(m_data->preload_item_visuals, rect, this,
681                                         GUI_ID_PRELOAD_ITEM_VISUALS_CB, wgettext("Preload item visuals"));
682                 }
683
684                 {
685                         core::rect<s32> rect(0, 0, option_w+20+20, 30);
686                         rect += m_topleft_client + v2s32(option_x+175*2, option_y+20*2);
687                         Environment->addCheckBox(m_data->enable_particles, rect, this,
688                                         GUI_ID_ENABLE_PARTICLES_CB, wgettext("Enable Particles"));
689                 }
690
691                 // Key change button
692                 {
693                         core::rect<s32> rect(0, 0, 120, 30);
694                         /*rect += m_topleft_client + v2s32(m_size_client.X-120-30,
695                                         m_size_client.Y-30-20);*/
696                         rect += m_topleft_client + v2s32(option_x, option_y+120);
697                         Environment->addButton(rect, this,
698                                         GUI_ID_CHANGE_KEYS_BUTTON, wgettext("Change keys"));
699                 }
700                 changeCtype("C");
701         }
702         else if(m_data->selected_tab == TAB_CREDITS)
703         {
704                 // CREDITS
705                 {
706                         core::rect<s32> rect(0, 0, 10, m_size_client.Y);
707                         rect += m_topleft_client + v2s32(15, 0);
708                         const wchar_t *text = L"C\nR\nE\nD\nI\nT\nS";
709                         gui::IGUIStaticText *t =
710                         Environment->addStaticText(text, rect, false, true, this, -1);
711                         t->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_CENTER);
712                 }
713                 {
714                         core::rect<s32> rect(0, 0, 454, 250);
715                         rect += m_topleft_client + v2s32(110, 50+35);
716                         Environment->addStaticText(narrow_to_wide(
717                         "Minetest " VERSION_STRING "\n"
718                         "http://minetest.net/\n"
719                         "\n"
720                         "by Perttu Ahola <celeron55@gmail.com>\n"
721                         "and contributors: PilzAdam, Taoki, tango_, kahrl (kaaaaaahrl?), darkrose, matttpt, erlehmann, SpeedProg, JacobF, teddydestodes, marktraceur, Jonathan Neuschäfer, thexyz, VanessaE, sfan5... and tens of more random people."
722                         ).c_str(), rect, false, true, this, -1);
723                 }
724         }
725
726         m_is_regenerating = false;
727 }
728
729 void GUIMainMenu::drawMenu()
730 {
731         gui::IGUISkin* skin = Environment->getSkin();
732         if (!skin)
733                 return;
734         video::IVideoDriver* driver = Environment->getVideoDriver();
735         
736         /*video::SColor bgcolor(140,0,0,0);
737         driver->draw2DRectangle(bgcolor, AbsoluteRect, &AbsoluteClippingRect);*/
738
739         video::SColor bgcolor(140,0,0,0);
740
741         if(getTab() == TAB_SINGLEPLAYER)
742         {
743                 {
744                         core::rect<s32> rect(0, 0, m_size_client.X, m_size_client.Y);
745                         rect += AbsoluteRect.UpperLeftCorner + m_topleft_client;
746                         driver->draw2DRectangle(bgcolor, rect, &AbsoluteClippingRect);
747                 }
748         }
749         else if(getTab() == TAB_MULTIPLAYER)
750         {
751                 {
752                         core::rect<s32> rect(0, 0, m_size_client.X, m_size_client.Y);
753                         rect += AbsoluteRect.UpperLeftCorner + m_topleft_client;
754                         driver->draw2DRectangle(bgcolor, rect, &AbsoluteClippingRect);
755                 }
756         }
757         else if(getTab() == TAB_ADVANCED)
758         {
759                 {
760                         core::rect<s32> rect(0, 0, m_size_client.X, m_size_client.Y);
761                         rect += AbsoluteRect.UpperLeftCorner + m_topleft_client;
762                         driver->draw2DRectangle(bgcolor, rect, &AbsoluteClippingRect);
763                 }
764                 {
765                         core::rect<s32> rect(0, 0, m_size_server.X, m_size_server.Y);
766                         rect += AbsoluteRect.UpperLeftCorner + m_topleft_server;
767                         driver->draw2DRectangle(bgcolor, rect, &AbsoluteClippingRect);
768                 }
769         }
770         else if(getTab() == TAB_SETTINGS)
771         {
772                 {
773                         core::rect<s32> rect(0, 0, m_size_client.X, m_size_client.Y);
774                         rect += AbsoluteRect.UpperLeftCorner + m_topleft_client;
775                         driver->draw2DRectangle(bgcolor, rect, &AbsoluteClippingRect);
776                 }
777         }
778         else if(getTab() == TAB_CREDITS)
779         {
780                 {
781                         core::rect<s32> rect(0, 0, m_size_client.X, m_size_client.Y);
782                         rect += AbsoluteRect.UpperLeftCorner + m_topleft_client;
783                         driver->draw2DRectangle(bgcolor, rect, &AbsoluteClippingRect);
784                 }
785                 video::ITexture *logotexture =
786                                 driver->getTexture(getTexturePath("logo.png").c_str());
787                 if(logotexture)
788                 {
789                         v2s32 logosize(logotexture->getOriginalSize().Width,
790                                         logotexture->getOriginalSize().Height);
791
792                         core::rect<s32> rect(0,0,logosize.X,logosize.Y);
793                         rect += AbsoluteRect.UpperLeftCorner + m_topleft_client;
794                         rect += v2s32(500, 30);
795                         driver->draw2DImage(logotexture, rect,
796                                 core::rect<s32>(core::position2d<s32>(0,0),
797                                 core::dimension2di(logotexture->getSize())),
798                                 NULL, NULL, true);
799                 }
800         }
801
802         gui::IGUIElement::draw();
803 }
804
805 void GUIMainMenu::readInput(MainMenuData *dst)
806 {
807         {
808                 gui::IGUIElement *e = getElementFromId(GUI_ID_TAB_CONTROL);
809                 if(e != NULL && e->getType() == gui::EGUIET_TAB_CONTROL)
810                         dst->selected_tab = ((gui::IGUITabControl*)e)->getActiveTab();
811         }
812         if(dst->selected_tab == TAB_SINGLEPLAYER)
813         {
814                 dst->simple_singleplayer_mode = true;
815         }
816         else
817         {
818                 dst->simple_singleplayer_mode = false;
819                 {
820                         gui::IGUIElement *e = getElementFromId(GUI_ID_NAME_INPUT);
821                         if(e != NULL)
822                                 dst->name = e->getText();
823                 }
824                 {
825                         gui::IGUIElement *e = getElementFromId(264);
826                         if(e != NULL)
827                                 dst->password = e->getText();
828                 }
829                 {
830                         gui::IGUIElement *e = getElementFromId(GUI_ID_ADDRESS_INPUT);
831                         if(e != NULL)
832                                 dst->address = e->getText();
833                 }
834                 {
835                         gui::IGUIElement *e = getElementFromId(GUI_ID_PORT_INPUT);
836                         if(e != NULL)
837                                 dst->port = e->getText();
838                 }
839         }
840         {
841                 gui::IGUIElement *e = getElementFromId(GUI_ID_CREATIVE_CB);
842                 if(e != NULL && e->getType() == gui::EGUIET_CHECK_BOX)
843                         dst->creative_mode = ((gui::IGUICheckBox*)e)->isChecked();
844         }
845         {
846                 gui::IGUIElement *e = getElementFromId(GUI_ID_DAMAGE_CB);
847                 if(e != NULL && e->getType() == gui::EGUIET_CHECK_BOX)
848                         dst->enable_damage = ((gui::IGUICheckBox*)e)->isChecked();
849         }
850         {
851                 gui::IGUIElement *e = getElementFromId(GUI_ID_PUBLIC_CB);
852                 if(e != NULL && e->getType() == gui::EGUIET_CHECK_BOX)
853                         dst->enable_public = ((gui::IGUICheckBox*)e)->isChecked();
854         }
855         {
856                 gui::IGUIElement *e = getElementFromId(GUI_ID_FANCYTREE_CB);
857                 if(e != NULL && e->getType() == gui::EGUIET_CHECK_BOX)
858                         dst->fancy_trees = ((gui::IGUICheckBox*)e)->isChecked();
859         }
860         {
861                 gui::IGUIElement *e = getElementFromId(GUI_ID_SMOOTH_LIGHTING_CB);
862                 if(e != NULL && e->getType() == gui::EGUIET_CHECK_BOX)
863                         dst->smooth_lighting = ((gui::IGUICheckBox*)e)->isChecked();
864         }
865         {
866                 gui::IGUIElement *e = getElementFromId(GUI_ID_3D_CLOUDS_CB);
867                 if(e != NULL && e->getType() == gui::EGUIET_CHECK_BOX)
868                         dst->clouds_3d = ((gui::IGUICheckBox*)e)->isChecked();
869         }
870         {
871                 gui::IGUIElement *e = getElementFromId(GUI_ID_OPAQUE_WATER_CB);
872                 if(e != NULL && e->getType() == gui::EGUIET_CHECK_BOX)
873                         dst->opaque_water = ((gui::IGUICheckBox*)e)->isChecked();
874         }
875
876         {
877                 gui::IGUIElement *e = getElementFromId(GUI_ID_MIPMAP_CB);
878                 if(e != NULL && e->getType() == gui::EGUIET_CHECK_BOX)
879                         dst->mip_map = ((gui::IGUICheckBox*)e)->isChecked();
880         }
881
882         {
883                 gui::IGUIElement *e = getElementFromId(GUI_ID_ANISOTROPIC_CB);
884                 if(e != NULL && e->getType() == gui::EGUIET_CHECK_BOX)
885                         dst->anisotropic_filter = ((gui::IGUICheckBox*)e)->isChecked();
886         }
887
888         {
889                 gui::IGUIElement *e = getElementFromId(GUI_ID_BILINEAR_CB);
890                 if(e != NULL && e->getType() == gui::EGUIET_CHECK_BOX)
891                         dst->bilinear_filter = ((gui::IGUICheckBox*)e)->isChecked();
892         }
893
894         {
895                 gui::IGUIElement *e = getElementFromId(GUI_ID_TRILINEAR_CB);
896                 if(e != NULL && e->getType() == gui::EGUIET_CHECK_BOX)
897                         dst->trilinear_filter = ((gui::IGUICheckBox*)e)->isChecked();
898         }
899
900         {
901                 gui::IGUIElement *e = getElementFromId(GUI_ID_SHADERS_CB);
902                 if(e != NULL && e->getType() == gui::EGUIET_CHECK_BOX)
903                         dst->enable_shaders = ((gui::IGUICheckBox*)e)->isChecked() ? 2 : 0;
904         }
905
906         {
907                 gui::IGUIElement *e = getElementFromId(GUI_ID_PRELOAD_ITEM_VISUALS_CB);
908                 if(e != NULL && e->getType() == gui::EGUIET_CHECK_BOX)
909                         dst->preload_item_visuals = ((gui::IGUICheckBox*)e)->isChecked();
910         }
911
912         {
913                 gui::IGUIElement *e = getElementFromId(GUI_ID_ENABLE_PARTICLES_CB);
914                 if(e != NULL && e->getType() == gui::EGUIET_CHECK_BOX)
915                         dst->enable_particles = ((gui::IGUICheckBox*)e)->isChecked();
916         }
917
918         {
919                 gui::IGUIElement *e = getElementFromId(GUI_ID_WORLD_LISTBOX);
920                 if(e != NULL && e->getType() == gui::EGUIET_LIST_BOX)
921                         dst->selected_world = ((gui::IGUIListBox*)e)->getSelected();
922         }
923         {
924                 ServerListSpec server =
925                 getServerListSpec(wide_to_narrow(dst->address), wide_to_narrow(dst->port));
926                 dst->servername = server["name"].asString();
927                 dst->serverdescription = server["description"].asString();
928         }
929 }
930
931 void GUIMainMenu::acceptInput()
932 {
933         readInput(m_data);
934         m_accepted = true;
935 }
936
937 bool GUIMainMenu::OnEvent(const SEvent& event)
938 {
939         if(event.EventType==EET_KEY_INPUT_EVENT)
940         {
941                 if(event.KeyInput.Key==KEY_ESCAPE && event.KeyInput.PressedDown)
942                 {
943                         m_gamecallback->exitToOS();
944                         quitMenu();
945                         return true;
946                 }
947                 if(event.KeyInput.Key==KEY_RETURN && event.KeyInput.PressedDown)
948                 {
949                         acceptInput();
950                         quitMenu();
951                         return true;
952                 }
953         }
954         if(event.EventType==EET_GUI_EVENT)
955         {
956                 if(event.GUIEvent.EventType==gui::EGET_ELEMENT_FOCUS_LOST
957                                 && isVisible())
958                 {
959                         if(!canTakeFocus(event.GUIEvent.Element))
960                         {
961                                 dstream<<"GUIMainMenu: Not allowing focus change."
962                                                 <<std::endl;
963                                 // Returning true disables focus change
964                                 return true;
965                         }
966                 }
967                 if(event.GUIEvent.EventType==gui::EGET_TAB_CHANGED)
968                 {
969                         if(!m_is_regenerating)
970                                 regenerateGui(m_screensize_old);
971                         return true;
972                 }
973                 if(event.GUIEvent.EventType==gui::EGET_LISTBOX_CHANGED && event.GUIEvent.Caller->getID() == GUI_ID_SERVERLIST)
974                 {
975                         serverListOnSelected();
976                         return true;
977                 }
978                 if(event.GUIEvent.EventType==gui::EGET_BUTTON_CLICKED)
979                 {
980                         switch(event.GUIEvent.Caller->getID())
981                         {
982                         case GUI_ID_JOIN_GAME_BUTTON: {
983                                 MainMenuData cur;
984                                 readInput(&cur);
985                                 if (getTab() == TAB_MULTIPLAYER && cur.address == L"")
986                                 {
987                                         (new GUIMessageMenu(env, parent, -1, menumgr,
988                                                         wgettext("Address required."))
989                                                         )->drop();
990                                         return true;
991                                 }
992                                 acceptInput();
993                                 quitMenu();
994                                 return true;
995                         }
996                         case GUI_ID_CHANGE_KEYS_BUTTON: {
997                                 GUIKeyChangeMenu *kmenu = new GUIKeyChangeMenu(env, parent, -1,menumgr);
998                                 kmenu->drop();
999                                 return true;
1000                         }
1001                         case GUI_ID_DELETE_WORLD_BUTTON: {
1002                                 MainMenuData cur;
1003                                 readInput(&cur);
1004                                 if(cur.selected_world == -1){
1005                                         (new GUIMessageMenu(env, parent, -1, menumgr,
1006                                                         wgettext("Cannot delete world: Nothing selected"))
1007                                                         )->drop();
1008                                 } else {
1009                                         WorldSpec spec = m_data->worlds[cur.selected_world];
1010                                         // Get files and directories involved
1011                                         std::vector<std::string> paths;
1012                                         paths.push_back(spec.path);
1013                                         fs::GetRecursiveSubPaths(spec.path, paths);
1014                                         // Launch confirmation dialog
1015                                         ConfirmDestDeleteWorld *dest = new
1016                                                         ConfirmDestDeleteWorld(spec, this, paths);
1017                                         std::wstring text = wgettext("Delete world");
1018                                         text += L" \"";
1019                                         text += narrow_to_wide(spec.name);
1020                                         text += L"\"?\n\n";
1021                                         text += wgettext("Files to be deleted");
1022                                         text += L":\n";
1023                                         for(u32 i=0; i<paths.size(); i++){
1024                                                 if(i == 3){ text += L"..."; break; }
1025                                                 text += narrow_to_wide(paths[i]) + L"\n";
1026                                         }
1027                                         (new GUIConfirmMenu(env, parent, -1, menumgr, dest,
1028                                                         text.c_str()))->drop();
1029                                 }
1030                                 return true;
1031                         }
1032                         case GUI_ID_CREATE_WORLD_BUTTON: {
1033                                 std::vector<SubgameSpec> games = getAvailableGames();
1034                                 if(games.size() == 0){
1035                                         GUIMessageMenu *menu = new GUIMessageMenu(env, parent,
1036                                                         -1, menumgr,
1037                                                         wgettext("Cannot create world: No games found"));
1038                                         menu->drop();
1039                                 } else {
1040                                         CreateWorldDest *dest = new CreateWorldDestMainMenu(this);
1041                                         GUICreateWorld *menu = new GUICreateWorld(env, parent, -1,
1042                                                         menumgr, dest, games);
1043                                         menu->drop();
1044                                 }
1045                                 return true;
1046                         }
1047                         case GUI_ID_CONFIGURE_WORLD_BUTTON: {
1048                                 MainMenuData cur;
1049                                 readInput(&cur);
1050                                 if(cur.selected_world == -1)
1051                                 {
1052                                         (new GUIMessageMenu(env, parent, -1, menumgr,
1053                                                         wgettext("Cannot configure world: Nothing selected"))
1054                                                         )->drop();
1055                                 } 
1056                                 else 
1057                                 {
1058                                         WorldSpec wspec = m_data->worlds[cur.selected_world];
1059                                         GUIConfigureWorld *menu = new GUIConfigureWorld(env, parent,
1060                                                                                 -1, menumgr, wspec);
1061                                         menu->drop();
1062                                 }
1063                                 return true;
1064                         }
1065                         case GUI_ID_SERVERLIST_DELETE: {
1066                                 gui::IGUIListBox *serverlist = (gui::IGUIListBox*)getElementFromId(GUI_ID_SERVERLIST);
1067                                 s32 selected = ((gui::IGUIListBox*)serverlist)->getSelected();
1068                                 if (selected == -1) return true;
1069                                 ServerList::deleteEntry(m_data->servers[selected]);
1070                                 m_data->servers = ServerList::getLocal();
1071                                 updateGuiServerList();
1072                                 if (selected > 0)
1073                                         selected -= 1;
1074                                 serverlist->setSelected(selected);
1075                                 serverListOnSelected();
1076                                 return true;
1077                         }
1078                         #if USE_CURL
1079                         case GUI_ID_SERVERLIST_TOGGLE: {
1080                                 gui::IGUIElement *togglebutton = getElementFromId(GUI_ID_SERVERLIST_TOGGLE);
1081                                 gui::IGUIElement *deletebutton = getElementFromId(GUI_ID_SERVERLIST_DELETE);
1082                                 gui::IGUIListBox *serverlist = (gui::IGUIListBox*)getElementFromId(GUI_ID_SERVERLIST);
1083                                 if (m_data->serverlist_show_available) // switch to favorite list
1084                                 {
1085                                         m_data->servers = ServerList::getLocal();
1086                                         togglebutton->setText(wgettext("Show Public"));
1087                                         deletebutton->setVisible(true);
1088                                         updateGuiServerList();
1089                                         serverlist->setSelected(0);
1090                                 }
1091                                 else // switch to online list
1092                                 {
1093                                         m_data->servers = ServerList::getOnline();
1094                                         togglebutton->setText(wgettext("Show Favorites"));
1095                                         deletebutton->setVisible(false);
1096                                         updateGuiServerList();
1097                                         serverlist->setSelected(0);
1098                                 }
1099                                 serverListOnSelected();
1100
1101                                 m_data->serverlist_show_available = !m_data->serverlist_show_available;
1102                         }
1103                         #endif
1104                         }
1105                 }
1106                 if(event.GUIEvent.EventType==gui::EGET_EDITBOX_ENTER)
1107                 {
1108                         switch(event.GUIEvent.Caller->getID())
1109                         {
1110                                 case GUI_ID_ADDRESS_INPUT: case GUI_ID_PORT_INPUT: case GUI_ID_NAME_INPUT: case 264:
1111                                 acceptInput();
1112                                 quitMenu();
1113                                 return true;
1114                         }
1115                 }
1116                 if(event.GUIEvent.EventType==gui::EGET_LISTBOX_SELECTED_AGAIN)
1117                 {
1118                         switch(event.GUIEvent.Caller->getID())
1119                         {
1120                         case GUI_ID_WORLD_LISTBOX:
1121                                 acceptInput();
1122                                 if(getTab() != TAB_SINGLEPLAYER)
1123                                         m_data->address = L""; // Force local game
1124                                 quitMenu();
1125                                 return true;
1126                         case GUI_ID_SERVERLIST:
1127                                 gui::IGUIListBox *serverlist = (gui::IGUIListBox*)getElementFromId(GUI_ID_SERVERLIST);
1128                                 if (serverlist->getSelected() > -1)
1129                                 {
1130                                         acceptInput();
1131                                         quitMenu();
1132                                         return true;
1133                                 }
1134                         }
1135                 }
1136         }
1137
1138         return Parent ? Parent->OnEvent(event) : false;
1139 }
1140
1141 void GUIMainMenu::createNewWorld(std::wstring name, std::string gameid)
1142 {
1143         if(name == L"")
1144                 return;
1145         acceptInput();
1146         m_data->create_world_name = name;
1147         m_data->create_world_gameid = gameid;
1148         quitMenu();
1149 }
1150
1151 void GUIMainMenu::deleteWorld(const std::vector<std::string> &paths)
1152 {
1153         // Delete files
1154         bool did = fs::DeletePaths(paths);
1155         if(!did){
1156                 GUIMessageMenu *menu = new GUIMessageMenu(env, parent,
1157                                 -1, menumgr, wgettext("Failed to delete all world files"));
1158                 menu->drop();
1159         }
1160         // Quit menu to refresh it
1161         acceptInput();
1162         m_data->only_refresh = true;
1163         quitMenu();
1164 }
1165         
1166 int GUIMainMenu::getTab()
1167 {
1168         gui::IGUIElement *e = getElementFromId(GUI_ID_TAB_CONTROL);
1169         if(e != NULL && e->getType() == gui::EGUIET_TAB_CONTROL)
1170                 return ((gui::IGUITabControl*)e)->getActiveTab();
1171         return TAB_SINGLEPLAYER; // Default
1172 }
1173
1174 void GUIMainMenu::displayMessageMenu(std::wstring msg)
1175 {
1176         (new GUIMessageMenu(env, parent, -1, menumgr, msg))->drop();
1177 }
1178
1179 void GUIMainMenu::updateGuiServerList()
1180 {
1181         gui::IGUIListBox *serverlist = (gui::IGUIListBox *)getElementFromId(GUI_ID_SERVERLIST);
1182         serverlist->clear();
1183
1184         for(std::vector<ServerListSpec>::iterator i = m_data->servers.begin();
1185                 i != m_data->servers.end(); i++)
1186         {
1187                 std::string text;
1188
1189                 if ((*i)["clients"].asString().size())
1190                         text += (*i)["clients"].asString();
1191                 if ((*i)["clients_max"].asString().size())
1192                         text += "/" + (*i)["clients_max"].asString();
1193                 text += " ";
1194                 if ((*i)["version"].asString().size())
1195                         text += (*i)["version"].asString() + " ";
1196                 if ((*i)["password"].asString().size())
1197                         text += "*";
1198                 if ((*i)["creative"].asString().size())
1199                         text += "C";
1200                 if ((*i)["damage"].asString().size())
1201                         text += "D";
1202                 if ((*i)["pvp"].asString().size())
1203                         text += "P";
1204                 text += " ";
1205
1206                 if ((*i)["name"] != "" && (*i)["description"] != "")
1207                         text += (*i)["name"].asString() + " (" +  (*i)["description"].asString() + ")";
1208                 else if ((*i)["name"] !="")
1209                         text += (*i)["name"].asString();
1210                 else
1211                         text += (*i)["address"].asString() + ":" + (*i)["port"].asString();
1212                 
1213                 serverlist->addItem(narrow_to_wide(text).c_str());
1214         }
1215 }
1216
1217 void GUIMainMenu::serverListOnSelected()
1218 {
1219         if (!m_data->servers.empty())
1220         {
1221                 gui::IGUIListBox *serverlist = (gui::IGUIListBox*)getElementFromId(GUI_ID_SERVERLIST);
1222                 u16 id = serverlist->getSelected();
1223                 //if (id < 0) return; // u16>0!
1224                 ((gui::IGUIEditBox*)getElementFromId(GUI_ID_ADDRESS_INPUT))
1225                 ->setText(narrow_to_wide(m_data->servers[id]["address"].asString()).c_str());
1226                 ((gui::IGUIEditBox*)getElementFromId(GUI_ID_PORT_INPUT))
1227                 ->setText(narrow_to_wide(m_data->servers[id]["port"].asString()).c_str());
1228         }
1229 }
1230
1231 ServerListSpec GUIMainMenu::getServerListSpec(std::string address, std::string port)
1232 {
1233         ServerListSpec server;
1234         server["address"] = address;
1235         server["port"] = port;
1236         for(std::vector<ServerListSpec>::iterator i = m_data->servers.begin();
1237                 i != m_data->servers.end(); i++)
1238         {
1239                 if ((*i)["address"] == address && (*i)["port"] == port)
1240                 {
1241                         server["description"] = (*i)["description"];
1242                         server["name"] = (*i)["name"];
1243                         break;
1244                 }
1245         }
1246         return server;
1247 }