]> git.lizzy.rs Git - dragonfireclient.git/blobdiff - src/main.cpp
end-of-day.
[dragonfireclient.git] / src / main.cpp
index 092d62988bb05a31ebadd33eb7c59306bba790fa..176cde639e33fcf206457b637f6c4befac3eb05c 100644 (file)
@@ -104,12 +104,11 @@ SUGG: Meshes of blocks could be split into 6 meshes facing into
 Gaming ideas:\r
 -------------\r
 \r
-- How would some GTA-style ideas work?\r
-  - Cars? Stealing? Unlawful stuff and cops? Lots of guns?\r
+- Aim for something like controlling a single dwarf in Dwarf Fortress\r
 \r
-- RPG style?\r
+- The player could go faster by a crafting a boat, or riding an animal\r
 \r
-- Space racer style?\r
+- Random NPC traders. what else?\r
 \r
 Documentation:\r
 --------------\r
@@ -153,8 +152,10 @@ TODO: Optimize day/night mesh updating somehow
                   meshbuffers? It should go quite fast.\r
                   - This is not easy; There'd need to be a buffer somewhere\r
                     that would contain the night and day lighting values.\r
+                        - Actually if FastFaces would be stored, they could\r
+                          hold both values\r
 \r
-TODO: Combine MapBlock's face caches to so big pieces that VBO\r
+FEATURE: Combine MapBlock's face caches to so big pieces that VBO\r
       gets used\r
       - That is >500 vertices\r
          - This is not easy; all the MapBlocks close to the player would\r
@@ -167,6 +168,29 @@ TODO: Make fetching sector's blocks more efficient when rendering
 \r
 TODO: Flowing water animation\r
 \r
+FIXME(FIXED): The new texture stuff is slow on wine\r
+       - A basic grassy ground block takes 20-40ms\r
+       - A bit more complicated block can take 270ms\r
+         - On linux, a similar one doesn't take long at all (14ms)\r
+           - It is NOT a bad std::string implementation of MSVC.\r
+       - Can take up to 200ms? Is it when loading textures or always?\r
+       - Updating excess amount of meshes when making footprints is too\r
+         slow. It has to be fixed.\r
+         -> implement Map::updateNodeMeshes()\r
+       The fix:\r
+    * Optimize TileSpec to only contain a reference number that\r
+         is fast to compare, which refers to a cached string, or\r
+       * Make TextureSpec for using instead of strings\r
+\r
+FIXME(FIXED): A lock condition is possible:\r
+       1) MapBlock::updateMesh() is called from client asynchronously:\r
+          - AsyncProcessData() -> Map::updateMeshes()\r
+       2) Asynchronous locks m_temp_mods_mutex\r
+       3) MapBlock::updateMesh() is called from client synchronously:\r
+          - Client::step() -> Environment::step()\r
+       4) Synchronous starts waiting for m_temp_mods_mutex\r
+       5) Asynchronous calls getTexture, which starts waiting for main thread\r
+\r
 Configuration:\r
 --------------\r
 \r
@@ -181,6 +205,10 @@ TODO: Untie client network operations from framerate
 \r
 TODO: Make morning and evening shorter\r
 \r
+TODO: Don't update all meshes always on single node changes, but\r
+      check which ones should be updated\r
+         - implement Map::updateNodeMeshes()\r
+\r
 Server:\r
 -------\r
 \r
@@ -236,7 +264,21 @@ Block object server side:
 NOTE: There are some lighting-related todos and fixmes in\r
       ServerMap::emergeBlock. And there always will be. 8)\r
 \r
-TODO: Map generator version 2\r
+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
+\r
+TODO: Change AttributeList to split the area into smaller sections so\r
+      that searching won't be as heavy.\r
+\r
+TODO: Remove HMParams\r
+\r
+TODO: Flowing water to actually contain flow direction information\r
+\r
+TODO: Remove duplicate lighting implementation from Map (leave\r
+      VoxelManipulator, which is faster)\r
+\r
+FEATURE: Map generator version 2\r
        - Create surface areas based on central points; a given point's\r
          area type is given by the nearest central point\r
          - Separate points for heightmap, caves, plants and minerals?\r
@@ -247,22 +289,63 @@ TODO: Map generator version 2
        - Create a system that allows a huge amount of different "map\r
          generator modules/filters"\r
 \r
