Cracking blocks while digging
authorPerttu Ahola <celeron55@gmail.com>
Tue, 21 Dec 2010 00:25:47 +0000 (02:25 +0200)
committerPerttu Ahola <celeron55@gmail.com>
Tue, 21 Dec 2010 00:25:47 +0000 (02:25 +0200)
16 files changed:
data/crack.png [new file with mode: 0644]
src/client.cpp
src/client.h
src/constants.h
src/defaultsettings.cpp
src/irrlichtwrapper.cpp
src/irrlichtwrapper.h
src/main.cpp
src/map.cpp
src/map.h
src/mapblock.cpp
src/mapblock.h
src/server.cpp
src/tile.cpp
src/tile.h
src/utility.h

diff --git a/data/crack.png b/data/crack.png
new file mode 100644 (file)
index 0000000..e39b74d
Binary files /dev/null and b/data/crack.png differ
index b612c9c44c2465446b744b7fd18002ec72810138..4979829d1cfd90f70ef4f90cfdc6f8f0bc3c161f 100644 (file)
@@ -398,45 +398,10 @@ void Client::step(float dtime)
                }
        }
 
-#if 0
-       /*
-               Clear old entries from fetchblock history
-       */
-       {
-               JMutexAutoLock lock(m_fetchblock_mutex);
-               
-               core::list<v3s16> remove_queue;
-               core::map<v3s16, float>::Iterator i;
-               i = m_fetchblock_history.getIterator();
-               for(; i.atEnd() == false; i++)
-               {
-                       float value = i.getNode()->getValue();
-                       value += dtime;
-                       i.getNode()->setValue(value);
-                       if(value >= 60.0)
-                               remove_queue.push_back(i.getNode()->getKey());
-               }
-               core::list<v3s16>::Iterator j;
-               j = remove_queue.begin();
-               for(; j != remove_queue.end(); j++)
-               {
-                       m_fetchblock_history.remove(*j);
-               }
-       }
-#endif
-
        /*{
                JMutexAutoLock lock(m_step_dtime_mutex);
                m_step_dtime += dtime;
        }*/
-       
-       /*
-               BEGIN TEST CODE
-       */
-
-       /*
-               END OF TEST CODE
-       */
 }
 
 float Client::asyncStep()
@@ -975,7 +940,11 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id)
                        if(abs_to_delete.find(p) != NULL)
                                abs_to_delete.remove(p);
 
-                       // Update objects of block
+                       /*
+                               Update objects of block
+                               
+                               NOTE: Be sure this is done in the main thread.
+                       */
                        block->updateObjects(is, m_server_ser_ver,
                                        m_device->getSceneManager());
                }
@@ -1482,11 +1451,11 @@ void Client::addNodeFromInventory(v3s16 nodepos, u16 i)
 }
 #endif
 
