#include "Dimension.h" #include "Constants.h" #include "Datei.h" #include "Game.h" #include "Globals.h" #include "World.h" using namespace Framework; #define MAX_VIEW_DISTANCE CHUNK_SIZE * 8 Dimension::Dimension( int id ) : dimensionId( id ), chunks( new Trie() ), entities( new RCArray() ) {} Dimension::~Dimension() { entities->release(); chunks->release(); } 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 ); } Block* Dimension::zBlock( Vec3 location ) { Chunk* c = zChunk( currentGame->getChunkCenter( location.x, location.y ) ); if( c ) return c->zBlockAt( location ); return 0; } Block* Dimension::getBlock( Vec3 location ) { cs.lock(); Chunk* c = zChunk( currentGame->getChunkCenter( location.x, location.y ) ); if( c ) { Block* b = c->zBlockAt( location ); b = b ? dynamic_cast(b->getThis()) : 0; cs.unlock(); return b; } cs.unlock(); return 0; } void Dimension::addEntity( Entity* entity ) { entities->add( entity ); } void Dimension::setChunk( Chunk* chunk, Punkt center, World* zWorld ) { char addr[ 8 ]; getAddrOfWorld( center, addr ); Chunk* old = chunks->z( addr, 8 ); cs.lock(); if( old ) { zWorld->setVisibility( old, 0 ); 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 ); if( chunk ) { zWorld->setVisibility( chunk, 1 ); } cs.unlock(); } int Dimension::getDimensionId() const { return dimensionId; } bool Dimension::hasChunck( int x, int y ) const { return zChunk( Punkt( x, y ) ); } void Dimension::removeDistantChunks( Punkt wPos, World* zWorld ) { Array removed; int index = 0; for( Chunk* chunk : chunkList ) { if( (chunk->getCenter() - wPos).getLength() > MAX_VIEW_DISTANCE ) removed.add( index, 0 ); index++; } for( int i : removed ) { Chunk* chunk = chunkList.get( i ); zWorld->setVisibility( chunk, 0 ); setChunk( 0, chunk->getCenter(), zWorld ); } } void Dimension::setBlock( Block* block ) { cs.lock(); Chunk* c = zChunk( currentGame->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( currentGame->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(e->getThis()); cs.unlock(); return result; } } cs.unlock(); return 0; } void Dimension::removeEntity( int id ) { currentGame->lockWorld(); cs.lock(); int index = 0; for( Entity* e : *entities ) { if( e->getId() == id ) { currentGame->setVisibility( e, 0 ); entities->remove( index ); cs.unlock(); currentGame->unlockWorld(); return; } index++; } cs.unlock(); currentGame->unlockWorld(); }