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