-void Client::pressGround(u8 button, v3s16 nodepos_undersurface,
+void Client::groundAction(u8 action, v3s16 nodepos_undersurface,
                v3s16 nodepos_oversurface, u16 item)
 {
        if(connectedAndInitialized() == false){
-               dout_client<<DTIME<<"Client::pressGround() "
+               dout_client<<DTIME<<"Client::groundAction() "
                                "cancelled (not connected)"
                                <<std::endl;
                return;
@@ -1507,7 +1476,7 @@ void Client::pressGround(u8 button, v3s16 nodepos_undersurface,
        u8 datasize = 2 + 1 + 6 + 6 + 2;
        SharedBuffer<u8> data(datasize);
        writeU16(&data[0], TOSERVER_GROUND_ACTION);
-       writeU8(&data[2], button);
+       writeU8(&data[2], action);
        writeV3S16(&data[3], nodepos_undersurface);
        writeV3S16(&data[9], nodepos_oversurface);
        writeU16(&data[15], item);
@@ -1540,37 +1509,6 @@ void Client::clickObject(u8 button, v3s16 blockpos, s16 id, u16 item)
        Send(0, data, true);
 }
 
-void Client::stopDigging()
-{
-       if(connectedAndInitialized() == false){
-               dout_client<<DTIME<<"Client::release() "
-                               "cancelled (not connected)"
-                               <<std::endl;
-               return;
-       }
-       
-       /*
-               length: 17
-               [0] u16 command
-               [2] u8 action
-               [3] v3s16 nodepos_undersurface
-               [9] v3s16 nodepos_abovesurface
-               [15] u16 item
-               actions:
-               0: start digging
-               1: place block
-               2: stop digging (all parameters ignored)
-       */
-       u8 datasize = 2 + 1 + 6 + 6 + 2;
-       SharedBuffer<u8> data(datasize);
-       writeU16(&data[0], TOSERVER_GROUND_ACTION);
-       writeU8(&data[2], 2);
-       writeV3S16(&data[3], v3s16(0,0,0));
-       writeV3S16(&data[9], v3s16(0,0,0));
-       writeU16(&data[15], 0);
-       Send(0, data, true);
-}
-
 void Client::sendSignText(v3s16 blockpos, s16 id, std::string text)
 {
        /*
@@ -1671,17 +1609,23 @@ MapNode Client::getNode(v3s16 p)
        return m_env.getMap().getNode(p);
 }
 
+/*void Client::getNode(v3s16 p, MapNode n)
+{
+       JMutexAutoLock envlock(m_env_mutex);
+       m_env.getMap().setNode(p, n);
+}*/
+
 /*f32 Client::getGroundHeight(v2s16 p)
 {
        JMutexAutoLock envlock(m_env_mutex);
        return m_env.getMap().getGroundHeight(p);
 }*/
 
-bool Client::isNodeUnderground(v3s16 p)
+/*bool Client::isNodeUnderground(v3s16 p)
 {
        JMutexAutoLock envlock(m_env_mutex);
        return m_env.getMap().isNodeUnderground(p);
-}
+}*/
 
 /*Player * Client::getLocalPlayer()
 {
index a1ee3f762b62b0c122c310f537cff3e618a720c9..a3d43997c4ccc8bc49a111dfe249c12639a0b9ad 100644 (file)
@@ -185,12 +185,9 @@ public:
        // Pops out a packet from the packet queue
        IncomingPacket getPacket();
 
-       /*void removeNode(v3s16 nodepos);
-       void addNodeFromInventory(v3s16 nodepos, u16 i);*/
-       void pressGround(u8 button, v3s16 nodepos_undersurface,
+       void groundAction(u8 action, v3s16 nodepos_undersurface,
                        v3s16 nodepos_oversurface, u16 item);
        void clickObject(u8 button, v3s16 blockpos, s16 id, u16 item);
-       void stopDigging();
 
        void sendSignText(v3s16 blockpos, s16 id, std::string text);
        
@@ -198,10 +195,13 @@ public:
        
        // Returns InvalidPositionException if not found
        MapNode getNode(v3s16 p);
+       // Returns InvalidPositionException if not found
+       //void setNode(v3s16 p, MapNode n);
+
        // Returns InvalidPositionException if not found
        //f32 getGroundHeight(v2s16 p);
        // Returns InvalidPositionException if not found
-       bool isNodeUnderground(v3s16 p);
+       //bool isNodeUnderground(v3s16 p);
 
        // Note: The players should not be exposed outside
        // Return value is valid until client is destroyed
@@ -236,6 +236,21 @@ public:
 
        //void updateSomeExpiredMeshes();
        
+       void setTempMod(v3s16 p, NodeMod mod)
+       {
+               JMutexAutoLock envlock(m_env_mutex);
+               assert(m_env.getMap().mapType() == MAPTYPE_CLIENT);
+               v3s16 blockpos = ((ClientMap&)m_env.getMap()).setTempMod(p, mod);
+               m_env.getMap().updateMeshes(blockpos, m_env.getDayNightRatio());
+       }
+       void clearTempMod(v3s16 p)
+       {
+               JMutexAutoLock envlock(m_env_mutex);
+               assert(m_env.getMap().mapType() == MAPTYPE_CLIENT);
+               v3s16 blockpos = ((ClientMap&)m_env.getMap()).clearTempMod(p);
+               m_env.getMap().updateMeshes(blockpos, m_env.getDayNightRatio());
+       }
+       
 private:
        
        // Virtual methods from con::PeerHandler
index c3fca432f83761cc891e05988128dbbb4e208215..7668c74515cd4cced4d69a370bf7a8d0585bbdab 100644 (file)
@@ -39,12 +39,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 
 #define PI 3.14159
 
-//#define SERVERMAP_DELETE_UNUSED_SECTORS_TIMEOUT (60*10)
-#define SERVERMAP_DELETE_UNUSED_SECTORS_TIMEOUT (60)
-#define SERVER_MAP_SAVE_INTERVAL (60)
-/*#define SERVERMAP_DELETE_UNUSED_SECTORS_TIMEOUT (10)
-#define SERVER_MAP_SAVE_INTERVAL (10)*/
-
 // This is the same as in minecraft and everything else
 #define FOV_ANGLE (PI/2.5)
 
index 04cdf16bce29660eb9d61c32eacb95f3c4e2670f..6888fa4971c87f40cac3a24ce631ad68fc5b12e6 100644 (file)
@@ -56,5 +56,7 @@ void set_default_settings()
        g_settings.setDefault("max_block_generate_distance", "4");
        g_settings.setDefault("time_send_interval", "20");
        g_settings.setDefault("time_speed", "360");
+       g_settings.setDefault("server_unload_unused_sectors_timeout", "60");
+       g_settings.setDefault("server_map_save_interval", "60");
 }
 
index 69b08a6d8a1a089c58d351f320d65abc6849e446..51511eb34fcc6f7eb8fefee6e2352e263560b42f 100644 (file)
@@ -17,7 +17,8 @@ void IrrlichtWrapper::Run()
                GetRequest<TextureSpec, video::ITexture*, u8, u8>
                                request = m_get_texture_queue.pop();
 
-               dstream<<"got request with key.name="<<request.key.name<<std::endl;
+               dstream<<"got texture request with key.name="
+                               <<request.key.name<<std::endl;
 
                GetResult<TextureSpec, video::ITexture*, u8, u8>
                                result;
@@ -37,7 +38,9 @@ video::ITexture* IrrlichtWrapper::getTexture(TextureSpec spec)
        
        if(get_current_thread_id() == m_main_thread)
        {
-               dstream<<"Loading texture directly: "<<spec.name<<std::endl;
+               dstream<<"Getting texture directly: name="
+                               <<spec.name<<std::endl;
+                               
                t = getTextureDirect(spec);
        }
        else
@@ -52,7 +55,7 @@ video::ITexture* IrrlichtWrapper::getTexture(TextureSpec spec)
 
                // Wait result
                GetResult<TextureSpec, video::ITexture*, u8, u8>
-                               result = result_queue.pop_front(true);
+                               result = result_queue.pop_front(1000);
                
                // Check that at least something worked OK
                assert(result.key.name == spec.name);
@@ -67,10 +70,6 @@ video::ITexture* IrrlichtWrapper::getTexture(TextureSpec spec)
 
 video::ITexture* IrrlichtWrapper::getTexture(const std::string &path)
 {
-       /*TextureSpec spec;
-       spec.name = path;
-       spec.path = path;
-       return getTexture(spec);*/
        return getTexture(TextureSpec(path, path, NULL));
 }
 
@@ -81,21 +80,61 @@ video::ITexture* IrrlichtWrapper::getTexture(const std::string &path)
 video::ITexture* IrrlichtWrapper::getTextureDirect(TextureSpec spec)
 {
        video::IVideoDriver* driver = m_device->getVideoDriver();
-       //TODO
-       if(spec.mod != NULL)
+       
+       if(spec.mod == NULL)
        {
-               dstream<<"IrrlichtWrapper::getTextureDirect: Modified textures"
-                               " not supported"<<std::endl;
+               dstream<<"IrrlichtWrapper::getTextureDirect: Loading texture "
+                               <<spec.path<<std::endl;
+               return driver->getTexture(spec.path.c_str());
        }
-       return driver->getTexture(spec.path.c_str());
+
+       dstream<<"IrrlichtWrapper::getTextureDirect: Loading and modifying "
+                       "texture "<<spec.path<<" to make "<<spec.name<<std::endl;
+
+       video::ITexture *base = driver->getTexture(spec.path.c_str());
+       video::ITexture *result = spec.mod->make(base, spec.name.c_str(), driver);
+
+       delete spec.mod;
+       
+       return result;
 }
 
 video::ITexture * CrackTextureMod::make(video::ITexture *original,
-               video::IVideoDriver* driver)
+               const char *newname, video::IVideoDriver* driver)
 {
-       //TODO
-       dstream<<__FUNCTION_NAME<<std::endl;
-       return NULL;
+       core::dimension2d<u32> dim(16, 16);
+       core::position2d<s32> pos_base(0, 0);
+       core::position2d<s32> pos_other(0, 16 * progression);
+
+       video::IImage *baseimage = driver->createImage(original, pos_base, dim);
+       assert(baseimage);
+       
+       video::ITexture *other = driver->getTexture("../data/crack.png");
+       // We have to get the whole texture because getting a smaller area
+       // messes the whole thing. It is probably a bug in Irrlicht.
+       video::IImage *otherimage = driver->createImage(
+                       other, core::position2d<s32>(0,0), other->getSize());
+
+       assert(otherimage);
+       
+       /*core::rect<s32> clip_rect(v2s32(0,0), dim);
+       otherimage->copyToWithAlpha(baseimage, v2s32(0,0),
+                       core::rect<s32>(pos_other, dim),
+                       video::SColor(255,255,255,255),
+                       &clip_rect);*/
+       
+       otherimage->copyToWithAlpha(baseimage, v2s32(0,0),
+                       core::rect<s32>(pos_other, dim),
+                       video::SColor(255,255,255,255),
+                       NULL);
+       
+       otherimage->drop();
+
+       video::ITexture *newtexture = driver->addTexture(newname, baseimage);
+
+       baseimage->drop();
+
+       return newtexture;
 }
 
 #if 0
index a78edfe784af4af703a80ddb17cf7f6fb7f0a5de..981e3377fe5d761d55298b36919716297684a3d8 100644 (file)
@@ -48,6 +48,9 @@ public:
        
        void set(std::string name, video::ITexture *texture)
        {
+               if(texture == NULL)
+                       return;
+               
                JMutexAutoLock lock(m_mutex);
 
                m_textures[name] = texture;
@@ -78,7 +81,7 @@ struct TextureMod
                Shall not modify or delete the original texture.
        */
        virtual video::ITexture * make(video::ITexture *original,
-                       video::IVideoDriver* driver) = 0;
+                       const char *newname, video::IVideoDriver* driver) = 0;
 };
 
 struct CrackTextureMod: public TextureMod
@@ -89,7 +92,7 @@ struct CrackTextureMod: public TextureMod
        }
        
        virtual video::ITexture * make(video::ITexture *original,
-                       video::IVideoDriver* driver);
+                       const char *newname, video::IVideoDriver* driver);
        
        u16 progression;
 };
