|
@@ -3,15 +3,16 @@
|
|
|
#include "Player.h"
|
|
|
#include "OverworldDimension.h"
|
|
|
#include "AddChunkUpdate.h"
|
|
|
+#include "NoBlock.h"
|
|
|
|
|
|
using namespace Framework;
|
|
|
|
|
|
-GameClient::GameClient( Player *zPlayer, FCKlient *client )
|
|
|
+GameClient::GameClient( Player* zPlayer, FCKlient* client )
|
|
|
: ReferenceCounter(),
|
|
|
zPlayer( zPlayer ),
|
|
|
client( client ),
|
|
|
writer( client->zClient() ),
|
|
|
- viewDistance( 5 ),
|
|
|
+ viewDistance( DEFAULT_VIEW_DISTANCE ),
|
|
|
first( 1 ),
|
|
|
online( 1 )
|
|
|
{}
|
|
@@ -21,7 +22,7 @@ GameClient::~GameClient()
|
|
|
client->release();
|
|
|
}
|
|
|
|
|
|
-void GameClient::sendWorldUpdate( WorldUpdate *zUpdate )
|
|
|
+void GameClient::sendWorldUpdate( WorldUpdate* zUpdate )
|
|
|
{
|
|
|
if( zPlayer->getCurrentDimensionId() == zUpdate->getAffectedDimension() )
|
|
|
{
|
|
@@ -29,18 +30,18 @@ void GameClient::sendWorldUpdate( WorldUpdate *zUpdate )
|
|
|
if( abs( pos.x - zUpdate->getMinAffectedPoint().x ) < viewDistance * CHUNK_SIZE || (abs( pos.x - zUpdate->getMaxAffectedPoint().x ) < viewDistance * CHUNK_SIZE) || abs( pos.y - zUpdate->getMinAffectedPoint().y ) < viewDistance * CHUNK_SIZE || (abs( pos.y - zUpdate->getMaxAffectedPoint().y ) < viewDistance * CHUNK_SIZE) )
|
|
|
{
|
|
|
cs.Enter();
|
|
|
- writer.schreibe( (char *)&Message::INGAME_MESSAGE, 1 );
|
|
|
- writer.schreibe( (char *)&Message::WORLD_UPDATE, 1 );
|
|
|
+ writer.schreibe( (char*)&Message::INGAME_MESSAGE, 1 );
|
|
|
+ writer.schreibe( (char*)&Message::WORLD_UPDATE, 1 );
|
|
|
zUpdate->write( &writer );
|
|
|
cs.Leave();
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-void GameClient::reply( Game *zGame )
|
|
|
+void GameClient::reply( Game* zGame )
|
|
|
{
|
|
|
cs.Enter();
|
|
|
- for( auto req = requests.getIterator(); req; req++ )
|
|
|
+ for( auto req : requests )
|
|
|
zGame->api( req, this );
|
|
|
requests.leeren();
|
|
|
cs.Leave();
|
|
@@ -48,18 +49,18 @@ void GameClient::reply( Game *zGame )
|
|
|
int y = (int)zPlayer->getPosition().y;
|
|
|
int d = zPlayer->getCurrentDimensionId();
|
|
|
cs.Enter();
|
|
|
- writer.schreibe( (char *)&Message::INGAME_MESSAGE, 1 );
|
|
|
- writer.schreibe( (char *)&Message::POSITION_UPDATE, 1 );
|
|
|
+ writer.schreibe( (char*)&Message::INGAME_MESSAGE, 1 );
|
|
|
+ writer.schreibe( (char*)&Message::POSITION_UPDATE, 1 );
|
|
|
float f = zPlayer->getPosition().x;
|
|
|
- writer.schreibe( (char *)&f, 4 );
|
|
|
+ writer.schreibe( (char*)&f, 4 );
|
|
|
f = zPlayer->getPosition().y;
|
|
|
- writer.schreibe( (char *)&f, 4 );
|
|
|
+ writer.schreibe( (char*)&f, 4 );
|
|
|
f = zPlayer->getPosition().z;
|
|
|
- writer.schreibe( (char *)&f, 4 );
|
|
|
+ writer.schreibe( (char*)&f, 4 );
|
|
|
f = zPlayer->getFaceDir().x;
|
|
|
- writer.schreibe( (char *)&f, 4 );
|
|
|
+ writer.schreibe( (char*)&f, 4 );
|
|
|
f = zPlayer->getFaceDir().y;
|
|
|
- writer.schreibe( (char *)&f, 4 );
|
|
|
+ writer.schreibe( (char*)&f, 4 );
|
|
|
cs.Leave();
|
|
|
// send world to client
|
|
|
if( first )
|
|
@@ -69,10 +70,10 @@ void GameClient::reply( Game *zGame )
|
|
|
{
|
|
|
for( int yP = y - CHUNK_SIZE * viewDistance; y <= y + CHUNK_SIZE * viewDistance; y += CHUNK_SIZE )
|
|
|
{
|
|
|
- Chunk *chunk = zGame->zDimension( d )->zChunk( zGame->getChunkCenter( xP, yP ) );
|
|
|
+ Chunk* chunk = zGame->zDimension( d )->zChunk( zGame->getChunkCenter( xP, yP ) );
|
|
|
if( chunk )
|
|
|
{
|
|
|
- AddChunkUpdate update( dynamic_cast<Chunk *>(chunk->getThis()) );
|
|
|
+ AddChunkUpdate update( dynamic_cast<Chunk*>(chunk->getThis()) );
|
|
|
sendWorldUpdate( &update );
|
|
|
}
|
|
|
}
|
|
@@ -91,10 +92,10 @@ void GameClient::reply( Game *zGame )
|
|
|
{
|
|
|
if( xP < lastMin.x || xP > lastMax.x || yP < lastMin.y || yP > lastMax.y )
|
|
|
{
|
|
|
- Chunk *chunk = zGame->zDimension( d )->zChunk( zGame->getChunkCenter( x, y ) );
|
|
|
+ Chunk* chunk = zGame->zDimension( d )->zChunk( zGame->getChunkCenter( x, y ) );
|
|
|
if( chunk )
|
|
|
{
|
|
|
- AddChunkUpdate update( dynamic_cast<Chunk *>(chunk->getThis()) );
|
|
|
+ AddChunkUpdate update( dynamic_cast<Chunk*>(chunk->getThis()) );
|
|
|
sendWorldUpdate( &update );
|
|
|
}
|
|
|
else
|
|
@@ -113,12 +114,12 @@ void GameClient::logout()
|
|
|
online = 0;
|
|
|
}
|
|
|
|
|
|
-void GameClient::addMessage( StreamReader *reader )
|
|
|
+void GameClient::addMessage( StreamReader* reader )
|
|
|
{
|
|
|
short len = 0;
|
|
|
- reader->lese( (char *)&len, 2 );
|
|
|
- InMemoryBuffer *buffer = new InMemoryBuffer();
|
|
|
- char *tmp = new char[ len ];
|
|
|
+ reader->lese( (char*)&len, 2 );
|
|
|
+ InMemoryBuffer* buffer = new InMemoryBuffer();
|
|
|
+ char* tmp = new char[ len ];
|
|
|
reader->lese( tmp, len );
|
|
|
buffer->schreibe( tmp, len );
|
|
|
delete[]tmp;
|
|
@@ -132,19 +133,19 @@ bool GameClient::isOnline() const
|
|
|
return online;
|
|
|
}
|
|
|
|
|
|
-void GameClient::sendResponse( NetworkResponse *zResponse )
|
|
|
+void GameClient::sendResponse( NetworkResponse* zResponse )
|
|
|
{
|
|
|
if( zResponse->isAreaAffected( { lastPos.x - (float)CHUNK_SIZE * (float)viewDistance, lastPos.y - (float)CHUNK_SIZE * (float)viewDistance, 0.f }, { lastPos.x + (float)CHUNK_SIZE * (float)viewDistance, lastPos.y + (float)CHUNK_SIZE * (float)viewDistance, (float)WORLD_HEIGHT } ) )
|
|
|
{
|
|
|
cs.Leave();
|
|
|
- writer.schreibe( (char *)&Message::INGAME_MESSAGE, 1 );
|
|
|
- writer.schreibe( (char *)&Message::API_MESSAGE, 1 );
|
|
|
+ writer.schreibe( (char*)&Message::INGAME_MESSAGE, 1 );
|
|
|
+ writer.schreibe( (char*)&Message::API_MESSAGE, 1 );
|
|
|
zResponse->writeTo( client->zWriter() );
|
|
|
cs.Leave();
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-Player *GameClient::zEntity() const
|
|
|
+Player* GameClient::zEntity() const
|
|
|
{
|
|
|
return zPlayer;
|
|
|
}
|
|
@@ -157,7 +158,7 @@ Game::Game( Framework::Text name, Framework::Text worldsDir )
|
|
|
updates( new RCArray<WorldUpdate>() ),
|
|
|
clients( new RCArray<GameClient>() ),
|
|
|
ticker( new TickOrganizer() ),
|
|
|
- path( (const char *)(worldsDir + "/" + name) ),
|
|
|
+ path( (const char*)(worldsDir + "/" + name) ),
|
|
|
stop( 0 ),
|
|
|
tickId( 0 ),
|
|
|
nextEntityId( 0 ),
|
|
@@ -171,12 +172,12 @@ Game::Game( Framework::Text name, Framework::Text worldsDir )
|
|
|
if( d.existiert() )
|
|
|
{
|
|
|
d.open( Datei::Style::lesen );
|
|
|
- d.lese( (char *)&nextEntityId, 4 );
|
|
|
+ d.lese( (char*)&nextEntityId, 4 );
|
|
|
d.close();
|
|
|
}
|
|
|
int seed = 0;
|
|
|
int index = 0;
|
|
|
- for( char *n = name; *n; n++ )
|
|
|
+ for( char* n = name; *n; n++ )
|
|
|
seed += (int)pow( (float)*n * 31, (float)++index );
|
|
|
generator = new WorldGenerator( seed, this );
|
|
|
loader = new WorldLoader( this );
|
|
@@ -199,10 +200,10 @@ void Game::thread()
|
|
|
{
|
|
|
m.messungStart();
|
|
|
ticker->nextTick();
|
|
|
- int index = 0;
|
|
|
Array<int> removed;
|
|
|
cs.Enter();
|
|
|
- for( auto player = clients->getIterator(); player; player++, index++ )
|
|
|
+ int index = 0;
|
|
|
+ for( auto player : *clients )
|
|
|
{
|
|
|
if( !player->isOnline() )
|
|
|
{
|
|
@@ -210,20 +211,21 @@ void Game::thread()
|
|
|
pFile.setDatei( path + "/player/" + player->zEntity()->getName() );
|
|
|
if( pFile.open( Datei::Style::schreiben ) )
|
|
|
PlayerEntityType::INSTANCE->saveEntity( player->zEntity(), &pFile );
|
|
|
- removed.add( player, 0 );
|
|
|
+ removed.add( index, 0 );
|
|
|
}
|
|
|
+ index++;
|
|
|
}
|
|
|
- for( auto i = removed.getIterator(); i; i++ )
|
|
|
+ for( auto i : removed )
|
|
|
clients->remove( i );
|
|
|
cs.Leave();
|
|
|
- for( auto dim = dimensions->getIterator(); dim; dim++ )
|
|
|
+ for( auto dim : *dimensions )
|
|
|
dim->tickEntities( this );
|
|
|
cs.Enter();
|
|
|
- while( updates->z( 0 ) )
|
|
|
+ while( updates->hat( 0 ) )
|
|
|
{
|
|
|
- WorldUpdate *update = updates->z( 0 );
|
|
|
+ WorldUpdate* update = updates->z( 0 );
|
|
|
cs.Leave();
|
|
|
- for( auto client = clients->getIterator(); client; client++ )
|
|
|
+ for( auto client : *clients )
|
|
|
client->sendWorldUpdate( update );
|
|
|
if( !zDimension( update->getAffectedDimension() ) )
|
|
|
addDimension( new Dimension( update->getAffectedDimension() ) );
|
|
@@ -232,7 +234,7 @@ void Game::thread()
|
|
|
updates->remove( 0 );
|
|
|
}
|
|
|
cs.Leave();
|
|
|
- for( auto client = clients->getIterator(); client; client++ )
|
|
|
+ for( auto client : *clients )
|
|
|
client->reply( this );
|
|
|
m.messungEnde();
|
|
|
double sec = m.getSekunden();
|
|
@@ -242,7 +244,7 @@ void Game::thread()
|
|
|
save();
|
|
|
}
|
|
|
|
|
|
-void Game::api( Framework::StreamReader *zRequest, GameClient *zOrigin )
|
|
|
+void Game::api( Framework::StreamReader* zRequest, GameClient* zOrigin )
|
|
|
{
|
|
|
char type;
|
|
|
zRequest->lese( &type, 1 );
|
|
@@ -252,8 +254,8 @@ void Game::api( Framework::StreamReader *zRequest, GameClient *zOrigin )
|
|
|
case 1: // world
|
|
|
{
|
|
|
int dimensionId;
|
|
|
- zRequest->lese( (char *)&dimensionId, 4 );
|
|
|
- Dimension *dim = zDimension( dimensionId );
|
|
|
+ zRequest->lese( (char*)&dimensionId, 4 );
|
|
|
+ Dimension* dim = zDimension( dimensionId );
|
|
|
if( !dim )
|
|
|
{
|
|
|
dim = new Dimension( dimensionId );
|
|
@@ -262,47 +264,53 @@ void Game::api( Framework::StreamReader *zRequest, GameClient *zOrigin )
|
|
|
dim->api( zRequest, &response );
|
|
|
break;
|
|
|
}
|
|
|
+ case 2: // player
|
|
|
+ zOrigin->zEntity()->api( zRequest, &response );
|
|
|
+ break;
|
|
|
default:
|
|
|
std::cout << "received unknown api request in game with type " << (int)type << "\n";
|
|
|
}
|
|
|
- if( response.isBroadcast() )
|
|
|
- distributeResponse( &response );
|
|
|
- else
|
|
|
- zOrigin->sendResponse( &response );
|
|
|
+ if( !response.isEmpty() )
|
|
|
+ {
|
|
|
+ if( response.isBroadcast() )
|
|
|
+ distributeResponse( &response );
|
|
|
+ else
|
|
|
+ zOrigin->sendResponse( &response );
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
-void Game::distributeResponse( NetworkResponse *zResponse )
|
|
|
+void Game::distributeResponse( NetworkResponse* zResponse )
|
|
|
{
|
|
|
- for( auto client = clients->getIterator(); client; client++ )
|
|
|
+ for( auto client : *clients )
|
|
|
client->sendResponse( zResponse );
|
|
|
}
|
|
|
|
|
|
-void Game::requestWorldUpdate( WorldUpdate *update )
|
|
|
+void Game::requestWorldUpdate( WorldUpdate* update )
|
|
|
{
|
|
|
cs.Enter();
|
|
|
updates->add( update );
|
|
|
cs.Leave();
|
|
|
}
|
|
|
|
|
|
-GameClient *Game::addPlayer( FCKlient *client, Framework::Text name )
|
|
|
+GameClient* Game::addPlayer( FCKlient* client, Framework::Text name )
|
|
|
{
|
|
|
cs.Enter();
|
|
|
Datei pFile;
|
|
|
pFile.setDatei( path + "/player/" + name );
|
|
|
- Player *player;
|
|
|
+ Player* player;
|
|
|
bool isNew = 0;
|
|
|
if( !pFile.existiert() || !pFile.open( Datei::Style::lesen ) )
|
|
|
{
|
|
|
- player = (Player *)PlayerEntityType::INSTANCE->createEntityAt( Vec3<float>( 0, 0, 0 ), OverworldDimension::ID, this );
|
|
|
+ player = (Player*)PlayerEntityType::INSTANCE->createEntityAt( Vec3<float>( 0, 0, 0 ), OverworldDimension::ID, this );
|
|
|
player->setName( name );
|
|
|
isNew = 1;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
- player = (Player *)PlayerEntityType::INSTANCE->loadEntity( this, &pFile );
|
|
|
+ player = (Player*)PlayerEntityType::INSTANCE->loadEntity( this, &pFile );
|
|
|
pFile.close();
|
|
|
}
|
|
|
- requestArea( { (int)player->getPosition().x - 100, (int)player->getPosition().y - 100, (int)player->getPosition().x + 100, (int)player->getPosition().y + 100, player->getCurrentDimensionId() } );
|
|
|
+ requestArea( { (int)player->getPosition().x - DEFAULT_VIEW_DISTANCE * CHUNK_SIZE, (int)player->getPosition().y - DEFAULT_VIEW_DISTANCE * CHUNK_SIZE, (int)player->getPosition().x + DEFAULT_VIEW_DISTANCE * CHUNK_SIZE, (int)player->getPosition().y + DEFAULT_VIEW_DISTANCE * CHUNK_SIZE, player->getCurrentDimensionId() } );
|
|
|
while( !zDimension( OverworldDimension::ID ) || (isNew && !zDimension( OverworldDimension::ID )->zChunk( getChunkCenter( (int)player->getPosition().x, (int)player->getPosition().y ) )) )
|
|
|
{
|
|
|
cs.Leave();
|
|
@@ -311,22 +319,22 @@ GameClient *Game::addPlayer( FCKlient *client, Framework::Text name )
|
|
|
}
|
|
|
if( isNew )
|
|
|
{
|
|
|
- Block *b = 0;
|
|
|
+ Either<Block*, int> b = NoBlockBlockType::ID;
|
|
|
int h = WORLD_HEIGHT;
|
|
|
- while( !IS_BLOCK( b ) && h > 0 )
|
|
|
+ while( ((b.isA() && (!(Block*)b || ((Block*)b)->isPassable())) || (b.isB() && StaticRegistry<BlockType>::INSTANCE.zElement( b )->zDefault()->isPassable())) && h > 0 )
|
|
|
b = zBlockAt( { (int)player->getPosition().x, (int)player->getPosition().y, --h }, player->getCurrentDimensionId() );
|
|
|
player->setPosition( { player->getPosition().x, player->getPosition().y, (float)h + 1.f } );
|
|
|
}
|
|
|
zDimension( OverworldDimension::ID )->addEntity( player );
|
|
|
- GameClient *gameClient = new GameClient( player, client );
|
|
|
+ GameClient* gameClient = new GameClient( player, client );
|
|
|
clients->add( gameClient );
|
|
|
cs.Leave();
|
|
|
- return dynamic_cast<GameClient *>(gameClient->getThis());
|
|
|
+ return dynamic_cast<GameClient*>(gameClient->getThis());
|
|
|
}
|
|
|
|
|
|
bool Game::isChunkLoaded( int x, int y, int dimension ) const
|
|
|
{
|
|
|
- Dimension *dim = zDimension( dimension );
|
|
|
+ Dimension* dim = zDimension( dimension );
|
|
|
return (dim && dim->hasChunck( x, y ));
|
|
|
}
|
|
|
|
|
@@ -335,17 +343,17 @@ bool Game::doesChunkExist( int x, int y, int dimension ) const
|
|
|
return isChunkLoaded( x, y, dimension ) || loader->existsChunk( x, y, dimension );
|
|
|
}
|
|
|
|
|
|
-Block *Game::zBlockAt( Framework::Vec3<int> location, int dimension ) const
|
|
|
+Framework::Either<Block*, int> Game::zBlockAt( Framework::Vec3<int> location, int dimension ) const
|
|
|
{
|
|
|
- Dimension *dim = zDimension( dimension );
|
|
|
+ Dimension* dim = zDimension( dimension );
|
|
|
if( dim )
|
|
|
return dim->zBlock( location, this );
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
-Dimension *Game::zDimension( int id ) const
|
|
|
+Dimension* Game::zDimension( int id ) const
|
|
|
{
|
|
|
- for( auto dim = dimensions->getIterator(); dim; dim++ )
|
|
|
+ for( auto dim : *dimensions )
|
|
|
{
|
|
|
if( dim->getDimensionId() == id )
|
|
|
return dim;
|
|
@@ -379,9 +387,9 @@ void Game::save() const
|
|
|
Datei d;
|
|
|
d.setDatei( path + "/eid" );
|
|
|
d.open( Datei::Style::schreiben );
|
|
|
- d.schreibe( (char *)&nextEntityId, 4 );
|
|
|
+ d.schreibe( (char*)&nextEntityId, 4 );
|
|
|
d.close();
|
|
|
- for( auto dim = dimensions->getIterator(); dim; dim++ )
|
|
|
+ for( auto dim : *dimensions )
|
|
|
dim->save( path );
|
|
|
}
|
|
|
|
|
@@ -391,7 +399,7 @@ void Game::requestStop()
|
|
|
warteAufThread( 1000000 );
|
|
|
}
|
|
|
|
|
|
-void Game::addDimension( Dimension *d )
|
|
|
+void Game::addDimension( Dimension* d )
|
|
|
{
|
|
|
dimensions->add( d );
|
|
|
}
|
|
@@ -402,4 +410,9 @@ int Game::getNextEntityId()
|
|
|
int result = nextEntityId++;
|
|
|
cs.Leave();
|
|
|
return result;
|
|
|
+}
|
|
|
+
|
|
|
+WorldGenerator* Game::zGenerator() const
|
|
|
+{
|
|
|
+ return generator;
|
|
|
}
|