diff options
-rw-r--r-- | src/client.cpp | 206 | ||||
-rw-r--r-- | src/client.h | 3 | ||||
-rw-r--r-- | src/filecache.cpp | 54 | ||||
-rw-r--r-- | src/filecache.h | 33 | ||||
-rw-r--r-- | src/game.cpp | 2 | ||||
-rw-r--r-- | src/server.cpp | 10 | ||||
-rw-r--r-- | src/sound.h | 15 | ||||
-rw-r--r-- | src/sound_openal.cpp | 40 | ||||
-rw-r--r-- | src/tile.cpp | 6 |
9 files changed, 183 insertions, 186 deletions
diff --git a/src/client.cpp b/src/client.cpp index 56555804e..6da26abfb 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -40,6 +40,8 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "clientmap.h" #include "filecache.h" #include "sound.h" +#include "utility_string.h" +#include "hex.h" static std::string getMediaCacheDir() { @@ -795,6 +797,66 @@ void Client::step(float dtime) } } +bool Client::loadMedia(const std::string &data, const std::string &filename) +{ + // Silly irrlicht's const-incorrectness + Buffer<char> data_rw(data.c_str(), data.size()); + + std::string name; + + const char *image_ext[] = { + ".png", ".jpg", ".bmp", ".tga", + ".pcx", ".ppm", ".psd", ".wal", ".rgb", + NULL + }; + name = removeStringEnd(filename, image_ext); + if(name != "") + { + verbosestream<<"Client: Attempting to load image " + <<"file \""<<filename<<"\""<<std::endl; + + io::IFileSystem *irrfs = m_device->getFileSystem(); + video::IVideoDriver *vdrv = m_device->getVideoDriver(); + + // Create an irrlicht memory file + io::IReadFile *rfile = irrfs->createMemoryReadFile( + *data_rw, data_rw.getSize(), "_tempreadfile"); + assert(rfile); + // Read image + video::IImage *img = vdrv->createImageFromFile(rfile); + if(!img){ + errorstream<<"Client: Cannot create image from data of " + <<"file \""<<filename<<"\""<<std::endl; + rfile->drop(); + return false; + } + else { + m_tsrc->insertSourceImage(filename, img); + img->drop(); + rfile->drop(); + return true; + } + } + + const char *sound_ext[] = { + "0.ogg", "1.ogg", "2.ogg", "3.ogg", "4.ogg", + "5.ogg", "6.ogg", "7.ogg", "8.ogg", "9.ogg", + ".ogg", NULL + }; + name = removeStringEnd(filename, sound_ext); + if(name != "") + { + verbosestream<<"Client: Attempting to load sound " + <<"file \""<<filename<<"\""<<std::endl; + m_sound->loadSoundData(name, data); + return true; + } + + errorstream<<"Client: Don't know how to load file \"" + <<filename<<"\""<<std::endl; + return false; +} + // Virtual methods from con::PeerHandler void Client::peerAdded(con::Peer *peer) { @@ -1393,9 +1455,6 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id) } else if(command == TOCLIENT_ANNOUNCE_MEDIA) { - 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); @@ -1410,13 +1469,11 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id) core::list<MediaRequest> file_requests; - for(int i=0; i<num_files; i++){ - - bool file_found = false; - + for(int i=0; i<num_files; i++) + { //read file from cache std::string name = deSerializeString(is); - std::string sha1_file = deSerializeString(is); + std::string sha1_base64 = deSerializeString(is); // if name contains illegal characters, ignore the file if(!string_allowed(name, TEXTURENAME_ALLOWED_CHARS)){ @@ -1425,86 +1482,46 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id) continue; } - std::string sha1_decoded = base64_decode(sha1_file); + std::string sha1_raw = base64_decode(sha1_base64); + std::string sha1_hex = hex_encode(sha1_raw); std::ostringstream tmp_os(std::ios_base::binary); - bool file_in_cache = m_media_cache.loadByChecksum(sha1_decoded, - tmp_os); - m_media_name_sha1_map.set(name, sha1_decoded); + bool found_in_cache = m_media_cache.load_sha1(sha1_raw, tmp_os); + m_media_name_sha1_map.set(name, sha1_raw); - if(file_in_cache) + // If found in cache, try to load it from there + if(found_in_cache) { - SHA1 sha1; - sha1.addBytes(tmp_os.str().c_str(), tmp_os.str().length()); - - unsigned char *digest = sha1.getDigest(); - - std::string digest_string = base64_encode(digest, 20); - - if (digest_string == sha1_file) { - // Silly irrlicht's const-incorrectness - Buffer<char> data_rw(tmp_os.str().c_str(), tmp_os.str().size()); - - // Create an irrlicht memory file - io::IReadFile *rfile = irrfs->createMemoryReadFile( - *data_rw, tmp_os.str().size(), "_tempreadfile"); - assert(rfile); - // Read image - video::IImage *img = vdrv->createImageFromFile(rfile); - if(!img){ - infostream<<"Client: Cannot create image from data of " - <<"received file \""<<name<<"\""<<std::endl; - rfile->drop(); - } - else { - m_tsrc->insertSourceImage(name, img); - img->drop(); - rfile->drop(); - - file_found = true; - } + bool success = loadMedia(tmp_os.str(), name); + if(success){ + verbosestream<<"Client: Loaded cached media: " + <<sha1_hex<<" \""<<name<<"\""<<std::endl; + continue; + } else{ + infostream<<"Client: Failed to load cached media: " + <<sha1_hex<<" \""<<name<<"\""<<std::endl; } - else { - infostream<<"Client::Media cached sha1 hash not matching server hash: " - <<name << ": server ->"<<sha1_file <<" client -> "<<digest_string<<std::endl; - } - - free(digest); - } - - //add file request - if (!file_found) { - infostream<<"Client: Adding file to request list: \"" - <<name<<"\""<<std::endl; - file_requests.push_back(MediaRequest(name)); } - + // Didn't load from cache; queue it to be requested + verbosestream<<"Client: Adding file to request list: \"" + <<sha1_hex<<" \""<<name<<"\""<<std::endl; + file_requests.push_back(MediaRequest(name)); } ClientEvent event; event.type = CE_TEXTURES_UPDATED; m_client_event_queue.push_back(event); - - //send Media request /* - u16 command - u16 number of files requested - for each file { - u16 length of name - string name - } - */ + u16 command + u16 number of files requested + for each file { + u16 length of name + string name + } + */ std::ostringstream os(std::ios_base::binary); - u8 buf[12]; - - - // Write command - writeU16(buf, TOSERVER_REQUEST_MEDIA); - os.write((char*)buf, 2); - - writeU16(buf,file_requests.size()); - os.write((char*)buf, 2); - + writeU16(os, TOSERVER_REQUEST_MEDIA); + writeU16(os, file_requests.size()); for(core::list<MediaRequest>::Iterator i = file_requests.begin(); i != file_requests.end(); i++) { @@ -1521,11 +1538,6 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id) } else if(command == TOCLIENT_MEDIA) { - verbosestream<<"Client received TOCLIENT_MEDIA"<<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); @@ -1547,7 +1559,10 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id) */ int num_bunches = readU16(is); int bunch_i = readU16(is); - m_media_receive_progress = (float)bunch_i / (float)(num_bunches - 1); + if(num_bunches >= 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); @@ -1564,19 +1579,14 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id) <<"sent by server: \""<<name<<"\""<<std::endl; continue; } - - // 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 file \""<<name<<"\""<<std::endl; - rfile->drop(); + + bool success = loadMedia(data, name); + if(success){ + verbosestream<<"Client: Loaded received media: " + <<"\""<<name<<"\". Caching."<<std::endl; + } else{ + infostream<<"Client: Failed to load received media: " + <<"\""<<name<<"\". Not caching."<<std::endl; continue; } @@ -1591,14 +1601,10 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id) n = m_media_name_sha1_map.find(name); if(n == NULL) errorstream<<"The server sent a file that has not " - <<"been announced."<<std::endl; + <<"been announced."<<std::endl; else - m_media_cache.updateByChecksum(n->getValue(), data); + m_media_cache.update_sha1(data); } - - m_tsrc->insertSourceImage(name, img); - img->drop(); - rfile->drop(); } ClientEvent event; diff --git a/src/client.h b/src/client.h index b15dbed54..302dd8005 100644 --- a/src/client.h +++ b/src/client.h @@ -315,6 +315,9 @@ public: private: + // Insert a media file appropriately into the appropriate manager + bool loadMedia(const std::string &data, const std::string &filename); + // Virtual methods from con::PeerHandler void peerAdded(con::Peer *peer); void deletingPeer(con::Peer *peer, bool timeout); diff --git a/src/filecache.cpp b/src/filecache.cpp index 5ba8ef5cc..0ef2dd11e 100644 --- a/src/filecache.cpp +++ b/src/filecache.cpp @@ -24,6 +24,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "filesys.h" #include "utility.h" #include "hex.h" +#include "sha1.h" #include <string> #include <iostream> @@ -34,7 +35,7 @@ bool FileCache::loadByPath(const std::string &path, std::ostream &os) if(!fis.good()){ verbosestream<<"FileCache: File not found in cache: " - <<path<<std::endl; + <<path<<std::endl; return false; } @@ -53,7 +54,7 @@ bool FileCache::loadByPath(const std::string &path, std::ostream &os) } if(bad){ errorstream<<"FileCache: Failed to read file from cache: \"" - <<path<<"\""<<std::endl; + <<path<<"\""<<std::endl; } return !bad; @@ -67,7 +68,7 @@ bool FileCache::updateByPath(const std::string &path, const std::string &data) if(!file.good()) { errorstream<<"FileCache: Can't write to file at " - <<path<<std::endl; + <<path<<std::endl; return false; } @@ -77,34 +78,41 @@ bool FileCache::updateByPath(const std::string &path, const std::string &data) return !file.fail(); } -bool FileCache::loadByName(const std::string &name, std::ostream &os) -{ - std::string path = m_dir + DIR_DELIM + name; - return loadByPath(path, os); -} - - -bool FileCache::updateByName(const std::string &name, const std::string &data) +bool FileCache::update(const std::string &name, const std::string &data) { std::string path = m_dir + DIR_DELIM + name; return updateByPath(path, data); } - -std::string FileCache::getPathFromChecksum(const std::string &checksum) +bool FileCache::update_sha1(const std::string &data) { - std::string checksum_hex = hex_encode(checksum.c_str(), checksum.length()); - return m_dir + DIR_DELIM + checksum_hex; + SHA1 sha1; + sha1.addBytes(data.c_str(), data.size()); + unsigned char *digest = sha1.getDigest(); + std::string sha1_raw((char*)digest, 20); + free(digest); + std::string sha1_hex = hex_encode(sha1_raw); + return update(sha1_hex, data); } - -bool FileCache::loadByChecksum(const std::string &checksum, std::ostream &os) +bool FileCache::load(const std::string &name, std::ostream &os) { - std::string path = getPathFromChecksum(checksum); + std::string path = m_dir + DIR_DELIM + name; return loadByPath(path, os); } - -bool FileCache::updateByChecksum(const std::string &checksum, - const std::string &data) +bool FileCache::load_sha1(const std::string &sha1_raw, std::ostream &os) { - std::string path = getPathFromChecksum(checksum); - return updateByPath(path, data); + std::ostringstream tmp_os(std::ios_base::binary); + if(!load(hex_encode(sha1_raw), tmp_os)) + return false; + SHA1 sha1; + sha1.addBytes(tmp_os.str().c_str(), tmp_os.str().length()); + unsigned char *digest = sha1.getDigest(); + std::string sha1_real_raw((char*)digest, 20); + free(digest); + if(sha1_real_raw != sha1_raw){ + verbosestream<<"FileCache["<<m_dir<<"]: filename "<<sha1_real_raw + <<" mismatches actual checksum"<<std::endl; + return false; + } + os<<tmp_os.str(); + return true; } diff --git a/src/filecache.h b/src/filecache.h index ae3fbc602..97203e635 100644 --- a/src/filecache.h +++ b/src/filecache.h @@ -34,39 +34,16 @@ public: m_dir(dir) { } - - /* - Searches the cache for a file with a given name. - If the file is found, lookup copies it into 'os' and - returns true. Otherwise false is returned. - */ - bool loadByName(const std::string &name, std::ostream &os); - - /* - Stores a file in the cache based on its name. - Returns true on success, false otherwise. - */ - bool updateByName(const std::string &name, const std::string &data); - - /* - Loads a file based on a check sum, which may be any kind of - rather unique byte sequence. Returns true, if the file could - be written into os, false otherwise. - */ - bool loadByChecksum(const std::string &checksum, std::ostream &os); - - /* - Stores a file in the cache based on its checksum. - Returns true on success, false otherwise. - */ - bool updateByChecksum(const std::string &checksum, const std::string &data); - + + bool update(const std::string &name, const std::string &data); + bool update_sha1(const std::string &data); + bool load(const std::string &name, std::ostream &os); + bool load_sha1(const std::string &sha1_raw, std::ostream &os); private: std::string m_dir; bool loadByPath(const std::string &path, std::ostream &os); bool updateByPath(const std::string &path, const std::string &data); - std::string getPathFromChecksum(const std::string &checksum); }; #endif diff --git a/src/game.cpp b/src/game.cpp index eeb5d02e4..aff1f1984 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -880,7 +880,7 @@ public: void fetchSounds(const std::string &name, std::set<std::string> &dst_paths, - std::set<std::vector<char> > &dst_datas) + std::set<std::string> &dst_datas) { if(m_fetched.count(name)) return; diff --git a/src/server.cpp b/src/server.cpp index 13a8ebf7d..02734bbc0 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -51,6 +51,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "utility_string.h" #include "sound.h" // dummySoundManager #include "event_manager.h" +#include "hex.h" #define PP(x) "("<<(x).X<<","<<(x).Y<<","<<(x).Z<<")" @@ -3996,14 +3997,13 @@ void Server::fillMediaCache() sha1.addBytes(tmp_os.str().c_str(), tmp_os.str().length()); unsigned char *digest = sha1.getDigest(); - std::string digest_string = base64_encode(digest, 20); - + std::string sha1_base64 = base64_encode(digest, 20); + std::string sha1_hex = hex_encode((char*)digest, 20); free(digest); // Put in list - this->m_media[filename] = MediaInfo(filepath, digest_string); - verbosestream<<"Server: sha1 for "<<filename<<"\tis " - <<digest_string<<std::endl; + this->m_media[filename] = MediaInfo(filepath, sha1_base64); + verbosestream<<"Server: "<<sha1_hex<<" is "<<filename<<std::endl; } } } diff --git a/src/sound.h b/src/sound.h index f9c1ea0ce..c342f4e5e 100644 --- a/src/sound.h +++ b/src/sound.h @@ -22,7 +22,6 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "irrlichttypes.h" #include <string> -#include <vector> #include <set> class OnDemandSoundFetcher @@ -30,7 +29,7 @@ class OnDemandSoundFetcher public: virtual void fetchSounds(const std::string &name, std::set<std::string> &dst_paths, - std::set<std::vector<char> > &dst_datas) = 0; + std::set<std::string> &dst_datas) = 0; }; struct SimpleSoundSpec @@ -53,10 +52,10 @@ public: // Multiple sounds can be loaded per name; when played, the sound // should be chosen randomly from alternatives // Return value determines success/failure - virtual bool loadSound(const std::string &name, + virtual bool loadSoundFile(const std::string &name, const std::string &filepath) = 0; - virtual bool loadSound(const std::string &name, - const std::vector<char> &filedata) = 0; + virtual bool loadSoundData(const std::string &name, + const std::string &filedata) = 0; virtual void updateListener(v3f pos, v3f vel, v3f at, v3f up) = 0; @@ -79,10 +78,10 @@ public: class DummySoundManager: public ISoundManager { public: - virtual bool loadSound(const std::string &name, + virtual bool loadSoundFile(const std::string &name, const std::string &filepath) {return true;} - virtual bool loadSound(const std::string &name, - const std::vector<char> &filedata) {return true;} + virtual bool loadSoundData(const std::string &name, + const std::string &filedata) {return true;} void updateListener(v3f pos, v3f vel, v3f at, v3f up) {} int playSound(const std::string &name, bool loop, float volume) {return 0;} diff --git a/src/sound_openal.cpp b/src/sound_openal.cpp index 6f9ff3bd6..f7bce6546 100644 --- a/src/sound_openal.cpp +++ b/src/sound_openal.cpp @@ -286,22 +286,6 @@ public: return bufs[j]; } - bool loadSound(const std::string &name, - const std::string &filepath) - { - SoundBuffer *buf = loadOggFile(filepath); - if(buf) - addBuffer(name, buf); - return false; - } - bool loadSound(const std::string &name, - const std::vector<char> &filedata) - { - errorstream<<"OpenALSoundManager: Loading from filedata not" - " implemented"<<std::endl; - return false; - } - PlayingSound* createPlayingSound(SoundBuffer *buf, bool loop, float volume) { @@ -392,15 +376,15 @@ public: if(!m_fetcher) return NULL; std::set<std::string> paths; - std::set<std::vector<char> > datas; + std::set<std::string> datas; m_fetcher->fetchSounds(name, paths, datas); for(std::set<std::string>::iterator i = paths.begin(); i != paths.end(); i++){ - loadSound(name, *i); + loadSoundFile(name, *i); } - for(std::set<std::vector<char> >::iterator i = datas.begin(); + for(std::set<std::string>::iterator i = datas.begin(); i != datas.end(); i++){ - loadSound(name, *i); + loadSoundData(name, *i); } return getBuffer(name); } @@ -439,6 +423,22 @@ public: /* Interface */ + bool loadSoundFile(const std::string &name, + const std::string &filepath) + { + SoundBuffer *buf = loadOggFile(filepath); + if(buf) + addBuffer(name, buf); + return false; + } + bool loadSoundData(const std::string &name, + const std::string &filedata) + { + errorstream<<"OpenALSoundManager: Loading from filedata not" + " implemented"<<std::endl; + return false; + } + void updateListener(v3f pos, v3f vel, v3f at, v3f up) { m_listener_pos = pos; diff --git a/src/tile.cpp b/src/tile.cpp index 4af7a3272..c35952b78 100644 --- a/src/tile.cpp +++ b/src/tile.cpp @@ -29,6 +29,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "mapnode.h" // For texture atlas making #include "nodedef.h" // For texture atlas making #include "gamedef.h" +#include "utility_string.h" /* A cache from texture name to texture path @@ -82,7 +83,10 @@ static std::string getImagePath(std::string path) "pcx", "ppm", "psd", "wal", "rgb", NULL }; - + // If there is no extension, add one + if(removeStringEnd(path, extensions) == "") + path = path + ".png"; + // Check paths until something is found to exist const char **ext = extensions; do{ bool r = replace_ext(path, *ext); |