#include "Chunk.h" #include "Constants.h" #include "Globals.h" #include "Registries.h" Chunk::Chunk( Framework::Punkt location, int dimensionId ) : ReferenceCounter(), dimensionId( dimensionId ), location( location ), isLoading( 0 ) {} Chunk::Chunk( Framework::Punkt location, int dimensionId, Framework::StreamReader* zReader ) : Chunk( location, dimensionId ) { load( zReader ); } Chunk::~Chunk() {} 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 ); bool d; zReader->lese( (char*)&d, 1 ); if( d ) { Block* block = STATIC_REGISTRY( BlockType ).zElement( id )->loadBlock( { pos.x + location.x - CHUNK_SIZE / 2, pos.y + location.y - CHUNK_SIZE / 2, pos.z }, zReader ); if( block ) setBlock( block ); } else if( STATIC_REGISTRY( BlockType ).zElement( id )->needsInstance() ) setBlock( STATIC_REGISTRY( BlockType ).zElement( 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(); } int Chunk::getDimensionId() const { return dimensionId; } 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() || c->isPassable() ); } } cs.unlock(); }