@@ -149,10 +152,11 @@ public:
                These are called from other threads
        */
 
-       // Not exactly thread-safe but this needs to be fast
+       // Not exactly thread-safe but this needs to be fast.
+       // getTimer()->getRealTime() only reads one variable anyway.
        u32 getTime()
        {
-               return m_device->getTimer()->getTime();
+               return m_device->getTimer()->getRealTime();
        }
        
        video::ITexture* getTexture(TextureSpec spec);
index 56e725722a6a36c9981083b44811cbfbd36397bc..6b545596519aa14819141a17f4ac2033751e8fa6 100644 (file)
@@ -179,12 +179,6 @@ TODO: TOSERVER_LEAVE
 Doing now:\r
 ======================================================================\r
 \r
-TODO: Node cracking animation when digging\r
-      - TODO: A way to generate new textures by combining textures\r
-         - TODO: Mesh update to fetch cracked faces from the former\r
-\r
-TODO: A thread-safe wrapper for irrlicht for threads, to get rid of\r
-      g_device\r
 \r
 ======================================================================\r
 \r
@@ -1164,7 +1158,7 @@ int main(int argc, char *argv[])
        <<std::endl;\r
 \r
        std::cout<<std::endl;\r
-       char templine[100];\r
+       //char templine[100];\r
        \r
        // Port?\r
        u16 port = 30000;\r
