]> git.lizzy.rs Git - minetest.git/blobdiff - src/main.cpp
Merge pull request #13 from Bahamada/upstream_merge
[minetest.git] / src / main.cpp
index edfbc11c3f37aa935b9d3b190766ec4c55e634cc..41da310f450344af0c99b48f3ad6c32c8cc31e76 100644 (file)
@@ -1,6 +1,6 @@
 /*\r
 Minetest-c55\r
-Copyright (C) 2010 celeron55, Perttu Ahola <celeron55@gmail.com>\r
+Copyright (C) 2010-2011 celeron55, Perttu Ahola <celeron55@gmail.com>\r
 \r
 This program is free software; you can redistribute it and/or modify\r
 it under the terms of the GNU General Public License as published by\r
@@ -27,10 +27,8 @@ NOTE: Global locale is now set at initialization
 NOTE: If VBO (EHM_STATIC) is used, remember to explicitly free the\r
       hardware buffer (it is not freed automatically)\r
 \r
-Random suggeestions (AKA very old suggestions that haven't been done):\r
-----------------------------------------------------------------------\r
-\r
-SUGG: Fix address to be ipv6 compatible\r
+Old, wild and random suggestions that probably won't be done:\r
+-------------------------------------------------------------\r
 \r
 SUGG: If player is on ground, mainly fetch ground-level blocks\r
 \r
@@ -81,64 +79,26 @@ SUGG: Calculate lighting per vertex to get a lighting effect like in
 SUGG: Background music based on cellular automata?\r
       http://www.earslap.com/projectslab/otomata\r
 \r
-Storyline:\r
-----------\r
-NOTE: If you read the text below, PLEASE DON'T TELL ANYTHING ABOUT IT TO\r
-ANYONE, EVEN OF THE EXISTENCE OF IT. I WILL BE VERY DISAPPOINTED IF I SEE\r
-PEOPLE ON THE INTERNET TALKING ABOUT THIS AND IT WILL TAKE AT LEAST HALF\r
-OF MY MOTIVATION AWAY.\r
-\r
-At the beginning, there is a sky city (like in CT), in wich is a library\r
-(The Important Library), a part of which explodes. Unfortunately the\r
-magical Important Book in the library gets thrown out in the wind and flies\r
-far away to the dangerous Low Lands. The book is shown to glow in blue when\r
-flying in the wind in some animation, when the wind flies it to the\r
-horizon. It is early morning and quicky sunrise takes the place of the blue\r
-glow. This marks the direction where the book is.\r
-\r
-The rulers of the sky city choose to let some brave young men go and start\r
-a mission to get the book back. The rulers still have some magic so they\r
-can let them fall onto the ground without damage, but not further. When a\r
-new player spawns, he will just be an another missioner.\r
-\r
-The Low Lands are a very dangerous and a tough place to be in, but\r
-immediately underneath the sky city there is fairly peaceful, but sometimes\r
-dangerous creatures come there too, especially at night.\r
-\r
-The far ancestors of the highlanders lived in the lowlands, but then they\r
-learned magic and went to live in the sky. They have really no idea and no\r
-tools to survive in the lowlands. One guy is known to have dropped down to\r
-the lowlands a long time ago, but it is not known if he survived.\r
-\r
-The missioners will have to find out how to survive in the lowlands by\r
-finding materials and crafting tools and weapons and armor and interesting\r
-items. As they build up their capabilities, they can go and explore the\r
-lowlands further.\r
-\r
-The main flying direction of the book is known from the beginning. The book\r
-will have ended up in anywhere, but quite far in any case. A few or ten\r
-kilometers probably.\r
-\r
-The book might just lie on the ground but usually some evil castle lord\r
-will have hidden it in his castle. There are fairly many peaceful people\r
-in the lowlands, and the missioners can talk to them. They will sometimes\r
-tell some rumours of the book. "The Important Book? One guy going by told\r
-me it was seen falling from the highlands, probably towards the town of\r
-Clystaleon." (eh, just a random name I just made up)\r
-\r
-The map would of course be generated randomly, with some small towns and\r
-roads. Roads will occasionally have some road signs.\r
-\r
-But of course there will be monsters, especially at night. At the location\r
-of the book, there will usually be very little chance to survive without\r
-diamond armor and weapons, at least when the book has been stored by the\r
-evil castle lord. Useful rare minerals and items will be found only in\r
-areas of dangerous monsters.\r
-\r
-There is a blue glow coming from the book, which is a blue circle with a\r
-radius of 30m, and which is seen at a distance of 50 to 100m.\r
-\r
-When found, the book has to be transported back to beneath the sky city.\r
+SUGG: Simple light color information to air\r
+\r
+SUGG: Server-side objects could be moved based on nodes to enable very\r
+      lightweight operation and simple AI\r
+       - Not practical; client would still need to show smooth movement.\r
+\r
+SUGG: Make a system for pregenerating quick information for mapblocks, so\r
+         that the client can show them as cubes before they are actually sent\r
+         or even generated.\r
+\r
+SUGG: Erosion simulation at map generation time\r
+       - Simulate water flows, which would carve out dirt fast and\r
+         then turn stone into gravel and sand and relocate it.\r
+       - How about relocating minerals, too? Coal and gold in\r
+         downstream sand and gravel would be kind of cool\r
+         - This would need a better way of handling minerals, mainly\r
+               to have mineral content as a separate field. the first\r
+               parameter field is free for this.\r
+       - Simulate rock falling from cliffs when water has removed\r
+         enough solid rock from the bottom\r
 \r
 Gaming ideas:\r
 -------------\r
@@ -194,12 +154,10 @@ Build system / running:
 Networking and serialization:\r
 -----------------------------\r
 \r
-TODO: Get rid of GotSplitPacketException\r
-\r
-GUI:\r
-----\r
+SUGG: Fix address to be ipv6 compatible\r
 \r
-TODO: Configuration menu, at least for keys\r
+User Interface:\r
+---------------\r
 \r
 Graphics:\r
 ---------\r
@@ -225,12 +183,15 @@ TODO: A setting for enabling bilinear filtering for textures
 \r
 TODO: Better control of draw_control.wanted_max_blocks\r
 \r
-TODO: Get player texture (and some others) from the specified texture\r
-      directory\r
+TODO: Further investigate the use of GPU lighting in addition to the\r
+      current one\r
 \r
-SUGG: Simple light color information to air\r
+TODO: Artificial (night) light could be more yellow colored than sunlight.\r
+      - This is technically doable.\r
+         - Also the actual colors of the textures could be made less colorful\r
+           in the dark but it's a bit more difficult.\r
 \r
-TODO: Block mesh generator to tile properly on smooth lighting\r
+SUGG: Somehow make the night less colorful\r
 \r
 Configuration:\r
 --------------\r
@@ -256,6 +217,9 @@ TODO: Don't update all meshes always on single node changes, but
 \r
 FIXME: When disconnected to the menu, memory is not freed properly\r
 \r
+TODO: Investigate how much the mesh generator thread gets used when\r
+      transferring map data\r
+\r
 Server:\r
 -------\r
 \r
@@ -270,18 +234,65 @@ FIXME: Server sometimes goes into some infinite PeerNotFoundException loop
 * Make a small history check to transformLiquids to detect and log\r
   continuous oscillations, in such detail that they can be fixed.\r
 \r
+FIXME: The new optimized map sending doesn't sometimes send enough blocks\r
+       from big caves and such\r
+FIXME: Block send distance configuration does not take effect for some reason\r
+\r
+TODO: Map saving should be done by EmergeThread\r
+\r
+SUGG: Map unloading based on sector reference is not very good, it keeps\r
+       unnecessary stuff in memory. I guess. Investigate this.\r
+\r
+TODO: When block is placed and it has param_type==CPT_FACEDIR_SIMPLE, set\r
+      the direction accordingly.\r
+\r
+Environment:\r
+------------\r
+\r
+TODO: A list of "active blocks" in which stuff happens. (+=done)\r
+       + Add a never-resetted game timer to the server\r
+       + Add a timestamp value to blocks\r
+       + The simple rule: All blocks near some player are "active"\r
+       - Do stuff in real time in active blocks\r
+               + Handle objects\r
+               TODO: Make proper hooks in here\r
+               - Grow grass, delete leaves without a tree\r
+               - Spawn some mobs based on some rules\r
+               - Transform cobble to mossy cobble near water\r
+               - Run a custom script\r
+               - ...And all kinds of other dynamic stuff\r
+       + Keep track of when a block becomes active and becomes inactive\r
+       + When a block goes inactive:\r
+               + Store objects statically to block\r
+               + Store timer value as the timestamp\r
+       + When a block goes active:\r
+               + Create active objects out of static objects\r
+               TODO: Make proper hooks in here\r
+               - Simulate the results of what would have happened if it would have\r
+                 been active for all the time\r
+                       - Grow a lot of grass and so on\r
+       + Initially it is fine to send information about every active object\r
+         to every player. Eventually it should be modified to only send info\r
+         about the nearest ones.\r
+               + This was left to be done by the old system and it sends only the\r
+                 nearest ones.\r
+\r
 Objects:\r
 --------\r
 \r
-TODO: Get rid of MapBlockObjects and use ActiveObjects\r
+TODO: Get rid of MapBlockObjects and use only ActiveObjects\r
+       - Skipping the MapBlockObject data is nasty - there is no "total\r
+         length" stored; have to make a SkipMBOs function which contains\r
+         enough of the current code to skip them properly.\r
 \r
 SUGG: MovingObject::move and Player::move are basically the same.\r
       combine them.\r
-         - NOTE: Player::move is more up-to-date.\r
-         - NOTE: There is a simple move implementation now in collision.{h,cpp}\r
+       - NOTE: Player::move is more up-to-date.\r
+       - NOTE: There is a simple move implementation now in collision.{h,cpp}\r
+       - NOTE: MovingObject will be deleted (MapBlockObject)\r
 \r
-SUGG: Server-side objects could be moved based on nodes to enable very\r
-      lightweight operation and simple AI\r
+TODO: Add a long step function to objects that is called with the time\r
+      difference when block activates\r
 \r
 Map:\r
 ----\r
@@ -289,25 +300,15 @@ SUGG: Server-side objects could be moved based on nodes to enable very
 TODO: Mineral and ground material properties\r
       - This way mineral ground toughness can be calculated with just\r
            some formula, as well as tool strengths\r
+         - There are TODOs in appropriate files: material.h, content_mapnode.h\r
 \r
 TODO: Flowing water to actually contain flow direction information\r
       - There is a space for this - it just has to be implemented.\r
 \r
-SUGG: Erosion simulation at map generation time\r
-       - Simulate water flows, which would carve out dirt fast and\r
-         then turn stone into gravel and sand and relocate it.\r
-       - How about relocating minerals, too? Coal and gold in\r
-         downstream sand and gravel would be kind of cool\r
-         - This would need a better way of handling minerals, mainly\r
-               to have mineral content as a separate field. the first\r
-               parameter field is free for this.\r
-       - Simulate rock falling from cliffs when water has removed\r
-         enough solid rock from the bottom\r
-\r
 SUGG: Try out the notch way of generating maps, that is, make bunches\r
       of low-res 3d noise and interpolate linearly.\r
 \r
-Mapgen v2:\r
+Mapgen v2 (the current one):\r
 * Possibly add some kind of erosion and other stuff\r
 * Better water generation (spread it to underwater caverns but don't\r
   fill dungeons that don't touch big water masses)\r
@@ -316,21 +317,66 @@ Mapgen v2:
   the other chunk making nasty straight walls when the other chunk\r
   is generated. Fix it. Maybe just a special case if the ground is\r
   flat?\r
+* Consider not updating this one and make a good mainly block-based\r
+  generator\r
+\r
+SUGG: Make two "modified states", one that forces the block to be saved at\r
+       the next save event, and one that makes the block to be saved at exit\r
+       time.\r
+\r
+TODO: Add a not_fully_generated flag to MapBlock, which would be set for\r
+       blocks that contain eg. trees from neighboring generations but haven't\r
+       been generated itself. This is required for the future generator.\r
 \r
 Misc. stuff:\r
 ------------\r
-* Make an "environment metafile" to store at least time of day\r
-* Move digging property stuff from material.{h,cpp} to mapnode.cpp...\r
-  - Or maybe move content_features to material.{h,cpp}?\r
-* Maybe:\r
-  Make a system for pregenerating quick information for mapblocks, so\r
-  that the client can show them as cubes before they are actually sent\r
-  or even generated.\r
+- Make sure server handles removing grass when a block is placed (etc)\r
+    - The client should not do it by itself\r
+- Block cube placement around player's head\r
+- Protocol version field\r
+- Consider getting some textures from cisoun's texture pack\r
+       - Ask from Cisoun\r
+- Make sure the fence implementation and data format is good\r
+       - Think about using same bits for material for fences and doors, for\r
+       example\r
+- Finish the ActiveBlockModifier stuff and use it for something\r
+- Move mineral to param2, increment map serialization version, add conversion\r
+\r
+TODO: Add a per-sector database to store surface stuff as simple flags/values\r
+      - Light?\r
+         - A building?\r
+         And at some point make the server send this data to the client too,\r
+         instead of referring to the noise functions\r
+         - Ground height\r
+         - Surface ground type\r
+         - Trees?\r
+\r
+TODO: Restart irrlicht completely when coming back to main menu from game.\r
+       - This gets rid of everything that is stored in irrlicht's caches.\r
+\r
+TODO: Merge bahamada's audio stuff (clean patch available)\r
+\r
+TODO: Merge spongie's chest/furnace direction (by hand)\r
+\r
+TODO: Merge key configuration menu (no clean patch available)\r
 \r
 Making it more portable:\r
 ------------------------\r
-* Some MSVC: std::sto* are defined without a namespace and collide\r
-  with the ones in utility.h\r
\r
+Stuff to do before release:\r
+---------------------------\r
+\r
+Fixes to the current release:\r
+-----------------------------\r
+\r
+Stuff to do after release:\r
+---------------------------\r
+\r
+Doing currently:\r
+----------------\r
+\r
+TODO: Use MapBlock::resetUsageTimer() in appropriate places\r
+      (on client and server)\r
 \r
 ======================================================================\r
 \r
@@ -382,6 +428,7 @@ Making it more portable:
 //#include "tile.h"\r
 #include "materials.h"\r
 #include "game.h"\r
+#include "keycode.h"\r
 \r
 // This makes textures\r
 ITextureSource *g_texturesource = NULL;\r
@@ -395,6 +442,9 @@ Settings g_settings;
 // This is located in defaultsettings.cpp\r
 extern void set_default_settings();\r
 \r
+// Global profiler\r
+Profiler g_profiler;\r
+\r
 /*\r
        Random stuff\r
 */\r
