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