@@ -1271,70 +1265,6 @@ int main(int argc, char *argv[])
        u16 screenW = atoi(g_settings.get("screenW").c_str());\r
        u16 screenH = atoi(g_settings.get("screenH").c_str());\r
 \r
-#if 0\r
-       u16 screenW;\r
-       u16 screenH;\r
-       bool fullscreen = false;\r
-       \r
-       if(g_settings.get("screenW") != "" && g_settings.get("screenH") != "")\r
-       {\r
-               screenW = atoi(g_settings.get("screenW").c_str());\r
-               screenH = atoi(g_settings.get("screenH").c_str());\r
-       }\r
-       else\r
-       {\r
-               u16 resolutions[][3] = {\r
-                       //W, H, fullscreen\r
-                       {640,480, 0},\r
-                       {800,600, 0},\r
-                       {1024,768, 0},\r
-                       {1280,1024, 0},\r
-                       /*{640,480, 1},\r
-                       {800,600, 1},\r
-                       {1024,768, 1},\r
-                       {1280,1024, 1},*/\r
-               };\r
-\r
-               u16 res_count = sizeof(resolutions)/sizeof(resolutions[0]);\r
-               \r
-               for(u16 i=0; i<res_count; i++)\r
-               {\r
-                       std::cout<<(i+1)<<": "<<resolutions[i][0]<<"x"\r
-                                       <<resolutions[i][1];\r
-                       if(resolutions[i][2])\r
-                               std::cout<<" fullscreen"<<std::endl;\r
-                       else\r
-                               std::cout<<" windowed"<<std::endl;\r
-               }\r
-               std::cout<<"Select a window resolution number [empty = 2]: ";\r
-               std::cin.getline(templine, 100);\r
-\r
-               u16 r0;\r
-               if(templine[0] == 0)\r
-                       r0 = 2;\r
-               else\r
-                       r0 = atoi(templine);\r
-\r
-               if(r0 > res_count || r0 == 0)\r
-                       r0 = 2;\r
-               \r
-               {\r
-                       u16 i = r0-1;\r
-                       std::cout<<"-> ";\r
-                       std::cout<<(i+1)<<": "<<resolutions[i][0]<<"x"\r
-                                       <<resolutions[i][1];\r
-                       if(resolutions[i][2])\r
-                               std::cout<<" fullscreen"<<std::endl;\r
-                       else\r
-                               std::cout<<" windowed"<<std::endl;\r
-               }\r
-\r
-               screenW = resolutions[r0-1][0];\r
-               screenH = resolutions[r0-1][1];\r
-               fullscreen = resolutions[r0-1][2];\r
-       }\r
-#endif\r
-\r
        //\r
 \r
        MyEventReceiver receiver;\r
@@ -1354,10 +1284,6 @@ int main(int argc, char *argv[])
        device = createDevice(driverType,\r
                        core::dimension2d<u32>(screenW, screenH),\r
                        16, fullscreen, false, false, &receiver);\r
-       // With vsync\r
-       /*device = createDevice(driverType,\r
-                       core::dimension2d<u32>(screenW, screenH),\r
-                       16, fullscreen, false, true, &receiver);*/\r
 \r
        if (device == 0)\r
                return 1; // could not create selected driver.\r
