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