#include #include #include #include #include "World.h" #include "Globals.h" #include "WorldUpdate.h" #include "Constants.h" #include "Registries.h" #include "BasicBlocks.h" #include "Game.h" #include using namespace Network; using namespace Framework; World::World( Bildschirm3D* zScreen ) : Thread() { renderedWorld = new Welt3D(); renderedWorld->addDiffuseLight( DiffuseLight{ Vec3( 0.5f, 0.5f, -1.f ), Vec3( 1.f, 1.f, 1.f ) } ); dimensions = new RCArray(); currentPlayer = new CurrentPlayer(); zScreenPtr = zScreen; kam = new PlayerKam( zScreen ); kam->setWelt( renderedWorld ); zScreen->addKamera( kam ); firstMessage = 1; hasTarget = 0; entityTarget = -1; start(); } World::~World() { zScreenPtr->removeKamera( kam ); dimensions->release(); currentPlayer->release(); } void World::update( bool background ) { NetworkReader* serverMessageReader = 0; unsigned char type = 0; while( background ? serverMessageReader = network->zFactoryClient()->getNextBackgroundMessage() : serverMessageReader = network->zFactoryClient()->getNextForegroundMessage() ) { serverMessageReader->lese( (char*)&type, 1 ); if( type == 2 ) // WORLD UPDATE { int id = 0; serverMessageReader->lese( (char*)&id, 4 ); STATIC_REGISTRY( WorldUpdateType ).zElement( id )->applyUpdate( serverMessageReader ); } if( type == 3 ) // API MESSAGE { // TODO: process messages } if( type == 4 ) // POSITION UPDATE { Vec3 pos; Vec3 dir; serverMessageReader->lese( (char*)&pos.x, 4 ); serverMessageReader->lese( (char*)&pos.y, 4 ); serverMessageReader->lese( (char*)&pos.z, 4 ); kam->setPosition( pos + Vec3( 0.f, 0.f, 1.5f ) ); if( firstMessage ) { firstMessage = 0; serverMessageReader->lese( (char*)&dir.x, 4 ); serverMessageReader->lese( (char*)&dir.y, 4 ); serverMessageReader->lese( (char*)&dir.z, 4 ); kam->setDirection( dir ); } for( Dimension* dim : *dimensions ) dim->removeDistantChunks( { (int)pos.x, (int)pos.y }, this ); char b = 0; serverMessageReader->lese( &b, 1 ); if( hasTarget && dimensions->hat( 0 ) ) { if( entityTarget == -1 ) { Block* block = zBlockAt( target, dimensions->z( 0 )->getDimensionId() ); if( block ) block->setAmbientFactor( block->getAmbientFactor() - 0.2f ); } } if( b == 1 ) { serverMessageReader->lese( (char*)&entityTarget, 4 ); hasTarget = 1; } else if( b == 2 ) { serverMessageReader->lese( (char*)&target.x, 4 ); serverMessageReader->lese( (char*)&target.y, 4 ); serverMessageReader->lese( (char*)&target.z, 4 ); int side = 0; serverMessageReader->lese( (char*)&side, 4 ); hasTarget = 1; } else hasTarget = 0; if( hasTarget && dimensions->hat( 0 ) ) { if( entityTarget == -1 ) { Block* block = zBlockAt( target, dimensions->z( 0 )->getDimensionId() ); if( block ) block->setAmbientFactor( block->getAmbientFactor() + 0.2f ); } } ((Game*)(Menu*)menuRegister->get( "game" ))->updatePosition( pos, hasTarget, target ); } network->zFactoryClient()->endMessageReading( background ); } network->zFactoryClient()->endMessageReading( background ); } void World::setChunk( Chunk* chunk, int dimensionId ) { zScreenPtr->lock(); Dimension* zDim = zDimension( dimensionId ); if( !zDim ) { zDim = new Dimension( dimensionId ); dimensions->add( zDim ); } zDim->setChunk( chunk, chunk->getCenter(), this ); zScreenPtr->unlock(); } void World::thread() { new AsynchronCall( [this]() { while( true ) { zScreenPtr->lock(); if( currentGame != this ) { zScreenPtr->unlock(); return; } zScreenPtr->unlock(); update( 0 ); Sleep( 10 ); } } ); while( true ) { zScreenPtr->lock(); if( currentGame != this ) { zScreenPtr->unlock(); return; } zScreenPtr->unlock(); update( 1 ); Sleep( 10 ); } } Block* World::zBlockAt( Framework::Vec3 location, int dimension ) const { Dimension* dim = zDimension( dimension ); if( dim ) return dim->zBlock( location ); return 0; } Dimension* World::zDimension( int id ) const { for( auto dim : *dimensions ) { if( dim->getDimensionId() == id ) return dim; } return 0; } Dimension* World::zDimensionOrCreate( int id ) { zScreenPtr->lock(); Dimension* d = zDimension( id ); if( !d ) { d = new Dimension( id ); dimensions->add( d ); } zScreenPtr->unlock(); return d; } void World::setVisibility( Chunk* zChunk, bool visible ) { renderedWorld->lock(); if( visible ) renderedWorld->addCollection( dynamic_cast(zChunk->getThis()) ); else renderedWorld->removeCollection( zChunk ); renderedWorld->unlock(); } Framework::Bildschirm3D* World::zScreen() const { return zScreenPtr; } Framework::Punkt World::getChunkCenter( int x, int y ) const { return Punkt( ((x < 0 ? x + 1 : x) / CHUNK_SIZE) * CHUNK_SIZE + (x < 0 ? -CHUNK_SIZE : CHUNK_SIZE) / 2, ((y < 0 ? y + 1 : y) / CHUNK_SIZE) * CHUNK_SIZE + (y < 0 ? -CHUNK_SIZE : CHUNK_SIZE) / 2 ); }