-TODO: Change AttributeList to split the area into smaller sections so\r
-      that searching won't be as heavy.\r
-TODO: Change AttributeList to be 2D, as it would be too slow to search\r
-      in 3D fields anyway.\r
-\r
-FIXME: The new pre-sunlight-propagation code messes up with initial\r
-       water lighting. Does it any more?\r
-\r
-TODO: Remove HMParams\r
-\r
-TODO: Flowing water to actually contain flow direction information\r
-\r
-TODO: Faster lighting using VoxelManipulator\r
+FEATURE: The map could be generated procedually:\r
+      - This would need the map to be generated in larger pieces\r
+           - How large? How do they connect to each other?\r
+               - It has to be split vertically also\r
+               - Lighting would not have to be necessarily calculated until\r
+                 the blocks are actually needed - it would be quite fast\r
+               - Something like 64*64*16 MapBlocks?\r
+                 - No, MapSectors. And as much as it is efficient to do,\r
+                   64x64 might be too much.\r
+        - FIXME: This is currently halfway done and the generator is\r
+                 fairly broken\r
+      * Make the stone level with a heightmap\r
+         * Carve out stuff in the stone\r
+         * Dump dirt all around, and simulate it falling off steep\r
+           places\r
+         * 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
 Doing now:\r
 ----------\r
+# maybe done\r
+* not done\r
+\r
+* Remove all kinds of systems that are made redundant by the new map\r
+  generator\r
+  - Sector heightmaps? At least they should be made redundant.\r
+  - Sector objects\r
+* Do something about AttributeDatabase/List being too slow\r
+* Save chunk metadata on disk\r
+* Change water side textures so that buggy water doesn't look bad\r
+* Make server find the spawning place from the real map data, not from\r
+  the heightmap\r
+* only_from_disk doesn't work that well anymore\r
+* Make the generator to run in background and not blocking block\r
+  placement and transfer\r
+* Fix the strange mineral occurences\r
+* When the map is generated and a place is found for the player, the\r
+  first chunk is actually still volatile and will have stuff still\r
+  changed after spawning, which creates a lot of glitches.\r
+  - This is partly fixed by now allowing only 2-sector deeep\r
+    modification of volatile chunks. But it should still be fixed?\r
+  - How about checking that the neighbors are fully generated too and\r
+    generate them when the middle piece is needed\r
+       - This is very slow\r
+  - How about just enabling changed_blocks properly\r
+    - This is probably a good idea\r
+    - The server has to make sure the spawn point is not at the\r
+         changing borders of a chunk\r
+* Add some kind of erosion and other stuff that now is possible\r
 \r
 ======================================================================\r
 \r
@@ -295,6 +378,7 @@ Doing now:
 #pragma comment(lib, "Irrlicht.lib")\r
 //#pragma comment(lib, "jthread.lib")\r
 #pragma comment(lib, "zlibwapi.lib")\r
+#pragma comment(lib, "Shell32.lib")\r
 // This would get rid of the console window\r
 //#pragma comment(linker, "/subsystem:windows /ENTRY:mainCRTStartup")\r
 #endif\r
@@ -327,6 +411,7 @@ Doing now:
 #include "filesys.h"\r
 #include "config.h"\r
 #include "guiMainMenu.h"\r
+#include "mineral.h"\r
 \r
 IrrlichtWrapper *g_irrlicht;\r
 \r
@@ -1236,38 +1321,106 @@ struct ChatLine
        std::wstring text;\r
 };\r
 \r
