123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340 |
- #include "Dimension.h"
- #include "Constants.h"
- #include "Datei.h"
- #include "Game.h"
- #include "Globals.h"
- #include "World.h"
- using namespace Framework;
- Dimension::Dimension()
- : id(-1),
- chunks(new RCTrie<Chunk>()),
- entities(new RCArray<Entity>()),
- gravity(0.0f)
- {}
- Dimension::~Dimension()
- {
- entities->release();
- chunks->release();
- }
- void Dimension::forAll(std::function<void(Model3D*)> f)
- {
- // handled by render and tick function
- }
- void Dimension::render(std::function<void(Model3D*)> f)
- {
- for (Chunk* chunk : chunkList)
- {
- chunk->renderSolid(f);
- }
- for (Chunk* chunk : chunkList)
- {
- chunk->renderTransparent(f);
- }
- }
- bool Dimension::tick(std::function<void(Model3D*)> f, double time)
- {
- bool res = 0;
- for (Chunk* chunk : chunkList)
- {
- res |= chunk->tick(f, time);
- }
- return res;
- }
- void Dimension::setId(int id)
- {
- this->id = id;
- }
- 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);
- }
- void Dimension::api(char* message)
- {
- switch (message[0])
- {
- case 1: // chunck
- {
- int cX = *(int*)(message + 1);
- int cY = *(int*)(message + 5);
- cs.lock();
- Chunk* ch = zChunk(Punkt(cX, cY));
- if (ch) ch->api(message + 9);
- cs.unlock();
- break;
- }
- case 2: // entity
- {
- int eId = *(int*)(message + 1);
- cs.lock();
- Entity* e = zEntity(eId);
- if (e) e->api(message + 5);
- cs.unlock();
- break;
- }
- case 3: // block
- {
- int px = *(int*)(message + 1);
- int py = *(int*)(message + 5);
- int pz = *(int*)(message + 9);
- cs.lock();
- Block* b = zBlock(Framework::Vec3<int>(px, py, pz));
- if (b) b->api(message + 13);
- cs.unlock();
- break;
- }
- case 4: // add new chunck
- {
- Punkt center;
- center.x = *(int*)(message + 1);
- center.y = *(int*)(message + 5);
- ByteArrayReader reader(message + 9, INT_MAX, 0);
- std::cout << "downloading chunk " << center.x << ", " << center.y
- << "\n";
- ZeitMesser zm;
- zm.messungStart();
- World::INSTANCE->lockWorld();
- Chunk* chunk = new Chunk(center, &reader);
- zm.messungEnde();
- std::cout << "chunk loading took " << zm.getSekunden()
- << " seconds\n";
- cs.lock();
- setChunk(chunk, center);
- cs.unlock();
- World::INSTANCE->unlockWorld();
- World::INSTANCE->onChunkAdded(center);
- World::INSTANCE->zClient()->chunkAPIRequest(center, "\2", 1);
- break;
- }
- case 5: // light update
- {
- int x = *(int*)(message + 1);
- int y = *(int*)(message + 5);
- int z = *(int*)(message + 9);
- Framework::Vec3<int> location(x, y, z);
- for (int i = 0; i < 6; i++)
- {
- Framework::Vec3<int> pos
- = location + getDirection(getDirectionFromIndex(i));
- if (pos.z >= 0 && pos.z < WORLD_HEIGHT)
- {
- cs.lock();
- Chunk* c
- = zChunk(World::INSTANCE->getChunkCenter(pos.x, pos.y));
- Block* zB = c ? c->zBlockAt(pos) : 0;
- if (zB)
- {
- bool visible = zB->isVisible();
- zB->setLightData(
- getOppositeDirection(getDirectionFromIndex(i)),
- (unsigned char*)(message + 13),
- c);
- if (zB->isVisible() != visible)
- {
- zChunk(
- World::INSTANCE->getChunkCenter(pos.x, pos.y))
- ->blockVisibilityChanged(zB);
- }
- }
- cs.unlock();
- }
- }
- break;
- }
- case 6: // set gravity
- gravity = *(float*)(message + 1);
- break;
- }
- }
- Chunk* Dimension::zChunk(Punkt wPos) const
- {
- char addr[8];
- getAddrOfWorld(wPos, addr);
- return chunks->z(addr, 8);
- }
- Block* Dimension::zBlock(Vec3<int> location)
- {
- Chunk* c = zChunk(World::INSTANCE->getChunkCenter(location.x, location.y));
- if (c) return c->zBlockAt(location);
- return 0;
- }
- Block* Dimension::getBlock(Vec3<int> location)
- {
- cs.lock();
- Chunk* c = zChunk(World::INSTANCE->getChunkCenter(location.x, location.y));
- if (c)
- {
- Block* b = c->zBlockAt(location);
- b = b ? dynamic_cast<Block*>(b->getThis()) : 0;
- cs.unlock();
- return b;
- }
- cs.unlock();
- return 0;
- }
- void Dimension::addEntity(Entity* entity)
- {
- entities->add(entity);
- World::INSTANCE->setVisibility(entity, 1);
- }
- void Dimension::setChunk(Chunk* chunk, Punkt center)
- {
- char addr[8];
- getAddrOfWorld(center, addr);
- Chunk* old = chunks->z(addr, 8);
- cs.lock();
- if (old)
- {
- int index = 0;
- for (auto iterator = chunkList.begin(); iterator; ++iterator, ++index)
- {
- if ((Chunk*)iterator == old)
- {
- if (chunk)
- iterator.set(chunk);
- else
- chunkList.remove(index);
- break;
- }
- }
- }
- else if (chunk)
- chunkList.add(chunk);
- chunks->set(addr, 8, chunk);
- cs.unlock();
- }
- bool Dimension::hasChunck(int x, int y) const
- {
- return zChunk(Punkt(x, y));
- }
- void Dimension::removeDistantChunks(Punkt wPos)
- {
- Array<int> removed;
- int index = 0;
- for (Chunk* chunk : chunkList)
- {
- if (abs(chunk->getCenter().x - wPos.x) > MAX_VIEW_DISTANCE + CHUNK_SIZE
- || abs(chunk->getCenter().y - wPos.y)
- > MAX_VIEW_DISTANCE + CHUNK_SIZE)
- removed.add(index, 0);
- index++;
- }
- for (int i : removed)
- {
- cs.lock();
- Chunk* chunk = chunkList.get(i);
- chunk->destroy();
- setChunk(0, chunk->getCenter());
- cs.unlock();
- }
- }
- void Dimension::setBlock(Block* block)
- {
- cs.lock();
- Chunk* c = zChunk(World::INSTANCE->getChunkCenter(
- (int)floor(block->getPos().x), (int)floor(block->getPos().y)));
- if (c)
- c->setBlock(block);
- else
- block->release();
- cs.unlock();
- }
- void Dimension::removeBlock(Block* zBlock)
- {
- cs.lock();
- Chunk* c = zChunk(World::INSTANCE->getChunkCenter(
- (int)floor(zBlock->getPos().x), (int)floor(zBlock->getPos().y)));
- if (c) c->removeBlock(zBlock);
- cs.unlock();
- }
- Entity* Dimension::zEntity(int id)
- {
- cs.lock();
- for (Entity* e : *entities)
- {
- if (e->getId() == id)
- {
- cs.unlock();
- return e;
- }
- }
- cs.unlock();
- return 0;
- }
- Entity* Dimension::getEntity(int id)
- {
- cs.lock();
- for (Entity* e : *entities)
- {
- if (e->getId() == id)
- {
- Entity* result = dynamic_cast<Entity*>(e->getThis());
- cs.unlock();
- return result;
- }
- }
- cs.unlock();
- return 0;
- }
- void Dimension::removeEntity(int id)
- {
- World::INSTANCE->lockWorld();
- cs.lock();
- int index = 0;
- for (Entity* e : *entities)
- {
- if (e->getId() == id)
- {
- World::INSTANCE->setVisibility(e, 0);
- entities->remove(index);
- cs.unlock();
- World::INSTANCE->unlockWorld();
- return;
- }
- index++;
- }
- cs.unlock();
- World::INSTANCE->unlockWorld();
- }
- int Dimension::getId() const
- {
- return id;
- }
- float Dimension::getGravity() const
- {
- return gravity;
- }
|