#include "settings.h"
#include "profiler.h"
#include "log.h"
+#include "nodemetadata.h"
+#include "nodedef.h"
+#include "tooldef.h"
+#include <IFileSystem.h>
/*
QueuedMeshUpdate
ScopeProfiler sp(g_profiler, "Client: Mesh making");
scene::SMesh *mesh_new = NULL;
- mesh_new = makeMapBlockMesh(q->data);
+ mesh_new = makeMapBlockMesh(q->data, m_gamedef);
MeshUpdateResult r;
r.p = q->p;
IrrlichtDevice *device,
const char *playername,
std::string password,
- MapDrawControl &control):
- m_mesh_update_thread(),
+ MapDrawControl &control,
+ IWritableTextureSource *tsrc,
+ IWritableToolDefManager *tooldef,
+ IWritableNodeDefManager *nodedef
+):
+ m_tsrc(tsrc),
+ m_tooldef(tooldef),
+ m_nodedef(nodedef),
+ m_mesh_update_thread(this),
m_env(
- new ClientMap(this, control,
+ new ClientMap(this, this, control,
device->getSceneManager()->getRootSceneNode(),
device->getSceneManager(), 666),
- device->getSceneManager()
+ device->getSceneManager(),
+ tsrc, this
),
m_con(PROTOCOL_ID, 512, CONNECTION_TIMEOUT, this),
m_device(device),
m_playerpos_send_timer = 0.0;
m_ignore_damage_timer = 0.0;
- //m_env_mutex.Init();
- //m_con_mutex.Init();
+ // Build main texture atlas, now that the GameDef exists (that is, us)
+ if(g_settings->getBool("enable_texture_atlas"))
+ m_tsrc->buildMainAtlas(this);
+ else
+ infostream<<"Not building texture atlas."<<std::endl;
+
+ // Update node textures
+ m_nodedef->updateTextures(m_tsrc);
+ // Start threads after setting up content definitions
m_mesh_update_thread.Start();
/*
Add local player
*/
{
- //JMutexAutoLock envlock(m_env_mutex); //bulk comment-out
-
- Player *player = new LocalPlayer();
+ Player *player = new LocalPlayer(this);
player->updateName(playername);
{
DSTACK(__FUNCTION_NAME);
//JMutexAutoLock lock(m_con_mutex); //bulk comment-out
- m_con.setTimeoutMs(0);
+ m_con.SetTimeoutMs(0);
m_con.Connect(address);
}
snprintf((char*)&data[23], PASSWORD_SIZE, "%s", m_password.c_str());
// This should be incremented in each version
- writeU16(&data[51], 3);
+ writeU16(&data[51], PROTOCOL_VERSION);
// Send as unreliable
Send(0, data, false);
counter = 0.0;
//JMutexAutoLock lock(m_con_mutex); //bulk comment-out
// connectedAndInitialized() is true, peer exists.
- con::Peer *peer = m_con.GetPeer(PEER_ID_SERVER);
- infostream<<"Client: avg_rtt="<<peer->avg_rtt<<std::endl;
+ float avg_rtt = m_con.GetPeerAvgRTT(PEER_ID_SERVER);
+ infostream<<"Client: avg_rtt="<<avg_rtt<<std::endl;
}
}
void Client::Receive()
{
DSTACK(__FUNCTION_NAME);
- u32 data_maxsize = 200000;
- Buffer<u8> data(data_maxsize);
+ SharedBuffer<u8> data;
u16 sender_peer_id;
u32 datasize;
{
//TimeTaker t1("con mutex and receive", m_device);
//JMutexAutoLock lock(m_con_mutex); //bulk comment-out
- datasize = m_con.Receive(sender_peer_id, *data, data_maxsize);
+ datasize = m_con.Receive(sender_peer_id, data);
}
//TimeTaker t1("ProcessData", m_device);
ProcessData(*data, datasize, sender_peer_id);
return;
}
- con::Peer *peer;
- {
- //JMutexAutoLock lock(m_con_mutex); //bulk comment-out
- // All data is coming from the server
- // PeerNotFoundException is handled by caller.
- peer = m_con.GetPeer(PEER_ID_SERVER);
- }
-
u8 ser_version = m_server_ser_ver;
//infostream<<"Client received command="<<(int)command<<std::endl;
//TimeTaker t1("TOCLIENT_ADDNODE");
MapNode n;
- n.deSerialize(&data[8], ser_version);
+ n.deSerialize(&data[8], ser_version, m_nodedef);
addNode(p, n);
}
Create a new block
*/
//infostream<<"Creating new"<<std::endl;
- block = new MapBlock(&m_env.getMap(), p);
+ block = new MapBlock(&m_env.getMap(), p, this);
block->deSerialize(istr, ser_version);
sector->insertBlock(block);
// Create a player if it doesn't exist
if(player == NULL)
{
- player = new RemotePlayer(
+ player = new RemotePlayer(this,
m_device->getSceneManager()->getRootSceneNode(),
m_device,
-1);
//t4.stop();
//TimeTaker t1("inventory.deSerialize()", m_device);
- player->inventory.deSerialize(is);
+ player->inventory.deSerialize(is, this);
//t1.stop();
m_inventory_updated = true;
<< peer_id << std::endl;
} else {
std::istringstream iss(itemstring);
- delete inv->changeItem(0, InventoryItem::deSerialize(iss));
+ delete inv->changeItem(0,
+ InventoryItem::deSerialize(iss, this));
infostream<<"Client: player item for peer " << peer_id << ": ";
player->getWieldItem()->serialize(infostream);
infostream<<std::endl;
event.deathscreen.camera_point_target_z = camera_point_target.Z;
m_client_event_queue.push_back(event);
}
+ else if(command == TOCLIENT_TOOLDEF)
+ {
+ infostream<<"Client: Received tool definitions"<<std::endl;
+
+ std::string datastring((char*)&data[2], datasize-2);
+ std::istringstream is(datastring, std::ios_base::binary);
+
+ // Stop threads while updating content definitions
+ m_mesh_update_thread.stop();
+
+ std::istringstream tmp_is(deSerializeLongString(is), std::ios::binary);
+ m_tooldef->deSerialize(tmp_is);
+
+ // Resume threads
+ m_mesh_update_thread.setRun(true);
+ m_mesh_update_thread.Start();
+ }
+ else if(command == TOCLIENT_TEXTURES)
+ {
+ infostream<<"Client: Received textures: packet size: "<<datasize
+ <<std::endl;
+
+ io::IFileSystem *irrfs = m_device->getFileSystem();
+ video::IVideoDriver *vdrv = m_device->getVideoDriver();
+
+ std::string datastring((char*)&data[2], datasize-2);
+ std::istringstream is(datastring, std::ios_base::binary);
+
+ // Stop threads while updating content definitions
+ m_mesh_update_thread.stop();
+
+ /*
+ u16 command
+ u32 number of textures
+ for each texture {
+ u16 length of name
+ string name
+ u32 length of data
+ data
+ }
+ */
+ int num_textures = readU32(is);
+ infostream<<"Client: Received textures: count: "<<num_textures
+ <<std::endl;
+ for(int i=0; i<num_textures; i++){
+ std::string name = deSerializeString(is);
+ std::string data = deSerializeLongString(is);
+ // Silly irrlicht's const-incorrectness
+ Buffer<char> data_rw(data.c_str(), data.size());
+ // Create an irrlicht memory file
+ io::IReadFile *rfile = irrfs->createMemoryReadFile(
+ *data_rw, data.size(), "_tempreadfile");
+ assert(rfile);
+ // Read image
+ video::IImage *img = vdrv->createImageFromFile(rfile);
+ if(!img){
+ errorstream<<"Client: Cannot create image from data of "
+ <<"received texture \""<<name<<"\""<<std::endl;
+ rfile->drop();
+ continue;
+ }
+ m_tsrc->insertSourceImage(name, img);
+ img->drop();
+ rfile->drop();
+ }
+
+ // Rebuild inherited images and recreate textures
+ m_tsrc->rebuildImagesAndTextures();
+
+ // Update texture atlas
+ if(g_settings->getBool("enable_texture_atlas"))
+ m_tsrc->buildMainAtlas(this);
+
+ // Update node textures
+ m_nodedef->updateTextures(m_tsrc);
+
+ // Resume threads
+ m_mesh_update_thread.setRun(true);
+ m_mesh_update_thread.Start();
+
+ ClientEvent event;
+ event.type = CE_TEXTURES_UPDATED;
+ m_client_event_queue.push_back(event);
+ }
else
{
infostream<<"Client: Ignoring unknown command "
float Client::getRTT(void)
{
- con::Peer *peer = m_con.GetPeerNoEx(PEER_ID_SERVER);
- if(!peer)
- return 0.0;
- return peer->avg_rtt;
+ try{
+ return m_con.GetPeerAvgRTT(PEER_ID_SERVER);
+ } catch(con::PeerNotFoundException &e){
+ return 1337;
+ }
+}
+
+// IGameDef interface
+// Under envlock
+IToolDefManager* Client::getToolDefManager()
+{
+ return m_tooldef;
+}
+INodeDefManager* Client::getNodeDefManager()
+{
+ return m_nodedef;
+}
+ITextureSource* Client::getTextureSource()
+{
+ return m_tsrc;
}