@@ -1380,10 +1306,10 @@ int main(int argc, char *argv[])
        */\r
 \r
        video::IVideoDriver* driver = device->getVideoDriver();\r
-       // These make the textures not to show at all\r
-       //driver->setTextureCreationFlag(video::ETCF_ALWAYS_16_BIT);\r
-       //driver->setTextureCreationFlag(video::ETCF_OPTIMIZED_FOR_SPEED );\r
 \r
+       /*\r
+               This changes the minimum allowed number of vertices in a VBO\r
+       */\r
        //driver->setMinHardwareBufferVertexCount(1);\r
 \r
        scene::ISceneManager* smgr = device->getSceneManager();\r
@@ -2147,48 +2073,69 @@ int main(int argc, char *argv[])
                        } // regular block\r
                } // for coords\r
 \r
-               /*static v3s16 oldnodepos;\r
-               static bool oldnodefound = false;*/\r
-\r
                if(nodefound)\r
                {\r
-                       //std::cout<<DTIME<<"nodefound == true"<<std::endl;\r
-                       //std::cout<<DTIME<<"nodepos=("<<nodepos.X<<","<<nodepos.Y<<","<<nodepos.Z<<")"<<std::endl;\r
-                       //std::cout<<DTIME<<"neighbourpos=("<<neighbourpos.X<<","<<neighbourpos.Y<<","<<neighbourpos.Z<<")"<<std::endl;\r
+                       static v3s16 nodepos_old(-32768,-32768,-32768);\r
+\r
+                       static float dig_time = 0.0;\r
 \r
-                       static v3s16 nodepos_old(-1,-1,-1);\r
-                       if(nodepos != nodepos_old){\r
+                       if(nodepos != nodepos_old)\r
+                       {\r
                                std::cout<<DTIME<<"Pointing at ("<<nodepos.X<<","\r
                                                <<nodepos.Y<<","<<nodepos.Z<<")"<<std::endl;\r
+\r
+                               if(nodepos_old != v3s16(-32768,-32768,-32768))\r
+                               {\r
+                                       client.clearTempMod(nodepos_old);\r
+                                       dig_time = 0.0;\r
+                               }\r
                        }\r
 \r
                        hilightboxes.push_back(nodefacebox);\r
                        \r
-                       //if(g_input->getLeftClicked())\r
+                       if(g_input->getLeftReleased())\r
+                       {\r
+                               client.clearTempMod(nodepos);\r
+                               dig_time = 0.0;\r
+                       }\r
                        if(g_input->getLeftClicked() ||\r
                                        (g_input->getLeftState() && nodepos != nodepos_old))\r
                        {\r
                                std::cout<<DTIME<<"Ground left-clicked"<<std::endl;\r
-                               client.pressGround(0, nodepos, neighbourpos, g_selected_item);\r
+                               client.groundAction(0, nodepos, neighbourpos, g_selected_item);\r
+                       }\r
+                       if(g_input->getLeftClicked())\r
+                       {\r
+                               client.setTempMod(nodepos, NodeMod(NODEMOD_CRACK, 0));\r
                        }\r
+                       if(g_input->getLeftState())\r
+                       {\r
+                               dig_time += dtime;\r
+                               \r
+                               float dig_time_complete = 0.5;\r
+                               MapNode n = client.getNode(nodepos);\r
+                               if(n.d == CONTENT_STONE)\r
+                                       dig_time_complete = 1.5;\r
+\r
+                               u16 dig_index = (u16)(3.99*dig_time/dig_time_complete);\r
+                               if(dig_time > 0.2)\r
+                               {\r
+                                       //dstream<<"dig_index="<<dig_index<<std::endl;\r
+                                       client.setTempMod(nodepos, NodeMod(NODEMOD_CRACK, dig_index));\r
+                               }\r
+                       }\r
+                       \r
                        if(g_input->getRightClicked())\r
-                       /*if(g_input->getRightClicked() ||\r
-                                       (g_input->getRightState() && nodepos != nodepos_old))*/\r
                        {\r
                                std::cout<<DTIME<<"Ground right-clicked"<<std::endl;\r
-                               client.pressGround(1, nodepos, neighbourpos, g_selected_item);\r
+                               client.groundAction(1, nodepos, neighbourpos, g_selected_item);\r
                        }\r
                        \r
                        nodepos_old = nodepos;\r
                }\r
                else{\r
-                       //std::cout<<DTIME<<"nodefound == false"<<std::endl;\r
-                       //positiontextgui->setText(L"");\r
                }\r
 \r
-               /*oldnodefound = nodefound;\r
-               oldnodepos = nodepos;*/\r
-\r
                } // selected_object == NULL\r
                \r
                g_input->resetLeftClicked();\r
