123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304 |
- #include "Dimension.h"
- #include "Constants.h"
- #include "Datei.h"
- #include "Game.h"
- using namespace Framework;
- Dimension::Dimension(int id)
- : dimensionId(id),
- gravity(9.8f),
- chunks(new Trie<Chunk>()),
- entities(new RCArray<Entity>())
- {}
- Dimension::~Dimension()
- {
- entities->release();
- chunks->release();
- }
- void Dimension::api(Framework::StreamReader* zRequest, NetworkResponse* zResponse)
- {
- // TODO: switch type chunck, block
- }
- void Dimension::tickEntities()
- {
- for (auto entity : *entities)
- {
- if (!entity->isRemoved() && zChunk(Punkt((int)entity->getPosition().x, (int)entity->getPosition().y)))
- entity->prepareTick(this);
- }
- int index = 0;
- for (auto entity : *entities)
- {
- if (!entity->isRemoved() && zChunk(Punkt((int)entity->getPosition().x, (int)entity->getPosition().y)))
- entity->tick(this);
- index++;
- }
- }
- void Dimension::getAddrOf(Punkt cPos, char* addr) const
- {
- *(int*)addr = cPos.x;
- *((int*)addr + 1) = cPos.y;
- }
- void Dimension::getAddrOfWorld(Punkt wPos, char* addr) const
- {
- if (wPos.x < 0)
- wPos.x -= CHUNK_SIZE;
- if (wPos.y < 0) // needed because otherwise would (-8, -8) have the same adress as (8, 8)
- wPos.y -= CHUNK_SIZE;
- wPos /= CHUNK_SIZE;
- getAddrOf(wPos, addr);
- }
- Chunk* Dimension::zChunk(Punkt wPos) const
- {
- char addr[8];
- getAddrOfWorld(wPos, addr);
- return chunks->z(addr, 8);
- }
- Framework::Either<Block*, int> Dimension::zBlock(Vec3<int> location)
- {
- Chunk* c = zChunk(Game::INSTANCE->getChunkCenter(location.x, location.y));
- if (c)
- {
- int x = location.x % CHUNK_SIZE;
- int y = location.y % CHUNK_SIZE;
- if (x < 0)
- x += CHUNK_SIZE;
- if (y < 0)
- y += CHUNK_SIZE;
- return c->zBlockAt(Vec3<int>(x, y, location.z));
- }
- return 0;
- }
- Block* Dimension::zRealBlockInstance(Framework::Vec3<int> location)
- {
- Chunk* c = zChunk(Game::INSTANCE->getChunkCenter(location.x, location.y));
- if (c)
- {
- int x = location.x % CHUNK_SIZE;
- int y = location.y % CHUNK_SIZE;
- if (x < 0)
- x += CHUNK_SIZE;
- if (y < 0)
- y += CHUNK_SIZE;
- c->instantiateBlock(Vec3<int>(x, y, location.z));
- return c->zBlockAt(Vec3<int>(x, y, location.z));
- }
- return 0;
- }
- void Dimension::placeBlock(Framework::Vec3<int> location, Framework::Either<Block*, int> block)
- {
- Chunk* c = zChunk(Game::getChunkCenter(location.x, location.y));
- if (c)
- {
- int x = location.x % CHUNK_SIZE;
- int y = location.y % CHUNK_SIZE;
- if (x < 0)
- x += CHUNK_SIZE;
- if (y < 0)
- y += CHUNK_SIZE;
- if (block.isA())
- c->putBlockAt(Vec3<int>(x, y, location.z), block);
- else
- {
- c->putBlockAt(Vec3<int>(x, y, location.z), 0);
- c->putBlockTypeAt(Vec3<int>(x, y, location.z), block);
- }
- }
- else if (block.isA())
- block.getA()->release();
- }
- void Dimension::addEntity(Entity* entity)
- {
- entities->add(entity);
- }
- void Dimension::setChunk(Chunk* chunk, Punkt center)
- {
- char addr[8];
- getAddrOfWorld(center, addr);
- Chunk* old = chunks->z(addr, 8);
- if (old)
- {
- for (int i = 0; i < chunkList.getEintragAnzahl(); i++)
- {
- if (chunkList.get(i) == old)
- {
- chunkList.remove(i);
- break;
- }
- }
- }
- chunks->set(addr, 8, chunk);
- if (chunk)
- {
- chunkList.add(chunk);
- chunk->setAdded();
- }
- getAddrOfWorld(center + Punkt(CHUNK_SIZE, 0), addr);
- Chunk* zChunk = chunks->z(addr, 8);
- if (zChunk)
- {
- zChunk->setNeighbor(WEST, chunk);
- if (chunk)
- chunk->setNeighbor(EAST, zChunk);
- }
- getAddrOfWorld(center + Punkt(-CHUNK_SIZE, 0), addr);
- zChunk = chunks->z(addr, 8);
- if (zChunk)
- {
- zChunk->setNeighbor(EAST, chunk);
- if (chunk)
- chunk->setNeighbor(WEST, zChunk);
- }
- getAddrOfWorld(center + Punkt(0, CHUNK_SIZE), addr);
- zChunk = chunks->z(addr, 8);
- if (zChunk)
- {
- zChunk->setNeighbor(NORTH, chunk);
- if (chunk)
- chunk->setNeighbor(SOUTH, zChunk);
- }
- getAddrOfWorld(center + Punkt(0, -CHUNK_SIZE), addr);
- zChunk = chunks->z(addr, 8);
- if (zChunk)
- {
- zChunk->setNeighbor(SOUTH, chunk);
- if (chunk)
- chunk->setNeighbor(NORTH, zChunk);
- }
- }
- void Dimension::save(Text worldDir) const
- {
- for (auto chunk = chunks->getIterator(); chunk; chunk++)
- {
- if (!chunk._)
- continue;
- Datei* file = new Datei();
- Text filePath = worldDir + "/dim/" + dimensionId + "/";
- filePath.appendHex(chunk->getCenter().x);
- filePath += "_";
- filePath.appendHex(chunk->getCenter().y);
- filePath += ".chunk";
- file->setDatei(filePath);
- if (file->open(Datei::Style::schreiben))
- chunk->save(file, StreamTarget::FULL);
- file->close();
- file->release();
- }
- Text filePath = worldDir + "/dim/" + dimensionId + "/entities";
- Datei* file = new Datei();
- file->setDatei(filePath);
- if (file->open(Datei::Style::schreiben))
- {
- for (Entity* entity : *entities)
- {
- if (entity->zType()->getId() != PlayerEntityType::ID)
- {
- if (!entity->isRemoved())
- {
- int type = entity->zType()->getId();
- file->schreibe((char*)&type, 4);
- StaticRegistry<EntityType>::INSTANCE.zElement(type)->saveEntity(entity, file);
- }
- }
- else
- {
- Datei pFile;
- pFile.setDatei(worldDir + "/player/" + ((Player*)entity)->getName());
- if (pFile.open(Datei::Style::schreiben))
- PlayerEntityType::INSTANCE->saveEntity(entity, &pFile);
- }
- }
- file->close();
- }
- }
- int Dimension::getDimensionId() const
- {
- return dimensionId;
- }
- bool Dimension::hasChunck(int x, int y) const
- {
- return zChunk(Punkt(x, y));
- }
- float Dimension::getGravity() const
- {
- return gravity;
- }
- void Dimension::removeOldChunks()
- {
- Array<int> removed;
- int index = 0;
- for (Chunk* chunk : chunkList)
- {
- if (!chunk->hasViews())
- removed.add(index, 0);
- index++;
- }
- for (int i : removed)
- {
- Chunk* chunk = chunkList.get(i);
- // TODO: save chunk
- chunk->prepareRemove();
- setChunk(0, chunk->getCenter());
- }
- }
- Entity* Dimension::zEntity(int id)
- {
- for (auto entity : *entities)
- {
- if (!entity->isRemoved() && entity->getId() == id)
- return entity;
- }
- return 0;
- }
- Entity* Dimension::zNearestEntity(Framework::Vec3<float> pos, std::function<bool(Entity*)> filter)
- {
- Entity* result = 0;
- float sqDist = 0;
- for (auto entity : *entities)
- {
- if (!entity->isRemoved() && filter(entity))
- {
- float d = pos.abstandSq(entity->getPosition());
- if (!result || d < sqDist)
- {
- result = entity;
- sqDist = d;
- }
- }
- }
- return result;
- }
- void Dimension::removeEntity(int id)
- {
- int index = 0;
- for (auto entity : *entities)
- {
- if (entity->getId() == id)
- {
- entities->remove(index);
- return;
- }
- index++;
- }
- }
|