-int main(int argc, char *argv[])\r
-{\r
-       /*\r
-               Low-level initialization\r
-       */\r
+// These are defined global so that they're not optimized too much.\r
+// Can't change them to volatile.\r
+s16 temp16;\r
+f32 tempf;\r
+v3f tempv3f1;\r
+v3f tempv3f2;\r
+std::string tempstring;\r
+std::string tempstring2;\r
 \r
-       bool disable_stderr = false;\r
-#ifdef _WIN32\r
-       disable_stderr = true;\r
-#endif\r
+void SpeedTests()\r
+{\r
+       {\r
+               dstream<<"The following test should take around 20ms."<<std::endl;\r
+               TimeTaker timer("Testing std::string speed");\r
+               const u32 jj = 10000;\r
+               for(u32 j=0; j<jj; j++)\r
+               {\r
+                       tempstring = "";\r
+                       tempstring2 = "";\r
+                       const u32 ii = 10;\r
+                       for(u32 i=0; i<ii; i++){\r
+                               tempstring2 += "asd";\r
+                       }\r
+                       for(u32 i=0; i<ii+1; i++){\r
+                               tempstring += "asd";\r
+                               if(tempstring == tempstring2)\r
+                                       break;\r
+                       }\r
+               }\r
+       }\r
+       \r
+       dstream<<"All of the following tests should take around 100ms each."\r
+                       <<std::endl;\r
 \r
-       // Initialize debug streams\r
-       debugstreams_init(disable_stderr, DEBUGFILE);\r
-       // Initialize debug stacks\r
-       debug_stacks_init();\r
+       {\r
+               TimeTaker timer("Testing floating-point conversion speed");\r
+               tempf = 0.001;\r
+               for(u32 i=0; i<4000000; i++){\r
+                       temp16 += tempf;\r
+                       tempf += 0.001;\r
+               }\r
+       }\r
+       \r
+       {\r
+               TimeTaker timer("Testing floating-point vector speed");\r
 \r
-       DSTACK(__FUNCTION_NAME);\r
+               tempv3f1 = v3f(1,2,3);\r
+               tempv3f2 = v3f(4,5,6);\r
+               for(u32 i=0; i<10000000; i++){\r
+                       tempf += tempv3f1.dotProduct(tempv3f2);\r
+                       tempv3f2 += v3f(7,8,9);\r
+               }\r
+       }\r
 \r
-       porting::initializePaths();\r
-       // Create user data directory\r
-       fs::CreateDir(porting::path_userdata);\r
+       {\r
+               TimeTaker timer("Testing core::map speed");\r
+               \r
+               core::map<v2s16, f32> map1;\r
+               tempf = -324;\r
+               const s16 ii=300;\r
+               for(s16 y=0; y<ii; y++){\r
+                       for(s16 x=0; x<ii; x++){\r
+                               map1.insert(v2s16(x,y), tempf);\r
+                               tempf += 1;\r
+                       }\r
+               }\r
+               for(s16 y=ii-1; y>=0; y--){\r
+                       for(s16 x=0; x<ii; x++){\r
+                               tempf = map1[v2s16(x,y)];\r
+                       }\r
+               }\r
+       }\r
 \r
-       initializeMaterialProperties();\r
+       {\r
+               dstream<<"Around 5000/ms should do well here."<<std::endl;\r
+               TimeTaker timer("Testing mutex speed");\r
+               \r
+               JMutex m;\r
+               m.Init();\r
+               u32 n = 0;\r
+               u32 i = 0;\r
+               do{\r
+                       n += 10000;\r
+                       for(; i<n; i++){\r
+                               m.Lock();\r
+                               m.Unlock();\r
+                       }\r
+               }\r
+               // Do at least 10ms\r
+               while(timer.getTime() < 10);\r
 \r
-       BEGIN_DEBUG_EXCEPTION_HANDLER\r
+               u32 dtime = timer.stop();\r
+               u32 per_ms = n / dtime;\r
+               std::cout<<"Done. "<<dtime<<"ms, "\r
+                               <<per_ms<<"/ms"<<std::endl;\r
+       }\r
+}\r
 \r
-       // Print startup message\r
-       dstream<<DTIME<<"minetest-c55"\r
-                       " with SER_FMT_VER_HIGHEST="<<(int)SER_FMT_VER_HIGHEST\r
-                       <<", "<<BUILD_INFO\r
-                       <<std::endl;\r
-       \r
+int main(int argc, char *argv[])\r
+{\r
        /*\r
                Parse command line\r
        */\r
@@ -1285,6 +1438,10 @@ int main(int argc, char *argv[])
        allowed_options.insert("disable-unittests", ValueSpec(VALUETYPE_FLAG));\r
        allowed_options.insert("enable-unittests", ValueSpec(VALUETYPE_FLAG));\r
        allowed_options.insert("map-dir", ValueSpec(VALUETYPE_STRING));\r
+#ifdef _WIN32\r
+       allowed_options.insert("dstream-on-stderr", ValueSpec(VALUETYPE_FLAG));\r
+#endif\r
+       allowed_options.insert("speedtests", ValueSpec(VALUETYPE_FLAG));\r
 \r
        Settings cmd_args;\r
        \r
@@ -1316,8 +1473,40 @@ int main(int argc, char *argv[])
 \r
                return cmd_args.getFlag("help") ? 0 : 1;\r
        }\r
+       \r
+       /*\r
+               Low-level initialization\r
+       */\r
 \r
+       bool disable_stderr = false;\r
+#ifdef _WIN32\r
+       if(cmd_args.getFlag("dstream-on-stderr") == false)\r
+               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::initializePaths();\r
+       // Create user data directory\r
+       fs::CreateDir(porting::path_userdata);\r
+       \r
+       // C-style stuff initialization\r
+       initializeMaterialProperties();\r
+\r
+       // Debug handler\r
+       BEGIN_DEBUG_EXCEPTION_HANDLER\r
+\r
+       // Print startup message\r
+       dstream<<DTIME<<"minetest-c55"\r
+                       " with SER_FMT_VER_HIGHEST="<<(int)SER_FMT_VER_HIGHEST\r
+                       <<", "<<BUILD_INFO\r
+                       <<std::endl;\r
+       \r
        /*\r
                Basic initialization\r
        */\r
@@ -1379,6 +1568,16 @@ int main(int argc, char *argv[])
        srand(time(0));\r
        mysrand(time(0));\r
 \r
+       /*\r
+               Pre-initialize some stuff with a dummy irrlicht wrapper.\r
+\r
+               These are needed for unit tests at least.\r
+       */\r
+       \r
+       IIrrlichtWrapper irrlicht_dummy;\r
+\r
+       init_mapnode(&irrlicht_dummy);\r
+\r
        /*\r
                Run unit tests\r
        */\r
@@ -1486,7 +1685,15 @@ int main(int argc, char *argv[])
        g_device = device;\r
        g_irrlicht = new IrrlichtWrapper(device);\r
 \r
-       //g_device = device;\r
+       /*\r
+               Speed tests (done after irrlicht is loaded to get timer)\r
+       */\r
+       if(cmd_args.getFlag("speedtests"))\r
+       {\r
+               dstream<<"Running speed tests"<<std::endl;\r
+               SpeedTests();\r
+               return 0;\r
+       }\r
        \r
        device->setResizable(true);\r
 \r
@@ -1533,11 +1740,12 @@ int main(int argc, char *argv[])
        skin->setColor(gui::EGDC_3D_SHADOW, video::SColor(255,0,0,0));\r
        \r
        /*\r
-               Preload some textures\r
+               Preload some textures and stuff\r
        */\r
 \r
        init_content_inventory_texture_paths();\r
-       init_tile_textures();\r
+       init_mapnode(g_irrlicht);\r
+       init_mineral(g_irrlicht);\r
 \r
        /*\r
                GUI stuff\r
@@ -1595,10 +1803,10 @@ int main(int argc, char *argv[])
        {\r
        \r
        /*\r
-               Out-of-game menu loop\r
+               Out-of-game menu loop.\r
+\r
+               Loop quits when menu returns proper parameters.\r
        */\r
-       \r
-       // Wait for proper parameters\r
        for(;;)\r
        {\r
                // Cursor can be non-visible when coming from the game\r
@@ -1658,6 +1866,15 @@ int main(int argc, char *argv[])
                dstream<<"Dropping main menu"<<std::endl;\r
 \r
                menu->drop();\r
+               \r
+               // Delete map if requested\r
+               if(menudata.delete_map)\r
+               {\r
+                       bool r = fs::RecursiveDeleteContent(map_dir);\r
+                       if(r == false)\r
+                               error_message = L"Delete failed";\r
+                       continue;\r
+               }\r
 \r
                playername = wide_to_narrow(menudata.name);\r
                address = wide_to_narrow(menudata.address);\r
@@ -1694,6 +1911,9 @@ int main(int argc, char *argv[])
        */\r
        {\r
 \r
+       // This is set to true at the end of the scope\r
+       g_irrlicht->Shutdown(false);\r
+\r
        /*\r
                Draw "Loading" screen\r
        */\r
@@ -1970,20 +2190,6 @@ int main(int argc, char *argv[])
                                dtime_jitter1_max_fraction\r
                                                = dtime_jitter1_max_sample / (dtime_avg1+0.001);\r
                                jitter1_max = 0.0;\r
-                               \r
-                               /*\r
-                                       Control freetime ratio\r
-                               */\r
-                               /*if(dtime_jitter1_max_fraction > DTIME_JITTER_MAX_FRACTION)\r
-                               {\r
-                                       if(g_freetime_ratio < FREETIME_RATIO_MAX)\r
-                                               g_freetime_ratio += 0.01;\r
-                               }\r
-                               else\r
-                               {\r
-                                       if(g_freetime_ratio > FREETIME_RATIO_MIN)\r
-                                               g_freetime_ratio -= 0.01;\r
-                               }*/\r
                        }\r
                }\r
                \r
@@ -2118,9 +2324,9 @@ int main(int argc, char *argv[])
                camera_direction.rotateXZBy(camera_yaw);\r
                \r
                // This is at the height of the eyes of the current figure\r
-               v3f camera_position = player_position + v3f(0, BS+BS/2, 0);\r
+               //v3f camera_position = player_position + v3f(0, BS+BS/2, 0);\r
                // This is more like in minecraft\r
-               //v3f camera_position = player_position + v3f(0, BS+BS*0.625, 0);\r
+               v3f camera_position = player_position + v3f(0, BS+BS*0.625, 0);\r
 \r
                camera->setPosition(camera_position);\r
                // *100.0 helps in large map coordinates\r
@@ -2223,7 +2429,7 @@ int main(int argc, char *argv[])
                bool nodefound = false;\r
                v3s16 nodepos;\r
                v3s16 neighbourpos;\r
-               core::aabbox3d<f32> nodefacebox;\r
+               core::aabbox3d<f32> nodehilightbox;\r
                f32 mindistance = BS * 1001;\r
                \r
                v3s16 pos_i = floatToInt(player_position);\r
@@ -2315,7 +2521,7 @@ int main(int argc, char *argv[])
                                                nodepos = np;\r
                                                neighbourpos = np;\r
                                                mindistance = distance;\r
-                                               nodefacebox = box;\r
+                                               nodehilightbox = box;\r
                                        }\r
                                }\r
                        }\r