@@ -2197,7 +2144,7 @@ int main(int argc, char *argv[])
                if(g_input->getLeftReleased())\r
                {\r
                        std::cout<<DTIME<<"Left released"<<std::endl;\r
-                       client.stopDigging();\r
+                       client.groundAction(2, v3s16(0,0,0), v3s16(0,0,0), 0);\r
                }\r
                if(g_input->getRightReleased())\r
                {\r
@@ -2214,26 +2161,6 @@ int main(int argc, char *argv[])
 \r
                camera->setAspectRatio((f32)screensize.X / (f32)screensize.Y);\r
                \r
-               // Background color is choosen based on whether the player is\r
-               // much beyond the initial ground level\r
-               /*video::SColor bgcolor;\r
-               v3s16 p0 = Map::floatToInt(player_position);\r
-               // Does this make short random delays?\r
-               // NOTE: no need for this, sky doesn't show underground with\r
-               // enough range\r
-               bool is_underground = client.isNodeUnderground(p0);\r
-               //bool is_underground = false;\r
-               if(is_underground == false)\r
-                       bgcolor = video::SColor(255,90,140,200);\r
-               else\r
-                       bgcolor = video::SColor(255,0,0,0);*/\r
-                       \r
-               //video::SColor bgcolor = video::SColor(255,90,140,200);\r
-               //video::SColor bgcolor = skycolor;\r
-               \r
-               //s32 daynight_i = client.getDayNightIndex();\r
-               //video::SColor bgcolor = skycolor[daynight_i];\r
-\r
                u32 daynight_ratio = client.getDayNightRatio();\r
                video::SColor bgcolor = video::SColor(\r
                                255,\r
index 13db9265145d077390a748e38c7fa891e3a4fd81..2a517c544448b33c705f33686920509acb3c077e 100644 (file)
@@ -1622,6 +1622,7 @@ MapBlock * ServerMap::emergeBlock(
        }
 
        //dstream<<"Not found on disk, generating."<<std::endl;
+       //TimeTaker("emergeBlock()", g_irrlicht);
 
        /*
                Do not generate over-limit
@@ -1668,7 +1669,7 @@ MapBlock * ServerMap::emergeBlock(
                underground_emptiness[i] = ((rand() % 5) == 0);
        }
 
-#if 0
+#if 1
        /*
                This is a messy hack to sort the emptiness a bit
        */
@@ -2235,20 +2236,15 @@ void ServerMap::save(bool only_changed)
 
        }//sectorlock
        
-       u32 deleted_count = 0;
-       deleted_count = deleteUnusedSectors(
-                       SERVERMAP_DELETE_UNUSED_SECTORS_TIMEOUT);
-       
        /*
                Only print if something happened or saved whole map
        */
        if(only_changed == false || sector_meta_count != 0
-                       || block_count != 0 || deleted_count != 0)
+                       || block_count != 0)
        {
                dstream<<DTIME<<"ServerMap: Written: "
                                <<sector_meta_count<<" sector metadata files, "
-                               <<block_count<<" block files, "
-                               <<deleted_count<<" sectors unloaded from memory."
+                               <<block_count<<" block files"
                                <<std::endl;
        }
 }
@@ -2987,9 +2983,23 @@ void ClientMap::renderMap(video::IVideoDriver* driver, s32 pass)
                        <<", rendered "<<vertex_count<<" vertices."<<std::endl;*/
 }
 
-void ClientMap::updateMesh()
+v3s16 ClientMap::setTempMod(v3s16 p, NodeMod mod)
 {
-       //TODO: Remove this
+       v3s16 blockpos = getNodeBlockPos(p);
+       MapBlock * blockref = getBlockNoCreate(blockpos);
+       v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
+
+       blockref->setTempMod(relpos, mod);
+       return blockpos;
+}
+v3s16 ClientMap::clearTempMod(v3s16 p)
+{
+       v3s16 blockpos = getNodeBlockPos(p);
+       MapBlock * blockref = getBlockNoCreate(blockpos);
+       v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
+
+       blockref->clearTempMod(relpos);
+       return blockpos;
 }
 
 void ClientMap::PrintInfo(std::ostream &out)
index 05984b1a90d97b0ddff65c752b732be4400d4c8e..3b34cd899e4edbb3e75bda9c3b2dc89998021f07 100644 (file)
--- a/src/map.h
+++ b/src/map.h
@@ -35,7 +35,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 
 #include "common_irrlicht.h"
 #include "heightmap.h"
-#include "loadstatus.h"
 #include "mapnode.h"
 #include "mapblock.h"
 #include "mapsector.h"
@@ -593,8 +592,15 @@ public:
 
        void renderMap(video::IVideoDriver* driver, s32 pass);
 
-       // Update master heightmap mesh
-       void updateMesh();
+       /*
+               Methods for setting temporary modifications to nodes for
+               drawing.
+               Return value is position of changed block.
+       */
+       v3s16 setTempMod(v3s16 p, NodeMod mod);
+       v3s16 clearTempMod(v3s16 p);
+       // Efficient implementation needs a cache of TempMods
+       //void clearTempMods();
 
        // For debug printing
        virtual void PrintInfo(std::ostream &out);
