From e970a169d4b73372dfe2b1fff74cebaeb20d0050 Mon Sep 17 00:00:00 2001 From: Joel Leclerc Date: Sat, 5 May 2012 11:23:10 -0600 Subject: [PATCH] Fixed compressing, and started work on sending meshes (sorry for the dirty code) --- src/client.cpp | 407 +++++++++++++++++++++++++++++++++++---------- src/client.h | 14 +- src/clientserver.h | 37 +++++ src/server.cpp | 338 ++++++++++++++++++++++++++++++++++++- src/server.h | 27 +++ 5 files changed, 728 insertions(+), 95 deletions(-) diff --git a/src/client.cpp b/src/client.cpp index 8981f44..b663b23 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -48,6 +48,11 @@ static std::string getMediaCacheDir() return porting::path_user + DIR_DELIM + "cache" + DIR_DELIM + "media"; } +static std::string getMeshCacheDir() +{ + return porting::path_user + DIR_DELIM + "cache" + DIR_DELIM + "meshes"; +} + struct MediaRequest { std::string name; @@ -57,6 +62,15 @@ struct MediaRequest {} }; +struct MeshRequest +{ + std::string name; + + MeshRequest(const std::string &name_=""): + name(name_) + {} +}; + /* QueuedMeshUpdate */ @@ -259,8 +273,11 @@ Client::Client( m_password(password), m_access_denied(false), m_media_cache(getMediaCacheDir()), + m_mesh_cache(getMeshCacheDir()), m_media_receive_progress(0), m_media_received(false), + m_mesh_receive_progress(0), + m_meshes_received(false), m_itemdef_received(false), m_nodedef_received(false), m_time_of_day_set(false), @@ -853,18 +870,31 @@ bool Client::loadMedia(const std::string &data, const std::string &filename) m_sound->loadSoundData(name, data); return true; } + + errorstream<<"Client: Don't know how to load file \"" + < data_rw(data.c_str(), data.size()); - const char *mesh_ext[] = { + std::string name; + + const char *ext[] = { + ".png", ".jpg", ".bmp", ".tga", + ".pcx", ".ppm", ".psd", ".wal", ".rgb", ".3ds", ".obj", ".md2", ".md3", ".b3d", ".ply", ".stl", NULL }; - name = removeStringEnd(filename, mesh_ext); + name = removeStringEnd(filename, ext); if(name != "") { - verbosestream<<"Client: Attempting to load mesh " + verbosestream<<"Client: Attempting to load image " <<"file \""< file_requests; - - for(int i=0; i 0) { - //read file from cache - std::string name = deSerializeString(is); - std::string sha1_base64 = deSerializeString(is); - - // if name contains illegal characters, ignore the file - if(!string_allowed(name, TEXTURENAME_ALLOWED_CHARS)){ - errorstream<<"Client: ignoring illegal file name " - <<"sent by server: \""<= 2) + { m_media_receive_progress = (float)bunch_i / (float)(num_bunches - 1); + } else + { m_media_receive_progress = 1.0; + } if(bunch_i == num_bunches - 1) + { m_media_received = true; - int num_files = readU32(is); - infostream<<"Client: Received files: bunch "<= 1) + { + std::istringstream tmp_is(deSerializeLongString(is2), std::ios::binary); + std::ostringstream tmp_os; + decompressZlib(tmp_is, tmp_os); + std::istringstream is(tmp_os.str()); + infostream<<"Client: Received files: bunch "<::Node *n; + n = m_media_name_sha1_map.find(name); + if(n == NULL) + errorstream<<"The server sent a file that has not " + <<"been announced."< file_requests; + if(num_files > 0) + { + std::istringstream tmp_is(deSerializeLongString(is2), std::ios::binary); + std::ostringstream tmp_os; + decompressZlib(tmp_is, tmp_os); + std::istringstream is(tmp_os.str()); + for(int i=0; i::Iterator i = file_requests.begin(); + i != file_requests.end(); i++) { + os<name); + } + + // Make data buffer + std::string s = os.str(); + SharedBuffer data((u8*)s.c_str(), s.size()); + // Send as reliable + Send(0, data, true); + infostream<<"Client: Sending mesh request list to server (" + <= 2) + { + m_mesh_receive_progress = (float)bunch_i / (float)(num_bunches - 1); + } + else + { + m_mesh_receive_progress = 1.0; + } + if(bunch_i == num_bunches - 1) + { + m_meshes_received = true; + } + int num_files = readU32(is2); + if(num_files >= 1) + { + std::istringstream tmp_is(deSerializeLongString(is2), std::ios::binary); + std::ostringstream tmp_os; + decompressZlib(tmp_is, tmp_os); + std::istringstream is(tmp_os.str()); + infostream<<"Client: Received files: bunch "<::Node *n; + n = m_mesh_name_sha1_map.find(name); + if(n == NULL) + errorstream<<"The server sent a file that has not " + <<"been announced."< m_media_name_sha1_map; + FileCache m_mesh_cache; + // Mapping from media file name to SHA1 checksum + core::map m_mesh_name_sha1_map; float m_media_receive_progress; bool m_media_received; + float m_mesh_receive_progress; + bool m_meshes_received; bool m_itemdef_received; bool m_nodedef_received; friend class FarMesh; diff --git a/src/clientserver.h b/src/clientserver.h index fd7c86c..0a7149d 100644 --- a/src/clientserver.h +++ b/src/clientserver.h @@ -321,6 +321,33 @@ enum ToClientCommand /* u16 command */ + + TOCLIENT_MESH = 0x45, + /* + u16 command + u16 total number of texture bunches + u16 index of this bunch + u32 number of files in this bunch + for each file { + u16 length of name + string name + u32 length of data + data + } + */ + + TOCLIENT_ANNOUNCE_MESH = 0x46, + + /* + u16 command + u32 number of files + for each texture { + u16 length of name + string name + u16 length of sha1_digest + string sha1_digest + } + */ }; enum ToServerCommand @@ -511,6 +538,16 @@ enum ToServerCommand } */ + TOSERVER_REQUEST_MESH = 0x41, + /* + u16 command + u16 number of files requested + for each file { + u16 length of name + string name + } + */ + }; inline SharedBuffer makePacket_TOCLIENT_TIME_OF_DAY(u16 time, float time_speed) diff --git a/src/server.cpp b/src/server.cpp index d1a7dc3..87f7fb5 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -2282,6 +2282,9 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) // Send media announcement sendMediaAnnouncement(peer_id); + + // Send mesh announcement + //sendMeshAnnouncement(peer_id); // Send privileges SendPlayerPrivileges(peer_id); @@ -2926,7 +2929,8 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) // ActiveObject is added to environment in AsyncRunStep after // the previous addition has been succesfully removed } - else if(command == TOSERVER_REQUEST_MEDIA) { + else if(command == TOSERVER_REQUEST_MEDIA) + { std::string datastring((char*)&data[2], datasize-2); std::istringstream is(datastring, std::ios_base::binary); @@ -2950,6 +2954,31 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) // (definitions and files) getClient(peer_id)->definitions_sent = true; } + else if(command == TOSERVER_REQUEST_MESH) + { + std::string datastring((char*)&data[2], datasize-2); + std::istringstream is(datastring, std::ios_base::binary); + + core::list tosend; + u16 numfiles = readU16(is); + + infostream<<"Sending "<definitions_sent = true; + } else if(command == TOSERVER_INTERACT) { std::string datastring((char*)&data[2], datasize-2); @@ -4219,7 +4248,7 @@ void Server::sendMediaAnnouncement(u16 peer_id) */ writeU16(os, TOCLIENT_ANNOUNCE_MEDIA); - writeU16(tmp_os, file_announcements.size()); + writeU16(os, file_announcements.size()); for(core::list::Iterator j = file_announcements.begin(); @@ -4347,9 +4376,9 @@ void Server::sendRequestedMedia(u16 peer_id, */ writeU16(os, TOCLIENT_MEDIA); - writeU16(tmp_os, num_bunches); - writeU16(tmp_os, i); - writeU32(tmp_os, file_bunches[i].size()); + writeU16(os, num_bunches); + writeU16(os, i); + writeU32(os, file_bunches[i].size()); for(core::list::Iterator j = file_bunches[i].begin(); @@ -4373,6 +4402,305 @@ void Server::sendRequestedMedia(u16 peer_id, } } +void Server::fillMeshCache() +{ + DSTACK(__FUNCTION_NAME); + + infostream<<"Server: Calculating mesh file checksums"< paths; + for(core::list::Iterator i = m_mods.begin(); + i != m_mods.end(); i++){ + const ModSpec &mod = *i; + paths.push_back(mod.path + DIR_DELIM + "meshes"); + paths.push_back(mod.path + DIR_DELIM + "meshtextures"); + } + + // Collect media file information from paths into cache + for(std::list::iterator i = paths.begin(); + i != paths.end(); i++) + { + std::string meshpath = *i; + std::vector dirlist = fs::GetDirListing(meshpath); + for(u32 j=0; jm_mesh[filename] = MeshInfo(filepath, sha1_base64); + verbosestream<<"Server: "< file_announcements; + + for(std::map::iterator i = m_mesh.begin(); + i != m_mesh.end(); i++){ + // Put in list + file_announcements.push_back( + SendableMeshAnnouncement(i->first, i->second.sha1_digest)); + } + + // Make packet + std::ostringstream os(std::ios_base::binary); + std::ostringstream tmp_os(std::ios_base::binary); + + /* + u16 command + u32 number of files + for each texture { + u16 length of name + string name + u16 length of sha1_digest + string sha1_digest + } + */ + + writeU16(os, TOCLIENT_ANNOUNCE_MESH); + writeU16(tmp_os, file_announcements.size()); + + for(core::list::Iterator + j = file_announcements.begin(); + j != file_announcements.end(); j++){ + tmp_os<name); + tmp_os<sha1_digest); + } + + // Make data buffer + std::ostringstream tmp_os2(std::ios::binary); + compressZlib(tmp_os.str(), tmp_os2); + os< data((u8*)s.c_str(), s.size()); + + // Send as reliable + m_con.Send(peer_id, 0, data, true); + +} + +struct SendableMesh +{ + std::string name; + std::string path; + std::string data; + + SendableMesh(const std::string &name_="", const std::string path_="", + const std::string &data_=""): + name(name_), + path(path_), + data(data_) + {} +}; + +void Server::sendRequestedMesh(u16 peer_id, + const core::list &tosend) +{ + DSTACK(__FUNCTION_NAME); + + verbosestream<<"Server::sendRequestedMesh(): " + <<"Sending files to client"< > file_bunches; + file_bunches.push_back(core::list()); + + u32 file_size_bunch_total = 0; + + for(core::list::ConstIterator i = tosend.begin(); + i != tosend.end(); i++) + { + if(m_mesh.find(i->name) == m_mesh.end()) + { + errorstream<<"Server::sendRequestedMesh(): Client asked for " + <<"unknown file \""<<(i->name)<<"\""<= bytes_per_bunch) + { + file_bunches.push_back(core::list()); + file_size_bunch_total = 0; + } + + } + + /* Create and send packets */ + + u32 num_bunches = file_bunches.size(); + for(u32 i=0; i::Iterator + j = file_bunches[i].begin(); + j != file_bunches[i].end(); j++){ + tmp_os<name); + tmp_os<data); + } + + // Make data buffer + std::ostringstream tmp_os2(std::ios::binary); + compressZlib(tmp_os.str(), tmp_os2); + os< &tosend); + void fillMeshCache(); + void sendMeshAnnouncement(u16 peer_id); + void sendRequestedMesh(u16 peer_id, + const core::list &tosend); /* Something random @@ -826,6 +852,7 @@ private: friend class RemoteClient; std::map m_media; + std::map m_mesh; /* Sounds