@@ -445,7 +495,14 @@ std::ostream *derr_client_ptr = &dstream;
 class TimeGetter\r
 {\r
 public:\r
-       TimeGetter(IrrlichtDevice *device):\r
+       virtual u32 getTime() = 0;\r
+};\r
+\r
+// A precise irrlicht one\r
+class IrrlichtTimeGetter: public TimeGetter\r
+{\r
+public:\r
+       IrrlichtTimeGetter(IrrlichtDevice *device):\r
                m_device(device)\r
        {}\r
        u32 getTime()\r
@@ -457,8 +514,18 @@ class TimeGetter
 private:\r
        IrrlichtDevice *m_device;\r
 };\r
+// Not so precise one which works without irrlicht\r
+class SimpleTimeGetter: public TimeGetter\r
+{\r
+public:\r
+       u32 getTime()\r
+       {\r
+               return porting::getTimeMs();\r
+       }\r
+};\r
 \r
 // A pointer to a global instance of the time getter\r
+// TODO: why?\r
 TimeGetter *g_timegetter = NULL;\r
 \r
 u32 getTimeMs()\r
@@ -777,7 +844,8 @@ class RandomInputHandler : public InputHandler
                        if(counter1 < 0.0)\r
                        {\r
                                counter1 = 0.1*Rand(1, 40);\r
-                               keydown[irr::KEY_SPACE] = !keydown[irr::KEY_SPACE];\r
+                               keydown[getKeySetting("keymap_jump")] =\r
+                                               !keydown[getKeySetting("keymap_jump")];\r
                        }\r
                }\r
                {\r
@@ -786,7 +854,8 @@ class RandomInputHandler : public InputHandler
                        if(counter1 < 0.0)\r
                        {\r
                                counter1 = 0.1*Rand(1, 40);\r
-                               keydown[irr::KEY_KEY_E] = !keydown[irr::KEY_KEY_E];\r
+                               keydown[getKeySetting("keymap_special1")] =\r
+                                               !keydown[getKeySetting("keymap_special1")];\r
                        }\r
                }\r
                {\r
@@ -795,7 +864,8 @@ class RandomInputHandler : public InputHandler
                        if(counter1 < 0.0)\r
                        {\r
                                counter1 = 0.1*Rand(1, 40);\r
-                               keydown[irr::KEY_KEY_W] = !keydown[irr::KEY_KEY_W];\r
+                               keydown[getKeySetting("keymap_forward")] =\r
+                                               !keydown[getKeySetting("keymap_forward")];\r
                        }\r
                }\r
                {\r
@@ -804,7 +874,8 @@ class RandomInputHandler : public InputHandler
                        if(counter1 < 0.0)\r
                        {\r
                                counter1 = 0.1*Rand(1, 40);\r
-                               keydown[irr::KEY_KEY_A] = !keydown[irr::KEY_KEY_A];\r
+                               keydown[getKeySetting("keymap_left")] =\r
+                                               !keydown[getKeySetting("keymap_left")];\r
                        }\r
                }\r
                {\r
@@ -964,7 +1035,7 @@ void drawMenuBackground(video::IVideoDriver* driver)
        core::dimension2d<u32> screensize = driver->getScreenSize();\r
                \r
        video::ITexture *bgtexture =\r
-                       driver->getTexture(porting::getDataPath("mud.png").c_str());\r
+                       driver->getTexture(getTexturePath("mud.png").c_str());\r
        if(bgtexture)\r
        {\r
                s32 texturesize = 128;\r
@@ -984,7 +1055,7 @@ void drawMenuBackground(video::IVideoDriver* driver)
        }\r
        \r
        video::ITexture *logotexture =\r
-                       driver->getTexture(porting::getDataPath("menulogo.png").c_str());\r
+                       driver->getTexture(getTexturePath("menulogo.png").c_str());\r
        if(logotexture)\r
        {\r
                v2s32 logosize(logotexture->getOriginalSize().Width,\r
@@ -1008,6 +1079,15 @@ void drawMenuBackground(video::IVideoDriver* driver)
 \r
 int main(int argc, char *argv[])\r
 {\r
+       /*\r
+               Initialization\r
+       */\r
+\r
+       // Set locale. This is for forcing '.' as the decimal point.\r
+       std::locale::global(std::locale("C"));\r
+       // This enables printing all characters in bitmap font\r
+       setlocale(LC_CTYPE, "en_US");\r
+\r
        /*\r
                Parse command line\r
        */\r
@@ -1071,22 +1151,29 @@ int main(int argc, char *argv[])
                disable_stderr = true;\r
 #endif\r
 \r
-       // Initialize debug streams\r
-       debugstreams_init(disable_stderr, DEBUGFILE);\r
-       // Initialize debug stacks\r
-       debug_stacks_init();\r
-\r
-       DSTACK(__FUNCTION_NAME);\r
-\r
        porting::signal_handler_init();\r
        bool &kill = *porting::signal_handler_killstatus();\r
        \r
+       // Initialize porting::path_data and porting::path_userdata\r
        porting::initializePaths();\r
+\r
        // Create user data directory\r
        fs::CreateDir(porting::path_userdata);\r
        \r
-       // C-style stuff initialization\r
-       initializeMaterialProperties();\r
+       // Initialize debug streams\r
+#ifdef RUN_IN_PLACE\r
+       std::string debugfile = DEBUGFILE;\r
+#else\r
+       std::string debugfile = porting::path_userdata+"/"+DEBUGFILE;\r
+#endif\r
+       debugstreams_init(disable_stderr, debugfile.c_str());\r
+       // Initialize debug stacks\r
+       debug_stacks_init();\r
+\r
+       DSTACK(__FUNCTION_NAME);\r
+\r
+       // Init material properties table\r
+       //initializeMaterialProperties();\r
 \r
        // Debug handler\r
        BEGIN_DEBUG_EXCEPTION_HANDLER\r
@@ -1104,19 +1191,10 @@ int main(int argc, char *argv[])
        // Initialize default settings\r
        set_default_settings();\r
        \r
-       // Set locale. This is for forcing '.' as the decimal point.\r
-       std::locale::global(std::locale("C"));\r
-       // This enables printing all characters in bitmap font\r
-       setlocale(LC_CTYPE, "en_US");\r
-\r
        // Initialize sockets\r
        sockets_init();\r
        atexit(sockets_cleanup);\r
        \r
-       /*\r
-               Initialization\r
-       */\r
-\r
        /*\r
                Read config file\r
        */\r
@@ -1202,7 +1280,7 @@ int main(int argc, char *argv[])
                port = 30000;\r
        \r
        // Map directory\r
-       std::string map_dir = porting::path_userdata+"/map";\r
+       std::string map_dir = porting::path_userdata+"/world";\r
        if(cmd_args.exists("map-dir"))\r
                map_dir = cmd_args.get("map-dir");\r
        else if(g_settings.exists("map-dir"))\r
@@ -1213,6 +1291,9 @@ int main(int argc, char *argv[])
        {\r
                DSTACK("Dedicated server branch");\r
 \r
+               // Create time getter\r
+               g_timegetter = new SimpleTimeGetter();\r
+               \r
                // Create server\r
                Server server(map_dir.c_str());\r
                server.start(port);\r
@@ -1223,6 +1304,7 @@ int main(int argc, char *argv[])
                return 0;\r
        }\r
 \r
+\r
        /*\r
                More parameters\r
        */\r
@@ -1294,7 +1376,7 @@ int main(int argc, char *argv[])
        device = device;\r
        \r
        // Create time getter\r
-       g_timegetter = new TimeGetter(device);\r
+       g_timegetter = new IrrlichtTimeGetter(device);\r
        \r
        // Create game callback for menus\r
        g_gamecallback = new MainGameCallback(device);\r
@@ -1338,7 +1420,7 @@ int main(int argc, char *argv[])
 \r
        guienv = device->getGUIEnvironment();\r
        gui::IGUISkin* skin = guienv->getSkin();\r
-       gui::IGUIFont* font = guienv->getFont(porting::getDataPath("fontlucida.png").c_str());\r
+       gui::IGUIFont* font = guienv->getFont(getTexturePath("fontlucida.png").c_str());\r
        if(font)\r
                skin->setFont(font);\r
        else\r
@@ -1362,7 +1444,6 @@ int main(int argc, char *argv[])
                Preload some textures and stuff\r
        */\r
 \r
-       init_content_inventory_texture_paths();\r
        init_mapnode(); // Second call with g_texturesource set\r
        init_mineral();\r
 \r
@@ -1377,11 +1458,15 @@ int main(int argc, char *argv[])
        */\r
        std::wstring error_message = L"";\r
 \r
+       // The password entered during the menu screen,\r
+       std::string password;\r
+\r
        /*\r
                Menu-game loop\r
        */\r
        while(device->run() && kill == false)\r
        {\r
+\r
                // This is used for catching disconnects\r
                try\r
                {\r
@@ -1461,6 +1546,10 @@ int main(int argc, char *argv[])
                                        guienv->drawAll();\r
                                        \r
                                        driver->endScene();\r
+                                       \r
+                                       // On some computers framerate doesn't seem to be\r
+                                       // automatically limited\r
+                                       sleep_ms(25);\r
                                }\r
                                \r
                                // Break out of menu-game loop to shut down cleanly\r
@@ -1481,6 +1570,9 @@ int main(int argc, char *argv[])
                                }\r
 \r
                                playername = wide_to_narrow(menudata.name);\r
+\r
+                               password = translatePassword(playername, menudata.password);\r
+\r
                                address = wide_to_narrow(menudata.address);\r
                                int newport = stoi(wide_to_narrow(menudata.port));\r
                                if(newport != 0)\r
@@ -1490,13 +1582,22 @@ int main(int argc, char *argv[])
                                g_settings.set("creative_mode", itos(menudata.creative_mode));\r
                                g_settings.set("enable_damage", itos(menudata.enable_damage));\r
                                \r
-                               // Check for valid parameters, restart menu if invalid.\r
+                               // NOTE: These are now checked server side; no need to do it\r
+                               //       here, so let's not do it here.\r
+                               /*// Check for valid parameters, restart menu if invalid.\r
                                if(playername == "")\r
                                {\r
                                        error_message = L"Name required.";\r
                                        continue;\r
                                }\r
-                               \r
+                               // Check that name has only valid chars\r
+                               if(string_allowed(playername, PLAYERNAME_ALLOWED_CHARS)==false)\r
+                               {\r
+                                       error_message = L"Characters allowed: "\r
+                                                       +narrow_to_wide(PLAYERNAME_ALLOWED_CHARS);\r
+                                       continue;\r
+                               }*/\r
+\r
                                // Save settings\r
                                g_settings.set("name", playername);\r
                                g_settings.set("address", address);\r
@@ -1527,6 +1628,7 @@ int main(int argc, char *argv[])
                                font,\r
                                map_dir,\r
                                playername,\r
+                               password,\r
                                address,\r
                                port,\r
                                error_message\r