Guest User

minetest client side texture cache try 3

a guest
Jan 1st, 2012
179
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 18.62 KB | None | 0 0
  1. --- celeron55-minetest-6957930.orig/src/clientserver.h 2011-12-11 15:52:19.000000000 +0100
  2. +++ celeron55-minetest-6957930/src/clientserver.h 2012-01-02 00:45:57.000000000 +0100
  3. @@ -235,6 +235,19 @@
  4. u32 length of the next item
  5. serialized CraftiItemDefManager
  6. */
  7. +
  8. + TOCLIENT_ANNOUNCE_TEXTURES = 0x3c,
  9. +
  10. + /*
  11. + u16 command
  12. + u32 number of textures
  13. + for each texture {
  14. + u16 length of name
  15. + string name
  16. + u16 length of sha1_digest
  17. + string sha1_digest
  18. + }
  19. + */
  20. };
  21.  
  22. enum ToServerCommand
  23. @@ -408,6 +421,17 @@
  24. (Obsoletes TOSERVER_GROUND_ACTION and TOSERVER_CLICK_ACTIVEOBJECT.)
  25. */
  26.  
  27. + TOSERVER_REQUEST_TEXTURES = 0x40,
  28. +
  29. + /*
  30. + u16 command
  31. + u16 number of textures requested
  32. + for each texture {
  33. + u16 length of name
  34. + string name
  35. + }
  36. + */
  37. +
  38. };
  39.  
  40. inline SharedBuffer<u8> makePacket_TOCLIENT_TIME_OF_DAY(u16 time)
  41. --- celeron55-minetest-6957930.orig/src/server.h 2011-12-11 15:52:19.000000000 +0100
  42. +++ celeron55-minetest-6957930/src/server.h 2012-01-02 01:11:16.000000000 +0100
  43. @@ -235,6 +235,28 @@
  44. u16 peer_id;
  45. };
  46.  
  47. +struct TextureRequest
  48. +{
  49. + std::string name;
  50. +
  51. + TextureRequest(const std::string &name_=""):
  52. + name(name_)
  53. + {}
  54. +};
  55. +
  56. +struct TextureInformation
  57. +{
  58. + std::string path;
  59. + std::string sha1_digest;
  60. +
  61. + TextureInformation(const std::string path_="",
  62. + const std::string sha1_digest_=""):
  63. + path(path_),
  64. + sha1_digest(sha1_digest_)
  65. + {
  66. + }
  67. +};
  68. +
  69. class RemoteClient
  70. {
  71. public:
  72. @@ -563,7 +585,11 @@
  73. // Sends blocks to clients (locks env and con on its own)
  74. void SendBlocks(float dtime);
  75.  
  76. - void SendTextures(u16 peer_id);
  77. + void PrepareTextures();
  78. +
  79. + void SendTextureAnnouncement(u16 peer_id);
  80. +
  81. + void SendTexturesRequested(u16 peer_id,core::list<TextureRequest> tosend);
  82.  
  83. /*
  84. Something random
  85. @@ -743,6 +769,8 @@
  86.  
  87. friend class EmergeThread;
  88. friend class RemoteClient;
  89. +
  90. + std::map<std::string,TextureInformation> m_Textures;
  91. };
  92.  
  93. /*
  94. --- celeron55-minetest-6957930.orig/src/server.cpp 2011-12-11 15:52:19.000000000 +0100
  95. +++ celeron55-minetest-6957930/src/server.cpp 2012-01-02 01:42:54.000000000 +0100
  96. @@ -48,6 +48,8 @@
  97. #include "mapgen.h"
  98. #include "content_abm.h"
  99. #include "mods.h"
  100. +#include "sha1.h"
  101. +#include "base64.h"
  102.  
  103. #define PP(x) "("<<(x).X<<","<<(x).Y<<","<<(x).Z<<")"
  104.  
  105. @@ -924,6 +926,9 @@
  106. }
  107. }
  108.  
  109. + // Read Textures and calculate sha1 sums
  110. + PrepareTextures();
  111. +
  112. // Initialize Environment
  113.  
  114. m_env = new ServerEnvironment(new ServerMap(mapsavedir, this), m_lua,
  115. @@ -2105,8 +2110,8 @@
  116. // Send CraftItem definitions
  117. SendCraftItemDef(m_con, peer_id, m_craftitemdef);
  118.  
  119. - // Send textures
  120. - SendTextures(peer_id);
  121. + // Send texture announcement
  122. + SendTextureAnnouncement(peer_id);
  123.  
  124. // Send player info to all players
  125. //SendPlayerInfos();
  126. @@ -2820,6 +2825,26 @@
  127. // ActiveObject is added to environment in AsyncRunStep after
  128. // the previous addition has been succesfully removed
  129. }
  130. + else if(command == TOSERVER_REQUEST_TEXTURES) {
  131. + std::string datastring((char*)&data[2], datasize-2);
  132. + std::istringstream is(datastring, std::ios_base::binary);
  133. +
  134. + infostream<<"TOSERVER_REQUEST_TEXTURES: "<<std::endl;
  135. +
  136. + core::list<TextureRequest> tosend;
  137. +
  138. + u16 numtextures = readU16(is);
  139. +
  140. + for(int i = 0; i < numtextures; i++) {
  141. +
  142. + std::string name = deSerializeString(is);
  143. +
  144. + tosend.push_back(TextureRequest(name));
  145. + infostream<<"TOSERVER_REQUEST_TEXTURES: requested texture " << name <<std::endl;
  146. + }
  147. +
  148. + SendTexturesRequested(peer_id, tosend);
  149. + }
  150. else if(command == TOSERVER_INTERACT)
  151. {
  152. std::string datastring((char*)&data[2], datasize-2);
  153. @@ -4174,6 +4199,124 @@
  154. }
  155. }
  156.  
  157. +void Server::PrepareTextures() {
  158. + DSTACK(__FUNCTION_NAME);
  159. +
  160. + infostream<<"Server::PrepareTextures(): Calculate sha1 sums of textures"<<std::endl;
  161. +
  162. + for(core::list<ModSpec>::Iterator i = m_mods.begin();
  163. + i != m_mods.end(); i++){
  164. + const ModSpec &mod = *i;
  165. + std::string texturepath = mod.path + DIR_DELIM + "textures";
  166. + std::vector<fs::DirListNode> dirlist = fs::GetDirListing(texturepath);
  167. + for(u32 j=0; j<dirlist.size(); j++){
  168. + if(dirlist[j].dir) // Ignode dirs
  169. + continue;
  170. + std::string tname = dirlist[j].name;
  171. + std::string tpath = texturepath + DIR_DELIM + tname;
  172. + // Read data
  173. + std::ifstream fis(tpath.c_str(), std::ios_base::binary);
  174. + if(fis.good() == false){
  175. + errorstream<<"Server::PrepareTextures(): Could not open \""
  176. + <<tname<<"\" for reading"<<std::endl;
  177. + continue;
  178. + }
  179. + std::ostringstream tmp_os(std::ios_base::binary);
  180. + bool bad = false;
  181. + for(;;){
  182. + char buf[1024];
  183. + fis.read(buf, 1024);
  184. + std::streamsize len = fis.gcount();
  185. + tmp_os.write(buf, len);
  186. + if(fis.eof())
  187. + break;
  188. + if(!fis.good()){
  189. + bad = true;
  190. + break;
  191. + }
  192. + }
  193. + if(bad){
  194. + errorstream<<"Server::PrepareTextures(): Failed to read \""
  195. + <<tname<<"\""<<std::endl;
  196. + continue;
  197. + }
  198. +
  199. + SHA1 sha1;
  200. + sha1.addBytes(tmp_os.str().c_str(), tmp_os.str().length());
  201. +
  202. + unsigned char *digest = sha1.getDigest();
  203. + std::string digest_string = base64_encode(digest, 20);
  204. +
  205. + delete(digest);
  206. +
  207. + // Put in list
  208. + this->m_Textures[tname] = TextureInformation(tpath,digest_string);
  209. + infostream<<"Server::PrepareTextures(): added sha1 for "<< tname <<std::endl;
  210. + }
  211. + }
  212. +}
  213. +
  214. +struct SendableTextureAnnouncement
  215. + {
  216. + std::string name;
  217. + std::string sha1_digest;
  218. +
  219. + SendableTextureAnnouncement(const std::string name_="",
  220. + const std::string sha1_digest_=""):
  221. + name(name_),
  222. + sha1_digest(sha1_digest_)
  223. + {
  224. + }
  225. + };
  226. +
  227. +void Server::SendTextureAnnouncement(u16 peer_id){
  228. + DSTACK(__FUNCTION_NAME);
  229. +
  230. + infostream<<"Server::SendTextureAnnouncement(): Calculate sha1 sums of textures and send to client"<<std::endl;
  231. +
  232. + core::list<SendableTextureAnnouncement> texture_announcements;
  233. +
  234. + for (std::map<std::string,TextureInformation>::iterator i = m_Textures.begin();i != m_Textures.end(); i++ ) {
  235. +
  236. + // Put in list
  237. + texture_announcements.push_back(
  238. + SendableTextureAnnouncement(i->first, i->second.sha1_digest));
  239. + }
  240. +
  241. + //send announcements
  242. +
  243. + /*
  244. + u16 command
  245. + u32 number of textures
  246. + for each texture {
  247. + u16 length of name
  248. + string name
  249. + u16 length of digest string
  250. + string sha1_digest
  251. + }
  252. + */
  253. + std::ostringstream os(std::ios_base::binary);
  254. +
  255. + writeU16(os, TOCLIENT_ANNOUNCE_TEXTURES);
  256. + writeU16(os, texture_announcements.size());
  257. +
  258. + for(core::list<SendableTextureAnnouncement>::Iterator
  259. + j = texture_announcements.begin();
  260. + j != texture_announcements.end(); j++){
  261. + os<<serializeString(j->name);
  262. + os<<serializeString(j->sha1_digest);
  263. + }
  264. +
  265. + // Make data buffer
  266. + std::string s = os.str();
  267. + infostream<<"Server::SendTextureAnnouncement(): Send to client"<<std::endl;
  268. + SharedBuffer<u8> data((u8*)s.c_str(), s.size());
  269. +
  270. + // Send as reliable
  271. + m_con.Send(peer_id, 0, data, true);
  272. +
  273. +}
  274. +
  275. struct SendableTexture
  276. {
  277. std::string name;
  278. @@ -4188,112 +4331,109 @@
  279. {}
  280. };
  281.  
  282. -void Server::SendTextures(u16 peer_id)
  283. -{
  284. +void Server::SendTexturesRequested(u16 peer_id,core::list<TextureRequest> tosend) {
  285. DSTACK(__FUNCTION_NAME);
  286.  
  287. - infostream<<"Server::SendTextures(): Sending textures to client"<<std::endl;
  288. -
  289. + infostream<<"Server::SendTexturesRequested(): Sending textures to client"<<std::endl;
  290. +
  291. /* Read textures */
  292. -
  293. +
  294. // Put 5kB in one bunch (this is not accurate)
  295. u32 bytes_per_bunch = 5000;
  296. -
  297. +
  298. core::array< core::list<SendableTexture> > texture_bunches;
  299. texture_bunches.push_back(core::list<SendableTexture>());
  300. -
  301. +
  302. u32 texture_size_bunch_total = 0;
  303. - for(core::list<ModSpec>::Iterator i = m_mods.begin();
  304. - i != m_mods.end(); i++){
  305. - const ModSpec &mod = *i;
  306. - std::string texturepath = mod.path + DIR_DELIM + "textures";
  307. - std::vector<fs::DirListNode> dirlist = fs::GetDirListing(texturepath);
  308. - for(u32 j=0; j<dirlist.size(); j++){
  309. - if(dirlist[j].dir) // Ignode dirs
  310. - continue;
  311. - std::string tname = dirlist[j].name;
  312. - std::string tpath = texturepath + DIR_DELIM + tname;
  313. - // Read data
  314. - std::ifstream fis(tpath.c_str(), std::ios_base::binary);
  315. - if(fis.good() == false){
  316. - errorstream<<"Server::SendTextures(): Could not open \""
  317. - <<tname<<"\" for reading"<<std::endl;
  318. - continue;
  319. - }
  320. - std::ostringstream tmp_os(std::ios_base::binary);
  321. - bool bad = false;
  322. - for(;;){
  323. - char buf[1024];
  324. - fis.read(buf, 1024);
  325. - std::streamsize len = fis.gcount();
  326. - tmp_os.write(buf, len);
  327. - texture_size_bunch_total += len;
  328. - if(fis.eof())
  329. - break;
  330. - if(!fis.good()){
  331. - bad = true;
  332. - break;
  333. - }
  334. - }
  335. - if(bad){
  336. - errorstream<<"Server::SendTextures(): Failed to read \""
  337. - <<tname<<"\""<<std::endl;
  338. - continue;
  339. - }
  340. - /*infostream<<"Server::SendTextures(): Loaded \""
  341. - <<tname<<"\""<<std::endl;*/
  342. - // Put in list
  343. - texture_bunches[texture_bunches.size()-1].push_back(
  344. - SendableTexture(tname, tpath, tmp_os.str()));
  345. -
  346. - // Start next bunch if got enough data
  347. - if(texture_size_bunch_total >= bytes_per_bunch){
  348. - texture_bunches.push_back(core::list<SendableTexture>());
  349. - texture_size_bunch_total = 0;
  350. +
  351. + for(core::list<TextureRequest>::Iterator i = tosend.begin(); i != tosend.end(); i++) {
  352. +
  353. + //TODO get path + name
  354. + std::string tpath = m_Textures[(*i).name].path;
  355. +
  356. + // Read data
  357. + std::ifstream fis(tpath.c_str(), std::ios_base::binary);
  358. + if(fis.good() == false){
  359. + errorstream<<"Server::SendTexturesRequested(): Could not open \""
  360. + <<tpath<<"\" for reading"<<std::endl;
  361. + continue;
  362. + }
  363. + std::ostringstream tmp_os(std::ios_base::binary);
  364. + bool bad = false;
  365. + for(;;){
  366. + char buf[1024];
  367. + fis.read(buf, 1024);
  368. + std::streamsize len = fis.gcount();
  369. + tmp_os.write(buf, len);
  370. + texture_size_bunch_total += len;
  371. + if(fis.eof())
  372. + break;
  373. + if(!fis.good()){
  374. + bad = true;
  375. + break;
  376. }
  377. }
  378. + if(bad){
  379. + errorstream<<"Server::SendTexturesRequested(): Failed to read \""
  380. + <<(*i).name<<"\""<<std::endl;
  381. + continue;
  382. + }
  383. + /*infostream<<"Server::SendTexturesRequested(): Loaded \""
  384. + <<tname<<"\""<<std::endl;*/
  385. + // Put in list
  386. + texture_bunches[texture_bunches.size()-1].push_back(
  387. + SendableTexture((*i).name, tpath, tmp_os.str()));
  388. +
  389. + // Start next bunch if got enough data
  390. + if(texture_size_bunch_total >= bytes_per_bunch){
  391. + texture_bunches.push_back(core::list<SendableTexture>());
  392. + texture_size_bunch_total = 0;
  393. + }
  394. +
  395. }
  396.  
  397. /* Create and send packets */
  398. -
  399. - u32 num_bunches = texture_bunches.size();
  400. - for(u32 i=0; i<num_bunches; i++)
  401. - {
  402. - /*
  403. - u16 command
  404. - u16 total number of texture bunches
  405. - u16 index of this bunch
  406. - u32 number of textures in this bunch
  407. - for each texture {
  408. - u16 length of name
  409. - string name
  410. - u32 length of data
  411. - data
  412. - }
  413. - */
  414. - std::ostringstream os(std::ios_base::binary);
  415.  
  416. - writeU16(os, TOCLIENT_TEXTURES);
  417. - writeU16(os, num_bunches);
  418. - writeU16(os, i);
  419. - writeU32(os, texture_bunches[i].size());
  420. -
  421. - for(core::list<SendableTexture>::Iterator
  422. - j = texture_bunches[i].begin();
  423. - j != texture_bunches[i].end(); j++){
  424. - os<<serializeString(j->name);
  425. - os<<serializeLongString(j->data);
  426. - }
  427. -
  428. - // Make data buffer
  429. - std::string s = os.str();
  430. - infostream<<"Server::SendTextures(): bunch "<<i<<"/"<<num_bunches
  431. - <<" textures="<<texture_bunches[i].size()
  432. - <<" size=" <<s.size()<<std::endl;
  433. - SharedBuffer<u8> data((u8*)s.c_str(), s.size());
  434. - // Send as reliable
  435. - m_con.Send(peer_id, 0, data, true);
  436. - }
  437. + u32 num_bunches = texture_bunches.size();
  438. + for(u32 i=0; i<num_bunches; i++)
  439. + {
  440. + /*
  441. + u16 command
  442. + u16 total number of texture bunches
  443. + u16 index of this bunch
  444. + u32 number of textures in this bunch
  445. + for each texture {
  446. + u16 length of name
  447. + string name
  448. + u32 length of data
  449. + data
  450. + }
  451. + */
  452. + std::ostringstream os(std::ios_base::binary);
  453. +
  454. + writeU16(os, TOCLIENT_TEXTURES);
  455. + writeU16(os, num_bunches);
  456. + writeU16(os, i);
  457. + writeU32(os, texture_bunches[i].size());
  458. +
  459. + for(core::list<SendableTexture>::Iterator
  460. + j = texture_bunches[i].begin();
  461. + j != texture_bunches[i].end(); j++){
  462. + os<<serializeString(j->name);
  463. + os<<serializeLongString(j->data);
  464. + }
  465. +
  466. + // Make data buffer
  467. + std::string s = os.str();
  468. + infostream<<"Server::SendTexturesRequested(): bunch "<<i<<"/"<<num_bunches
  469. + <<" textures="<<texture_bunches[i].size()
  470. + <<" size=" <<s.size()<<std::endl;
  471. + SharedBuffer<u8> data((u8*)s.c_str(), s.size());
  472. + // Send as reliable
  473. + m_con.Send(peer_id, 0, data, true);
  474. + }
  475. +
  476. +
  477. }
  478.  
  479. /*
  480. --- celeron55-minetest-6957930.orig/src/client.cpp 2011-12-11 15:52:19.000000000 +0100
  481. +++ celeron55-minetest-6957930/src/client.cpp 2012-01-02 01:38:37.000000000 +0100
  482. @@ -36,6 +36,17 @@
  483. #include "tooldef.h"
  484. #include "craftitemdef.h"
  485. #include <IFileSystem.h>
  486. +#include "sha1.h"
  487. +#include "base64.h"
  488. +
  489. +struct TextureRequest
  490. +{
  491. + std::string name;
  492. +
  493. + TextureRequest(const std::string &name_=""):
  494. + name(name_)
  495. + {}
  496. +};
  497.  
  498. /*
  499. QueuedMeshUpdate
  500. @@ -1232,6 +1243,157 @@
  501. event.deathscreen.camera_point_target_z = camera_point_target.Z;
  502. m_client_event_queue.push_back(event);
  503. }
  504. + else if(command == TOCLIENT_ANNOUNCE_TEXTURES)
  505. + {
  506. + io::IFileSystem *irrfs = m_device->getFileSystem();
  507. + video::IVideoDriver *vdrv = m_device->getVideoDriver();
  508. +
  509. + std::string datastring((char*)&data[2], datasize-2);
  510. + std::istringstream is(datastring, std::ios_base::binary);
  511. +
  512. +
  513. + // Stop threads while updating content definitions
  514. + m_mesh_update_thread.setRun(false);
  515. + // Process the remaining TextureSource queue to let MeshUpdateThread
  516. + // get it's remaining textures and thus let it stop
  517. + while(m_mesh_update_thread.IsRunning()){
  518. + m_tsrc->processQueue();
  519. + }
  520. +
  521. + int num_textures = readU16(is);
  522. +
  523. + core::list<TextureRequest> texture_requests;
  524. +
  525. + for(int i=0; i<num_textures; i++){
  526. +
  527. + bool texture_found = false;
  528. +
  529. + //read texture from cache
  530. + std::string name = deSerializeString(is);
  531. + std::string sha1_texture = deSerializeString(is);
  532. +
  533. + std::string tpath = porting::path_userdata + DIR_DELIM + std::string("cache") + DIR_DELIM + name;
  534. + // Read data
  535. + std::ifstream fis(tpath.c_str(), std::ios_base::binary);
  536. +
  537. +
  538. + if(fis.good() == false){
  539. + infostream<<"Client::Texture not found in cache: "
  540. + <<name << " expected it at: "<<tpath<<std::endl;
  541. + }
  542. + else
  543. + {
  544. + std::ostringstream tmp_os(std::ios_base::binary);
  545. + bool bad = false;
  546. + for(;;){
  547. + char buf[1024];
  548. + fis.read(buf, 1024);
  549. + std::streamsize len = fis.gcount();
  550. + tmp_os.write(buf, len);
  551. + if(fis.eof())
  552. + break;
  553. + if(!fis.good()){
  554. + bad = true;
  555. + break;
  556. + }
  557. + }
  558. + if(bad){
  559. + infostream<<"Client: Failed to read texture from cache\""
  560. + <<name<<"\""<<std::endl;
  561. + }
  562. + else {
  563. +
  564. + SHA1 sha1;
  565. + sha1.addBytes(tmp_os.str().c_str(), tmp_os.str().length());
  566. +
  567. + unsigned char *digest = sha1.getDigest();
  568. +
  569. + std::string digest_string = base64_encode(digest, 20);
  570. +
  571. + if (digest_string == sha1_texture) {
  572. + // Silly irrlicht's const-incorrectness
  573. + Buffer<char> data_rw(tmp_os.str().c_str(), tmp_os.str().size());
  574. +
  575. + // Create an irrlicht memory file
  576. + io::IReadFile *rfile = irrfs->createMemoryReadFile(
  577. + *data_rw, tmp_os.str().size(), "_tempreadfile");
  578. + assert(rfile);
  579. + // Read image
  580. + video::IImage *img = vdrv->createImageFromFile(rfile);
  581. + if(!img){
  582. + infostream<<"Client: Cannot create image from data of "
  583. + <<"received texture \""<<name<<"\""<<std::endl;
  584. + rfile->drop();
  585. + }
  586. + else {
  587. + m_tsrc->insertSourceImage(name, img);
  588. + img->drop();
  589. + rfile->drop();
  590. +
  591. + texture_found = true;
  592. + }
  593. + }
  594. + else {
  595. + infostream<<"Client::Texture cached sha1 hash not matching server hash: "
  596. + <<name << ": server ->"<<sha1_texture <<" client -> "<<digest_string<<std::endl;
  597. + }
  598. +
  599. + delete(digest);
  600. + }
  601. + }
  602. +
  603. + //add texture request
  604. + if (!texture_found) {
  605. + infostream<<"Client: Adding texture to request list: \""
  606. + <<name<<"\""<<std::endl;
  607. + texture_requests.push_back(TextureRequest(name));
  608. + }
  609. +
  610. + }
  611. + // Resume threads
  612. + m_mesh_update_thread.setRun(true);
  613. + m_mesh_update_thread.Start();
  614. +
  615. + ClientEvent event;
  616. + event.type = CE_TEXTURES_UPDATED;
  617. + m_client_event_queue.push_back(event);
  618. +
  619. +
  620. + //send Texture request
  621. + /*
  622. + u16 command
  623. + u16 number of textures requested
  624. + for each texture {
  625. + u16 length of name
  626. + string name
  627. + u16 length of path
  628. + string path
  629. + }
  630. + */
  631. + std::ostringstream os(std::ios_base::binary);
  632. + u8 buf[12];
  633. +
  634. +
  635. + // Write command
  636. + writeU16(buf, TOSERVER_REQUEST_TEXTURES);
  637. + os.write((char*)buf, 2);
  638. +
  639. + writeU16(buf,texture_requests.size());
  640. + os.write((char*)buf, 2);
  641. +
  642. +
  643. + for(core::list<TextureRequest>::Iterator i = texture_requests.begin();
  644. + i != texture_requests.end(); i++) {
  645. + os<<serializeString(i->name);
  646. + }
  647. +
  648. + // Make data buffer
  649. + std::string s = os.str();
  650. + SharedBuffer<u8> data((u8*)s.c_str(), s.size());
  651. + // Send as reliable
  652. + Send(0, data, true);
  653. + infostream<<"Client: Sending request list to server " <<std::endl;
  654. + }
  655. else if(command == TOCLIENT_TEXTURES)
  656. {
  657. io::IFileSystem *irrfs = m_device->getFileSystem();
  658. @@ -1286,6 +1448,20 @@
  659. rfile->drop();
  660. continue;
  661. }
  662. +
  663. + fs::CreateDir(porting::path_userdata + DIR_DELIM + std::string("cache"));
  664. +
  665. + std::string filename = porting::path_userdata + DIR_DELIM + std::string("cache") + DIR_DELIM + name;
  666. + std::ofstream outfile(filename.c_str(), std::ios_base::binary | std::ios_base::trunc);
  667. +
  668. + if (outfile.good()) {
  669. + outfile.write(data.c_str(),data.length());
  670. + outfile.close();
  671. + }
  672. + else {
  673. + errorstream<<"Client: Unable to open cached texture file "<< filename <<std::endl;
  674. + }
  675. +
  676. m_tsrc->insertSourceImage(name, img);
  677. img->drop();
  678. rfile->drop();
  679. --- celeron55-minetest-6957930.orig/src/client.h 2011-12-11 15:52:19.000000000 +0100
  680. +++ celeron55-minetest-6957930/src/client.h 2012-01-01 03:41:44.000000000 +0100
  681. @@ -30,6 +30,7 @@
  682. #include "clientobject.h"
  683. #include "utility.h" // For IntervalLimiter
  684. #include "gamedef.h"
  685. +#include "filesys.h"
  686.  
  687. struct MeshMakeData;
  688. class IGameDef;
Advertisement
Add Comment
Please, Sign In to add comment