@@ -2358,7 +2564,16 @@ int main(int argc, char *argv[])
                                                        nodepos = np;\r
                                                        neighbourpos = np + dirs[i];\r
                                                        mindistance = distance;\r
-                                                       nodefacebox = facebox;\r
+\r
+                                                       //nodehilightbox = facebox;\r
+\r
+                                                       const float d = 0.502;\r
+                                                       core::aabbox3d<f32> nodebox\r
+                                                                       (-BS*d, -BS*d, -BS*d, BS*d, BS*d, BS*d);\r
+                                                       v3f nodepos_f = intToFloat(nodepos);\r
+                                                       nodebox.MinEdge += nodepos_f;\r
+                                                       nodebox.MaxEdge += nodepos_f;\r
+                                                       nodehilightbox = nodebox;\r
                                                }\r
                                        } // if distance < mindistance\r
                                } // for dirs\r
@@ -2373,8 +2588,12 @@ int main(int argc, char *argv[])
 \r
                        static float dig_time = 0.0;\r
                        static u16 dig_index = 0;\r
+                       \r
+                       // Visualize selection\r
+\r
+                       hilightboxes.push_back(nodehilightbox);\r
 \r
-                       hilightboxes.push_back(nodefacebox);\r
+                       // Handle digging\r
                        \r
                        if(g_input->getLeftReleased())\r
                        {\r
@@ -2460,6 +2679,7 @@ int main(int argc, char *argv[])
 \r
                                        if(dig_index < CRACK_ANIMATION_LENGTH)\r
                                        {\r
+                                               //TimeTaker timer("client.setTempMod");\r
                                                //dstream<<"dig_index="<<dig_index<<std::endl;\r
                                                client.setTempMod(nodepos, NodeMod(NODEMOD_CRACK, dig_index));\r
                                        }\r
@@ -2483,8 +2703,7 @@ int main(int argc, char *argv[])
                                                }\r
                                                // We want a slight delay to very little\r
                                                // time consuming nodes\r
-                                               //float mindelay = 0.15;\r
-                                               float mindelay = 0.20;\r
+                                               float mindelay = 0.15;\r
                                                if(nodig_delay_counter < mindelay)\r
                                                {\r
                                                        nodig_delay_counter = mindelay;\r
@@ -2751,7 +2970,8 @@ int main(int argc, char *argv[])
                //TimeTaker //timer10("//timer10");\r
                \r
                video::SMaterial m;\r
-               m.Thickness = 10;\r
+               //m.Thickness = 10;\r
+               m.Thickness = 3;\r
                m.Lighting = false;\r
                driver->setMaterial(m);\r
 \r
@@ -2824,6 +3044,14 @@ int main(int argc, char *argv[])
 \r
        delete quick_inventory;\r
 \r
+       /*\r
+               Disable texture fetches and other stuff that is queued\r
+               to be processed by the main loop.\r
+\r
+               This has to be done before client goes out of scope.\r
+       */\r
+       g_irrlicht->Shutdown(true);\r
+\r
        } // client and server are deleted at this point\r
 \r
        } //try\r