123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215 |
- #include "DimensionMap.h"
- #include <Datei.h>
- #include "Game.h"
- DimensionMap::DimensionMap(int dimensionId)
- : ReferenceCounter(),
- dimensionId(dimensionId)
- {
- chunks = new Framework::RCTrie<ChunkMap>();
- }
- DimensionMap::~DimensionMap()
- {
- chunks->release();
- }
- void DimensionMap::api(Framework::InMemoryBuffer* zRequest,
- NetworkMessage* zResponse,
- Entity* zSource,
- Dimension* zDimension)
- {
- char type;
- zRequest->lese(&type, 1);
- switch (type)
- {
- case 0: // request chunk
- {
- Framework::Punkt location;
- zRequest->lese((char*)&location.x, 4);
- zRequest->lese((char*)&location.y, 4);
- location = Game::getChunkCenter(location.x, location.y);
- char addr[8];
- zDimension->getAddrOfWorld(location, addr);
- ChunkMap* res = getMap(addr, 8, location);
- // create an empty map for a chunk that does not yet exist
- if (!res) res = new ChunkMap(location);
- zResponse->sendMap(res);
- zResponse->setUseBackground();
- res->release();
- break;
- }
- case 1: // subscribe to changes
- {
- cs.lock();
- observers.add(zSource->getId());
- cs.unlock();
- break;
- }
- case 2: // unsubscribe from changes
- {
- cs.lock();
- observers.removeValue(zSource->getId());
- cs.unlock();
- break;
- }
- case 3: // player list request
- {
- InMemoryBuffer buff;
- int count = 0;
- for (Entity* entity : *zDimension->entities)
- {
- if (entity->zType()->getId() == EntityTypeEnum::PLAYER)
- {
- Player* p = dynamic_cast<Player*>(entity);
- char len = (char)textLength(p->getName());
- buff.schreibe(&len, 1);
- buff.schreibe(p->getName(), len);
- Vec3<float> pos = p->getPosition();
- buff.schreibe((char*)&pos.x, 4);
- buff.schreibe((char*)&pos.y, 4);
- buff.schreibe((char*)&pos.z, 4);
- count++;
- }
- }
- char* msg = new char[4 + buff.getSize()];
- *(int*)msg = count;
- buff.lese(msg + 4, (int)buff.getSize());
- zResponse->sendPlayerPositions(msg, 4 + (int)buff.getSize());
- break;
- }
- }
- }
- ChunkMap* DimensionMap::load(Framework::Punkt chunkCenter)
- {
- Framework::Datei file;
- Framework::Text filePath
- = Game::INSTANCE->getWorldDirectory() + "/dim/" + dimensionId + "/map/";
- filePath.appendHex(chunkCenter.x);
- filePath += "_";
- filePath.appendHex(chunkCenter.y);
- filePath += ".map";
- file.setDatei(filePath);
- if (file.open(Datei::Style::lesen))
- {
- ChunkMap* map = new ChunkMap(&file);
- file.close();
- return map;
- }
- return 0;
- }
- void DimensionMap::loadMap(char* addr, int addrLen, Chunk* zChunk)
- {
- cs.lock();
- if (chunks->z(addr, addrLen))
- {
- cs.unlock();
- return;
- }
- ChunkMap* map = load(zChunk->getCenter());
- if (!map)
- {
- map = new ChunkMap(zChunk);
- for (auto iterator = observers.begin(); iterator;)
- {
- Entity* e = Game::INSTANCE->zEntity(iterator.val());
- if (!e)
- {
- iterator.remove();
- continue;
- }
- else
- {
- NetworkMessage* msg = new NetworkMessage();
- msg->sendMap(map);
- msg->setUseBackground();
- Game::INSTANCE->sendMessage(msg, e);
- }
- iterator++;
- }
- }
- chunks->set(addr, addrLen, map);
- cs.unlock();
- }
- void DimensionMap::onMapUpdated(char* addr, int addrLen)
- {
- cs.lock();
- ChunkMap* map = chunks->z(addr, addrLen);
- if (map)
- {
- for (auto iterator = observers.begin(); iterator;)
- {
- Entity* e = Game::INSTANCE->zEntity(iterator.val());
- if (!e)
- {
- iterator.remove();
- continue;
- }
- else
- {
- NetworkMessage* msg = new NetworkMessage();
- msg->sendMap(map);
- msg->setUseBackground();
- Game::INSTANCE->sendMessage(msg, e);
- }
- iterator++;
- }
- }
- cs.unlock();
- }
- void DimensionMap::saveMap(char* addr, int addrLen)
- {
- cs.lock();
- ChunkMap* map = chunks->z(addr, addrLen);
- if (map)
- {
- Framework::Datei file;
- Framework::Text filePath = Game::INSTANCE->getWorldDirectory() + "/dim/"
- + dimensionId + "/map/";
- filePath.appendHex(map->getChunkCenter().x);
- filePath += "_";
- filePath.appendHex(map->getChunkCenter().y);
- filePath += ".map";
- file.setDatei(filePath);
- file.erstellen();
- if (file.open(Datei::Style::schreiben))
- {
- map->writeTo(&file);
- file.close();
- }
- else
- {
- Game::INSTANCE->zChat()->broadcastMessage(
- "Could not save map data. The map has to be recalulated at "
- "each chunk loading.",
- Chat::CHANNEL_WARNING);
- std::cout << "WARNING: could not open file '" << filePath.getText()
- << "' for writing.";
- }
- }
- cs.unlock();
- }
- void DimensionMap::removeMap(char* addr, int addrLen)
- {
- cs.lock();
- saveMap(addr, addrLen);
- chunks->remove(addr, addrLen);
- cs.unlock();
- }
- ChunkMap* DimensionMap::getMap(
- char* addr, int addrLen, Framework::Punkt chunkCenter)
- {
- cs.lock();
- ChunkMap* map = chunks->get(addr, addrLen);
- if (!map) map = load(chunkCenter);
- cs.unlock();
- return map;
- }
|