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