]> git.lizzy.rs Git - minetest.git/blobdiff - src/client.cpp
Add player:set_sky() with simple skybox support
[minetest.git] / src / client.cpp
index ee63cf7c81e395a5089f2e72582f80fc2fdffc83..48b00377f36138077191cf76399ce92a2ef7c8a3 100644 (file)
@@ -51,15 +51,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include "util/pointedthing.h"
 #include "version.h"
 
-#if USE_CURL
-#include <curl/curl.h>
-#endif
-
-static std::string getMediaCacheDir()
-{
-       return porting::path_user + DIR_DELIM + "cache" + DIR_DELIM + "media";
-}
-
 /*
        QueuedMeshUpdate
 */
@@ -177,7 +168,7 @@ void * MeshUpdateThread::Thread()
        
        BEGIN_DEBUG_EXCEPTION_HANDLER
 
-       while(getRun())
+       while(!StopRequested())
        {
                /*// Wait for output queue to flush.
                // Allow 2 in queue, this makes less frametime jitter.
@@ -295,6 +286,20 @@ Client::Client(
        }
 }
 
+void Client::Stop()
+{
+       //request all client managed threads to stop
+       m_mesh_update_thread.Stop();
+}
+
+bool Client::isShutdown()
+{
+
+       if (!m_mesh_update_thread.IsRunning()) return true;
+
+       return false;
+}
+
 Client::~Client()
 {
        {
@@ -302,11 +307,10 @@ Client::~Client()
                m_con.Disconnect();
        }
 
-       m_mesh_update_thread.setRun(false);
-       while(m_mesh_update_thread.IsRunning())
-               sleep_ms(100);
+       m_mesh_update_thread.Stop();
+       m_mesh_update_thread.Wait();
        while(!m_mesh_update_thread.m_queue_out.empty()) {
-               MeshUpdateResult r = m_mesh_update_thread.m_queue_out.pop_front();
+               MeshUpdateResult r = m_mesh_update_thread.m_queue_out.pop_frontNoEx();
                delete r.mesh;
        }
 
@@ -379,13 +383,6 @@ void Client::step(float dtime)
                // 0ms
                ReceiveAll();
        }
-       
-       {
-               //TimeTaker timer("m_con_mutex + m_con.RunTimeouts()", m_device);
-               // 0ms
-               //JMutexAutoLock lock(m_con_mutex); //bulk comment-out
-               m_con.RunTimeouts(dtime);
-       }
 
        /*
                Packet counter
@@ -534,7 +531,7 @@ void Client::step(float dtime)
                        writeU16(&data[53], CLIENT_PROTOCOL_VERSION_MAX);
 
                        // Send as unreliable
-                       Send(0, data, false);
+                       Send(1, data, false);
                }
 
                // Not connected, return
@@ -593,7 +590,7 @@ void Client::step(float dtime)
                                        writeV3S16(&reply[2+1+6*k], *j);
                                        k++;
                                }
-                               m_con.Send(PEER_ID_SERVER, 1, reply, true);
+                               m_con.Send(PEER_ID_SERVER, 2, reply, true);
 
                                if(i == deleted_blocks.end())
                                        break;
@@ -702,7 +699,7 @@ void Client::step(float dtime)
                while(!m_mesh_update_thread.m_queue_out.empty())
                {
                        num_processed_meshes++;
-                       MeshUpdateResult r = m_mesh_update_thread.m_queue_out.pop_front();
+                       MeshUpdateResult r = m_mesh_update_thread.m_queue_out.pop_frontNoEx();
                        MapBlock *block = m_env.getMap().getBlockNoCreateNoEx(r.p);
                        if(block)
                        {
@@ -741,7 +738,7 @@ void Client::step(float dtime)
                                reply[2] = 1;
                                writeV3S16(&reply[3], r.p);
                                // Send as reliable
-                               m_con.Send(PEER_ID_SERVER, 1, reply, true);
+                               m_con.Send(PEER_ID_SERVER, 2, reply, true);
                        }
                }
                if(num_processed_meshes > 0)
@@ -754,6 +751,7 @@ void Client::step(float dtime)
        if (m_media_downloader && m_media_downloader->isStarted()) {
                m_media_downloader->step(this);
                if (m_media_downloader->isDone()) {
+                       received_media();
                        delete m_media_downloader;
                        m_media_downloader = NULL;
                }
@@ -836,7 +834,7 @@ void Client::step(float dtime)
                        std::string s = os.str();
                        SharedBuffer<u8> data((u8*)s.c_str(), s.size());
                        // Send as reliable
-                       Send(0, data, true);
+                       Send(1, data, true);
                }
        }
 }
@@ -903,30 +901,12 @@ bool Client::loadMedia(const std::string &data, const std::string &filename)
        name = removeStringEnd(filename, model_ext);
        if(name != "")
        {
-               verbosestream<<"Client: Storing model into Irrlicht: "
+               verbosestream<<"Client: Storing model into memory: "
                                <<"\""<<filename<<"\""<<std::endl;
-               scene::ISceneManager *smgr = m_device->getSceneManager();
-
-               //check if mesh was already cached
-               scene::IAnimatedMesh *mesh =
-                       smgr->getMeshCache()->getMeshByName(filename.c_str());
-
-               if (mesh != NULL) {
-                       errorstream << "Multiple models with name: " << filename.c_str() <<
-                                       " found replacing previous model!" << std::endl;
-
-                       smgr->getMeshCache()->removeMesh(mesh);
-                       mesh = 0;
-               }
-
-               io::IFileSystem *irrfs = m_device->getFileSystem();
-               io::IReadFile *rfile = irrfs->createMemoryReadFile(
-                               *data_rw, data_rw.getSize(), filename.c_str());
-               assert(rfile);
-               
-               mesh = smgr->getMesh(rfile);
-               smgr->getMeshCache()->addMesh(filename.c_str(), mesh);
-               rfile->drop();
+               if(m_mesh_data.count(filename))
+                       errorstream<<"Multiple models with name \""<<filename.c_str()
+                                       <<"\" found; replacing previous model"<<std::endl;
+               m_mesh_data[filename] = data;
                return true;
        }
 
@@ -971,7 +951,7 @@ void Client::request_media(const std::list<std::string> &file_requests)
        std::string s = os.str();
        SharedBuffer<u8> data((u8*)s.c_str(), s.size());
        // Send as reliable
-       Send(0, data, true);
+       Send(1, data, true);
        infostream<<"Client: Sending media request list to server ("
                        <<file_requests.size()<<" files)"<<std::endl;
 }
@@ -984,7 +964,7 @@ void Client::received_media()
        std::string s = os.str();
        SharedBuffer<u8> data((u8*)s.c_str(), s.size());
        // Send as reliable
-       Send(0, data, true);
+       Send(1, data, true);
        infostream<<"Client: Notifying server that we received all media"
                        <<std::endl;
 }
@@ -1624,11 +1604,6 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id)
                }
 
                m_media_downloader->step(this);
-               if (m_media_downloader->isDone()) {
-                       // might be done already if all media is in the cache
-                       delete m_media_downloader;
-                       m_media_downloader = NULL;
-               }
        }
        else if(command == TOCLIENT_MEDIA)
        {
@@ -1680,11 +1655,6 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id)
                        m_media_downloader->conventionalTransferDone(
                                        name, data, this);
                }
-
-               if (m_media_downloader->isDone()) {
-                       delete m_media_downloader;
-                       m_media_downloader = NULL;
-               }
        }
        else if(command == TOCLIENT_TOOLDEF)
        {
@@ -1858,6 +1828,10 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id)
                float size = readF1000(is);
                bool collisiondetection = readU8(is);
                std::string texture = deSerializeLongString(is);
+               bool vertical = false;
+               try {
+                       vertical = readU8(is);
+               } catch (...) {}
 
                ClientEvent event;
                event.type = CE_SPAWN_PARTICLE;
@@ -1869,6 +1843,7 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id)
                event.spawn_particle.size = size;
                event.spawn_particle.collisiondetection =
                                collisiondetection;
+               event.spawn_particle.vertical = vertical;
                event.spawn_particle.texture = new std::string(texture);
 
                m_client_event_queue.push_back(event);
@@ -1893,6 +1868,10 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id)
                bool collisiondetection = readU8(is);
                std::string texture = deSerializeLongString(is);
                u32 id = readU32(is);
+               bool vertical = false;
+               try {
+                       vertical = readU8(is);
+               } catch (...) {}
 
                ClientEvent event;
                event.type = CE_ADD_PARTICLESPAWNER;
@@ -1911,6 +1890,7 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id)
                event.add_particlespawner.minsize = minsize;
                event.add_particlespawner.maxsize = maxsize;
                event.add_particlespawner.collisiondetection = collisiondetection;
+               event.add_particlespawner.vertical = vertical;
                event.add_particlespawner.texture = new std::string(texture);
                event.add_particlespawner.id = id;
 
@@ -1945,6 +1925,10 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id)
                u32 dir          = readU32(is);
                v2f align        = readV2F1000(is);
                v2f offset       = readV2F1000(is);
+               v3f world_pos;
+               try{
+                       world_pos    = readV3F1000(is);
+               }catch(SerializationError &e) {};
 
                ClientEvent event;
                event.type = CE_HUDADD;
@@ -1959,6 +1943,7 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id)
                event.hudadd.dir    = dir;
                event.hudadd.align  = new v2f(align);
                event.hudadd.offset = new v2f(offset);
+               event.hudadd.world_pos = new v3f(world_pos);
                m_client_event_queue.push_back(event);
        }
        else if(command == TOCLIENT_HUDRM)
@@ -1977,6 +1962,7 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id)
        {
                std::string sdata;
                v2f v2fdata;
+               v3f v3fdata;
                u32 intdata = 0;
                
                std::string datastring((char *)&data[2], datasize - 2);
@@ -1990,6 +1976,8 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id)
                        v2fdata = readV2F1000(is);
                else if (stat == HUD_STAT_NAME || stat == HUD_STAT_TEXT)
                        sdata = deSerializeString(is);
+               else if (stat == HUD_STAT_WORLD_POS)
+                       v3fdata = readV3F1000(is);
                else
                        intdata = readU32(is);
                
@@ -1998,6 +1986,7 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id)
                event.hudchange.id      = id;
                event.hudchange.stat    = (HudElementStat)stat;
                event.hudchange.v2fdata = new v2f(v2fdata);
+               event.hudchange.v3fdata = new v3f(v3fdata);
                event.hudchange.sdata   = new std::string(sdata);
                event.hudchange.data    = intdata;
                m_client_event_queue.push_back(event);
@@ -2037,6 +2026,25 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id)
                        ((LocalPlayer *) player)->hotbar_selected_image = value;
                }
        }
+       else if(command == TOCLIENT_SET_SKY)
+       {
+               std::string datastring((char *)&data[2], datasize - 2);
+               std::istringstream is(datastring, std::ios_base::binary);
+
+               video::SColor *bgcolor = new video::SColor(readARGB8(is));
+               std::string *type = new std::string(deSerializeString(is));
+               u16 count = readU16(is);
+               std::vector<std::string> *params = new std::vector<std::string>;
+               for(size_t i=0; i<count; i++)
+                       params->push_back(deSerializeString(is));
+
+               ClientEvent event;
+               event.type = CE_SET_SKY;
+               event.set_sky.bgcolor = bgcolor;
+               event.set_sky.type = type;
+               event.set_sky.params = params;
+               m_client_event_queue.push_back(event);
+       }
        else
        {
                infostream<<"Client: Ignoring unknown command "
@@ -2846,3 +2854,31 @@ MtEventManager* Client::getEventManager()
        return m_event;
 }
 
+scene::IAnimatedMesh* Client::getMesh(const std::string &filename)
+{
+       std::map<std::string, std::string>::const_iterator i =
+                       m_mesh_data.find(filename);
+       if(i == m_mesh_data.end()){
+               errorstream<<"Client::getMesh(): Mesh not found: \""<<filename<<"\""
+                               <<std::endl;
+               return NULL;
+       }
+       const std::string &data = i->second;
+       scene::ISceneManager *smgr = m_device->getSceneManager();
+
+       // Create the mesh, remove it from cache and return it
+       // This allows unique vertex colors and other properties for each instance
+       Buffer<char> data_rw(data.c_str(), data.size()); // Const-incorrect Irrlicht
+       io::IFileSystem *irrfs = m_device->getFileSystem();
+       io::IReadFile *rfile = irrfs->createMemoryReadFile(
+                       *data_rw, data_rw.getSize(), filename.c_str());
+       assert(rfile);
+       scene::IAnimatedMesh *mesh = smgr->getMesh(rfile);
+       rfile->drop();
+       // NOTE: By playing with Irrlicht refcounts, maybe we could cache a bunch
+       // of uniquely named instances and re-use them
+       mesh->grab();
+       smgr->getMeshCache()->removeMesh(mesh);
+       return mesh;
+}
+