DimensionMap.cpp 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222
  1. #include "DimensionMap.h"
  2. #include <Datei.h>
  3. #include <Logging.h>
  4. #include "Chat.h"
  5. #include "ChunkMap.h"
  6. #include "Dimension.h"
  7. #include "Entity.h"
  8. #include "Game.h"
  9. #include "Player.h"
  10. DimensionMap::DimensionMap(int dimensionId)
  11. : ReferenceCounter(),
  12. dimensionId(dimensionId)
  13. {
  14. chunks = new Framework::RCTrie<ChunkMap>();
  15. }
  16. DimensionMap::~DimensionMap()
  17. {
  18. chunks->release();
  19. }
  20. void DimensionMap::api(Framework::InMemoryBuffer* zRequest,
  21. NetworkMessage* zResponse,
  22. Entity* zSource,
  23. Dimension* zDimension)
  24. {
  25. char type;
  26. zRequest->lese(&type, 1);
  27. switch (type)
  28. {
  29. case 0: // request chunk
  30. {
  31. Framework::Punkt location;
  32. zRequest->lese((char*)&location.x, 4);
  33. zRequest->lese((char*)&location.y, 4);
  34. location = Game::getChunkCenter(location.x, location.y);
  35. char addr[8];
  36. zDimension->getAddrOfWorld(location, addr);
  37. ChunkMap* res = getMap(addr, 8, location);
  38. // create an empty map for a chunk that does not yet exist
  39. if (!res) res = new ChunkMap(location);
  40. zResponse->sendMap(res);
  41. zResponse->setUseBackground();
  42. res->release();
  43. break;
  44. }
  45. case 1: // subscribe to changes
  46. {
  47. cs.lock();
  48. observers.add(zSource->getId());
  49. cs.unlock();
  50. break;
  51. }
  52. case 2: // unsubscribe from changes
  53. {
  54. cs.lock();
  55. observers.removeValue(zSource->getId());
  56. cs.unlock();
  57. break;
  58. }
  59. case 3: // player list request
  60. {
  61. Framework::InMemoryBuffer buff;
  62. int count = 0;
  63. for (Entity* entity : *zDimension->entities)
  64. {
  65. if (entity->zType()->getId() == EntityTypeEnum::PLAYER)
  66. {
  67. Player* p = dynamic_cast<Player*>(entity);
  68. char len = (char)Framework::textLength(p->getName());
  69. buff.schreibe(&len, 1);
  70. buff.schreibe(p->getName(), len);
  71. Framework::Vec3<float> pos = p->getPosition();
  72. buff.schreibe((char*)&pos.x, 4);
  73. buff.schreibe((char*)&pos.y, 4);
  74. buff.schreibe((char*)&pos.z, 4);
  75. count++;
  76. }
  77. }
  78. char* msg = new char[4 + buff.getSize()];
  79. *(int*)msg = count;
  80. buff.lese(msg + 4, (int)buff.getSize());
  81. zResponse->sendPlayerPositions(msg, 4 + (int)buff.getSize());
  82. break;
  83. }
  84. }
  85. }
  86. ChunkMap* DimensionMap::load(Framework::Punkt chunkCenter)
  87. {
  88. Framework::Datei file;
  89. Framework::Text filePath
  90. = Game::INSTANCE->getWorldDirectory() + "/dim/" + dimensionId + "/map/";
  91. filePath.appendHex(chunkCenter.x);
  92. filePath += "_";
  93. filePath.appendHex(chunkCenter.y);
  94. filePath += ".map";
  95. file.setDatei(filePath);
  96. if (file.open(Framework::Datei::Style::lesen))
  97. {
  98. ChunkMap* map = new ChunkMap(&file);
  99. file.close();
  100. return map;
  101. }
  102. return 0;
  103. }
  104. void DimensionMap::loadMap(char* addr, int addrLen, Chunk* zChunk)
  105. {
  106. cs.lock();
  107. if (chunks->z(addr, addrLen))
  108. {
  109. cs.unlock();
  110. return;
  111. }
  112. ChunkMap* map = load(zChunk->getCenter());
  113. if (!map)
  114. {
  115. map = new ChunkMap(zChunk);
  116. for (auto iterator = observers.begin(); iterator;)
  117. {
  118. Entity* e = Game::INSTANCE->zEntity(iterator.val());
  119. if (!e)
  120. {
  121. iterator.remove();
  122. continue;
  123. }
  124. else
  125. {
  126. NetworkMessage* msg = new NetworkMessage();
  127. msg->sendMap(map);
  128. msg->setUseBackground();
  129. Game::INSTANCE->sendMessage(msg, e);
  130. }
  131. iterator++;
  132. }
  133. }
  134. chunks->set(addr, addrLen, map);
  135. cs.unlock();
  136. }
  137. void DimensionMap::onMapUpdated(char* addr, int addrLen)
  138. {
  139. cs.lock();
  140. ChunkMap* map = chunks->z(addr, addrLen);
  141. if (map)
  142. {
  143. for (auto iterator = observers.begin(); iterator;)
  144. {
  145. Entity* e = Game::INSTANCE->zEntity(iterator.val());
  146. if (!e)
  147. {
  148. iterator.remove();
  149. continue;
  150. }
  151. else
  152. {
  153. NetworkMessage* msg = new NetworkMessage();
  154. msg->sendMap(map);
  155. msg->setUseBackground();
  156. Game::INSTANCE->sendMessage(msg, e);
  157. }
  158. iterator++;
  159. }
  160. }
  161. cs.unlock();
  162. }
  163. void DimensionMap::saveMap(char* addr, int addrLen)
  164. {
  165. cs.lock();
  166. ChunkMap* map = chunks->z(addr, addrLen);
  167. if (map)
  168. {
  169. Framework::Datei file;
  170. Framework::Text filePath = Game::INSTANCE->getWorldDirectory() + "/dim/"
  171. + dimensionId + "/map/";
  172. filePath.appendHex(map->getChunkCenter().x);
  173. filePath += "_";
  174. filePath.appendHex(map->getChunkCenter().y);
  175. filePath += ".map";
  176. file.setDatei(filePath);
  177. file.erstellen();
  178. if (file.open(Framework::Datei::Style::schreiben))
  179. {
  180. map->writeTo(&file);
  181. file.close();
  182. }
  183. else
  184. {
  185. Game::INSTANCE->zChat()->broadcastMessage(
  186. "Could not save map data. The map has to be recalulated at "
  187. "each chunk loading.",
  188. Chat::CHANNEL_WARNING);
  189. Framework::Logging::warning()
  190. << "could not open file '" << filePath.getText()
  191. << "' for writing.";
  192. }
  193. }
  194. cs.unlock();
  195. }
  196. void DimensionMap::removeMap(char* addr, int addrLen)
  197. {
  198. cs.lock();
  199. saveMap(addr, addrLen);
  200. chunks->remove(addr, addrLen);
  201. cs.unlock();
  202. }
  203. ChunkMap* DimensionMap::getMap(
  204. char* addr, int addrLen, Framework::Punkt chunkCenter)
  205. {
  206. cs.lock();
  207. ChunkMap* map = chunks->get(addr, addrLen);
  208. if (!map) map = load(chunkCenter);
  209. cs.unlock();
  210. return map;
  211. }