#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
*/
BEGIN_DEBUG_EXCEPTION_HANDLER
- while(getRun())
+ while(!StopRequested())
{
/*// Wait for output queue to flush.
// Allow 2 in queue, this makes less frametime jitter.
}
}
+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()
{
{
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;
}
// 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
writeU16(&data[53], CLIENT_PROTOCOL_VERSION_MAX);
// Send as unreliable
- Send(0, data, false);
+ Send(1, data, false);
}
// Not connected, return
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;
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)
{
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)
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;
}
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);
}
}
}
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;
}
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;
}
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;
}
}
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)
{
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)
{
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;
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);
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;
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;
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;
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)
{
std::string sdata;
v2f v2fdata;
+ v3f v3fdata;
u32 intdata = 0;
std::string datastring((char *)&data[2], datasize - 2);
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);
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);
((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 "
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;
+}
+