#include "Chunk.h" #include "Constants.h" #include "Globals.h" #include "Registries.h" Chunk::Chunk(Framework::Punkt location) : ReferenceCounter(), location(location), isLoading(0) {} Chunk::Chunk(Framework::Punkt location, Framework::StreamReader* zReader) : Chunk(location) { load(zReader); } Chunk::~Chunk() { char msg = 1; // remove observer network->zFactoryClient()->chunkAPIRequest(location, &msg, 1); } void Chunk::api(char* message) { switch (message[0]) { case 0: // set block { int index = *(int*)(message + 1); int id = *(int*)(message + 5); Framework::Vec3 location((index / WORLD_HEIGHT) / CHUNK_SIZE, (index / WORLD_HEIGHT) % CHUNK_SIZE, index % WORLD_HEIGHT); location.x += this->location.x - CHUNK_SIZE / 2; location.y += this->location.y - CHUNK_SIZE / 2; if (blockTypes[id]->doesNeedInstance()) { Block* zB = blockTypes[id]->createBlock(location); setBlock(zB); } else { Block* zB = zBlockAt(location); if (zB) removeBlock(zB); } break; } } } Block* Chunk::zBlockAt(Framework::Vec3 location) { cs.lock(); for (Block* b : blocks) { if (Framework::Vec3((int)floor(b->getPos().x), (int)floor(b->getPos().y), (int)floor(b->getPos().z)) == location) { cs.unlock(); return b; } } cs.unlock(); return 0; } void Chunk::setBlock(Block* block) { cs.lock(); Framework::Vec3 pos = (Framework::Vec3)block->getPos(); for (Framework::Iterator iterator = blocks.begin(); iterator; iterator++) { if (pos == (Framework::Vec3)iterator->getPos()) { iterator->release(); iterator.set(block); cs.unlock(); return; } } blocks.add(block); cs.unlock(); if (!isLoading) updateVisibility(); } void Chunk::removeBlock(Block* zBlock) { cs.lock(); int index = 0; for (Framework::Iterator iterator = blocks.begin(); iterator; iterator++, index++) { if (zBlock == (Block*)iterator) { blocks.remove(index); cs.unlock(); if (!isLoading) updateVisibility(); return; } } cs.unlock(); } void Chunk::load(Framework::StreamReader* zReader) { isLoading = 1; Framework::Vec3 pos = { 0, 0, 0 }; unsigned short id; zReader->lese((char*)&id, 2); while (id) { zReader->lese((char*)&pos.x, 4); zReader->lese((char*)&pos.y, 4); zReader->lese((char*)&pos.z, 4); if (blockTypes[id]->doesNeedInstance()) setBlock(blockTypes[id]->createBlock({ pos.x + location.x - CHUNK_SIZE / 2, pos.y + location.y - CHUNK_SIZE / 2, pos.z })); zReader->lese((char*)&id, 2); } isLoading = 0; updateVisibility(); } Framework::Punkt Chunk::getCenter() const { return location; } Framework::Vec3 Chunk::getMin() const { return { location.x - CHUNK_SIZE / 2, location.y - CHUNK_SIZE / 2, 0 }; } Framework::Vec3 Chunk::getMax() const { return { location.x + CHUNK_SIZE / 2, location.y + CHUNK_SIZE / 2, WORLD_HEIGHT }; } void Chunk::forAll(std::function f) { cs.lock(); for (Block* b : blocks) f(b); cs.unlock(); } void Chunk::updateVisibility() { cs.lock(); for (Block* b : blocks) { Framework::Vec3 pos = Framework::Vec3((int)floor(b->getPos().x), (int)floor(b->getPos().y), (int)floor(b->getPos().z)); for (int i = 0; i < 6; i++) { Block* c = zBlockAt(pos + getDirection(getDirectionFromIndex(i))); b->setSideVisible(getDirectionFromIndex(i), !c || c->isTransparent()); } } cs.unlock(); }