index af08cadaa45b3c870b040069690ec713dd46ed76..e2262544cdac2a6f10daa57a1dca21c80d7b4658 100644 (file)
@@ -300,6 +300,8 @@ TileSpec MapBlock::getNodeTile(MapNode mn, v3s16 p, v3s16 face_dir)
                }
                if(mod.type == NODEMOD_CRACK)
                {
+                       spec.feature = TILEFEAT_CRACK;
+                       spec.param.crack.progression = mod.param;
                }
        }
        
@@ -646,14 +648,31 @@ void MapBlock::updateMesh(u32 daynight_ratio)
                        
                        if(f.tile.feature == TILEFEAT_NONE)
                        {
-                               /*collector.append(g_tile_materials[f.tile.id], f.vertices, 4,
-                                               indices, 6);*/
                                collector.append(tile_material_get(f.tile.id), f.vertices, 4,
                                                indices, 6);
                        }
+                       else if(f.tile.feature == TILEFEAT_CRACK)
+                       {
+                               const char *path = tile_texture_path_get(f.tile.id);
+
+                               u16 progression = f.tile.param.crack.progression;
+
+                               std::string name = (std::string)path + "_cracked_"
+                                               + (char)('0' + progression);
+
+                               TextureMod *mod = new CrackTextureMod(progression);
+
+                               video::ITexture *texture = g_irrlicht->getTexture(
+                                               TextureSpec(name, path, mod));
+
+                               video::SMaterial material = tile_material_get(f.tile.id);
+                               material.setTexture(0, texture);
+
+                               collector.append(material, f.vertices, 4, indices, 6);
+                       }
                        else
                        {
-                               // Not implemented
+                               // No such feature
                                assert(0);
                        }
                }
@@ -668,19 +687,6 @@ void MapBlock::updateMesh(u32 daynight_ratio)
                                <<" materials (meshbuffers)"<<std::endl;*/
        }
 
-       /*
-               Clear temporary FastFaces
-       */
-
-       /*core::list<FastFace*>::Iterator i;
-       i = fastfaces_new->begin();
-       for(; i != fastfaces_new->end(); i++)
-       {
-               delete *i;
-       }
-       fastfaces_new->clear();
-       delete fastfaces_new;*/
-
        /*
                Add special graphics:
                - torches
@@ -688,14 +694,6 @@ void MapBlock::updateMesh(u32 daynight_ratio)
                TODO: Optimize by using same meshbuffer for same textures
        */
 
-       /*scene::ISceneManager *smgr = NULL;
-       video::IVideoDriver* driver = NULL;
-       if(g_device)
-       {
-               smgr = g_device->getSceneManager();
-               driver = smgr->getVideoDriver();
-       }*/
-                       
        for(s16 z=0; z<MAP_BLOCKSIZE; z++)
        for(s16 y=0; y<MAP_BLOCKSIZE; y++)
        for(s16 x=0; x<MAP_BLOCKSIZE; x++)
@@ -751,20 +749,16 @@ void MapBlock::updateMesh(u32 daynight_ratio)
                        if(dir == v3s16(0,-1,0))
                                buf->getMaterial().setTexture(0,
                                                g_irrlicht->getTexture("../data/torch_on_floor.png"));
-                                               //g_texturecache.get("torch_on_floor"));
                        else if(dir == v3s16(0,1,0))
                                buf->getMaterial().setTexture(0,
                                                g_irrlicht->getTexture("../data/torch_on_ceiling.png"));
-                                               //g_texturecache.get("torch_on_ceiling"));
                        // For backwards compatibility
                        else if(dir == v3s16(0,0,0))
                                buf->getMaterial().setTexture(0,
                                                g_irrlicht->getTexture("../data/torch_on_floor.png"));
-                                               //g_texturecache.get("torch_on_floor"));
                        else
                                buf->getMaterial().setTexture(0, 
                                                g_irrlicht->getTexture("../data/torch.png"));
-                               //buf->getMaterial().setTexture(0, g_texturecache.get("torch"));
 
                        // Add to mesh
                        mesh_new->addMeshBuffer(buf);
index 2bdf639b7017ee02145bfac5a452eba21ebf16b0..b5126b8225560c4984dc2b8d3583925ea82a61e6 100644 (file)
@@ -59,9 +59,10 @@ enum NodeModType
 
 struct NodeMod
 {
-       NodeMod()
+       NodeMod(enum NodeModType a_type=NODEMOD_NONE, u16 a_param=0)
        {
-               type = NODEMOD_NONE;
+               type = a_type;
+               param = a_param;
        }
        enum NodeModType type;
        u16 param;
@@ -393,6 +394,11 @@ public:
        */
        void setTempMod(v3s16 p, NodeMod mod)
        {
+               /*dstream<<"setTempMod called on block"
+                               <<" ("<<p.X<<","<<p.Y<<","<<p.Z<<")"
+                               <<", mod.type="<<mod.type
+                               <<", mod.param="<<mod.param
+                               <<std::endl;*/
                m_temp_mods[p] = mod;
        }
        void clearTempMod(v3s16 p)
index 7260e21d317a0c804d7485232532b9e5aff76ac6..7582024d143c1de2c645a347a791554d9b595abe 100644 (file)
@@ -1321,13 +1321,23 @@ void Server::AsyncRunStep()
        {
                float &counter = m_savemap_timer;
                counter += dtime;
-               if(counter >= SERVER_MAP_SAVE_INTERVAL)
+               if(counter >= g_settings.getFloat("server_map_save_interval"))
                {
                        counter = 0.0;
 
                        JMutexAutoLock lock(m_env_mutex);
+
                        // Save only changed parts
                        m_env.getMap().save(true);
+
+                       // Delete unused sectors
+                       u32 deleted_count = m_env.getMap().deleteUnusedSectors(
+                                       g_settings.getFloat("server_unload_unused_sectors_timeout"));
+                       if(deleted_count > 0)
+                       {
+                               dout_server<<"Server: Unloaded "<<deleted_count
+                                               <<" sectors from memory"<<std::endl;
+                       }
                }
        }
 }
index 174c72fdfbf0870b0c7ed9f4ca8360719b0b9b44..23b1638d1be6fd96450fe637ceb3ea007ddab213 100644 (file)
@@ -37,6 +37,13 @@ const char * g_tile_texture_paths[TILES_COUNT] =
        "../data/cloud.png",
 };
 
+const char * tile_texture_path_get(u32 i)
+{
+       assert(i < TILES_COUNT);
+
+       return g_tile_texture_paths[i];
+}
+
 // A mapping from tiles to materials
 // Initialized at run-time.
 video::SMaterial g_tile_materials[TILES_COUNT];
index d9756766124581880bf9ada047865f4abe2e5625..68e87a77d2542abe22aa0667692e10a9370bc292 100644 (file)
@@ -100,6 +100,8 @@ extern video::SMaterial g_tile_materials[TILES_COUNT];*/
        Functions
 */
 
+const char * tile_texture_path_get(u32 i);
+
 // Initializes g_tile_materials
 void tile_materials_preload(IrrlichtWrapper *irrlicht);
 
index cde5557605137cf19765a18afc5ad1fb27a3289d..bfee15e61b491bbb11b0d68354720ccc2a3d6a7d 100644 (file)
@@ -1085,7 +1085,6 @@ public:
        MutexedQueue()
        {
                m_mutex.Init();
-               m_is_empty_mutex.Init();
        }
        u32 size()
        {
@@ -1095,12 +1094,11 @@ public:
        {
                JMutexAutoLock lock(m_mutex);
                m_list.push_back(t);
-               
-               if(m_list.size() == 1)
-                       m_is_empty_mutex.Unlock();
        }
-       T pop_front(bool wait_if_empty=false)
+       T pop_front(u32 wait_time_max_ms=0)
        {
+               u32 wait_time_ms = 0;
+
                for(;;)
                {
                        {
@@ -1108,24 +1106,19 @@ public:
 
                                if(m_list.size() > 0)
                                {
-                                       if(m_list.size() == 1)
-                                               m_is_empty_mutex.Lock();
-                                       
                                        typename core::list<T>::Iterator begin = m_list.begin();
                                        T t = *begin;
                                        m_list.erase(begin);
                                        return t;
                                }
 
-                               if(wait_if_empty == false)
-                                       throw ItemNotFoundException("MutexedQueue: item not found");
+                               if(wait_time_ms >= wait_time_max_ms)
+                                       throw ItemNotFoundException("MutexedQueue: queue is empty");
                        }
-                       
-                       // To wait for an empty list, we're gonna hang on this mutex
-                       m_is_empty_mutex.Lock();
-                       m_is_empty_mutex.Unlock();
 
-                       // Then loop to the beginning and hopefully return something
+                       // Wait a while before trying again
+                       sleep_ms(10);
+                       wait_time_ms += 10;
                }
        }
 
@@ -1134,11 +1127,6 @@ public:
                return m_mutex;
        }
 
-       JMutex & getIsEmptyMutex()
-       {
-               return m_is_empty_mutex;
-       }
-       
        core::list<T> & getList()
        {
                return m_list;
@@ -1146,8 +1134,6 @@ public:
 
 protected:
        JMutex m_mutex;
-       // This is locked always when the list is empty
-       JMutex m_is_empty_mutex;
        core::list<T> m_list;
 };
 
@@ -1262,9 +1248,6 @@ public:
                request.dest = dest;
                
                m_queue.getList().push_back(request);
-               
-               if(m_queue.getList().size() == 1)
-                       m_queue.getIsEmptyMutex().Unlock();
        }
 
        GetRequest<Key, T, Caller, CallerData> pop(bool wait_if_empty=false)