Jelajahi Sumber

Entities will now be saved and loaded

Kolja Strohm 3 tahun lalu
induk
melakukan
ddd5c63ba0

+ 1 - 1
FactoryCraft/AddChunkUpdate.cpp

@@ -19,7 +19,7 @@ void AddChunkUpdate::onUpdate( Dimension *zDimension )
     zDimension->addChunk( dynamic_cast<Chunk *>( chunk->getThis() ) );
 }
 
-void AddChunkUpdate::write( Framework::Writer *zWriter )
+void AddChunkUpdate::write( Framework::StreamWriter *zWriter )
 {
     zWriter->schreibe( (char *)&AddChunkUpdateType::ID, 4 );
     int dimensionID = chunk->getDimensionId();

+ 1 - 1
FactoryCraft/AddChunkUpdate.h

@@ -14,7 +14,7 @@ public:
     ~AddChunkUpdate();
 
     void onUpdate( Dimension *zDimension ) override;
-    void write( Framework::Writer *zWriter ) override;
+    void write( Framework::StreamWriter *zWriter ) override;
 };
 
 class AddChunkUpdateType : WorldUpdateType

+ 2 - 2
FactoryCraft/BasicBlock.cpp

@@ -18,12 +18,12 @@ DirtBlockType::DirtBlockType()
     : BlockType( ID )
 {}
 
-void DirtBlockType::loadSuperBlock( Block *zBlock, Framework::Reader *zReader )
+void DirtBlockType::loadSuperBlock( Block *zBlock, Framework::StreamReader *zReader )
 {
     BlockType::loadSuperBlock( zBlock, zReader );
 }
 
-void DirtBlockType::saveSuperBlock( Block *zBlock, Framework::Writer *zWriter )
+void DirtBlockType::saveSuperBlock( Block *zBlock, Framework::StreamWriter *zWriter )
 {
     BlockType::saveSuperBlock( zBlock, zWriter );
 }

+ 2 - 8
FactoryCraft/BasicBlocks.h

@@ -24,18 +24,15 @@ class DirtBlockType : public BlockType
     REGISTRABLE( DirtBlockType )
 
 protected:
-    virtual void loadSuperBlock( Block *zBlock, Framework::Reader *zReader ) override;
-    virtual void saveSuperBlock( Block *zBlock, Framework::Writer *zWriter ) override;
+    virtual void loadSuperBlock( Block *zBlock, Framework::StreamReader *zReader ) override;
+    virtual void saveSuperBlock( Block *zBlock, Framework::StreamWriter *zWriter ) override;
     virtual void createSuperBlock( Block *zBlock, Item *zItem ) override;
     virtual void createSuperItem( Block *zBlock, Item *zItem ) override;
     virtual Block *createBlock( Framework::Vec3<int> position, Game *zTarget ) override;
     virtual Item *createItem( Game *zTarget ) override;
     DirtBlockType();
 };
-
-#ifdef REGISTER
 REGISTER( DirtBlockType, BlockType )
-#endif
 
 class DirtBlockItemType : public BasicBlockItemType
 {
@@ -47,7 +44,4 @@ protected:
 public:
     virtual Item *createItem() const override;
 };
-
-#ifdef REGISTER
 REGISTER( DirtBlockItemType, ItemType )
-#endif

+ 3 - 3
FactoryCraft/Block.cpp

@@ -139,7 +139,7 @@ BasicBlockItemType::BasicBlockItemType( int id, ItemSkillLevelUpRule *levelUpRul
     : ItemType( id, levelUpRule, zBrokenType )
 {}
 
-void BasicBlockItemType::loadSuperItem( Item *zItem, Framework::Reader *zReader ) const
+void BasicBlockItemType::loadSuperItem( Item *zItem, Framework::StreamReader *zReader ) const
 {
     ItemType::loadSuperItem( zItem, zReader );
     BasicBlockItem *item = dynamic_cast<BasicBlockItem *>( zItem );
@@ -154,10 +154,10 @@ void BasicBlockItemType::loadSuperItem( Item *zItem, Framework::Reader *zReader
     zReader->lese( (char *)&item->speedModifier, 4 );
 }
 
-void BasicBlockItemType::saveSuperItem( Item *zItem, Framework::Writer *zWriter ) const
+void BasicBlockItemType::saveSuperItem( const Item *zItem, Framework::StreamWriter *zWriter ) const
 {
     ItemType::saveSuperItem( zItem, zWriter );
-    BasicBlockItem *item = dynamic_cast<BasicBlockItem *>( zItem );
+    const BasicBlockItem *item = dynamic_cast<const BasicBlockItem *>( zItem );
     if( !item )
         throw "BasicBlockItemType::saveSuperItem was called with an invalid item";
     zWriter->schreibe( (char *)&item->transparent, 1 );

+ 2 - 2
FactoryCraft/Block.h

@@ -98,7 +98,7 @@ class BasicBlockItemType : public ItemType
 {
 protected:
     BasicBlockItemType( int id, ItemSkillLevelUpRule *levelUpRule, const ItemType *zBrokenType );
-    virtual void loadSuperItem( Item *zItem, Framework::Reader *zReader ) const override;
-    virtual void saveSuperItem( Item *zItem, Framework::Writer *zWriter ) const override;
+    virtual void loadSuperItem( Item *zItem, Framework::StreamReader *zReader ) const override;
+    virtual void saveSuperItem( const Item *zItem, Framework::StreamWriter *zWriter ) const override;
     void initializeItem( BasicBlockItem *zItem, bool transparent, bool passable, float hp, float maxHP, float hardness, int toolId, float speedModifier ) const;
 };

+ 6 - 4
FactoryCraft/BlockType.cpp

@@ -11,8 +11,9 @@ BlockType::BlockType( int id )
     StaticRegistry<BlockType>::INSTANCE.registerT( this, id );
 }
 
-void BlockType::loadSuperBlock( Block *zBlock, Framework::Reader *zReader )
+void BlockType::loadSuperBlock( Block *zBlock, Framework::StreamReader *zReader )
 {
+    zBlock->loadInventory( zReader );
     zReader->lese( (char *)&zBlock->transparent, 1 );
     zReader->lese( (char *)&zBlock->passable, 1 );
     zReader->lese( (char *)&zBlock->hp, 4 );
@@ -24,8 +25,9 @@ void BlockType::loadSuperBlock( Block *zBlock, Framework::Reader *zReader )
     zBlock->zTool = StaticRegistry<ItemType>::INSTANCE.zElement( effectiveToolId );
 }
 
-void BlockType::saveSuperBlock( Block *zBlock, Framework::Writer *zWriter )
+void BlockType::saveSuperBlock( Block *zBlock, Framework::StreamWriter *zWriter )
 {
+    zBlock->saveInventory( zWriter );
     zWriter->schreibe( (char *)&zBlock->transparent, 1 );
     zWriter->schreibe( (char *)&zBlock->passable, 1 );
     zWriter->schreibe( (char *)&zBlock->hp, 4 );
@@ -68,14 +70,14 @@ void BlockType::createSuperItem( Block *zBlock, Item *zItem )
     item->toolId = zBlock->zTool->getId();
 }
 
-Block *BlockType::loadBlock( Framework::Vec3<int> position, Game *zTarget, Framework::Reader *zReader )
+Block *BlockType::loadBlock( Framework::Vec3<int> position, Game *zTarget, Framework::StreamReader *zReader )
 {
     Block *result = createBlock( position, zTarget );
     loadSuperBlock( result, zReader );
     return result;
 }
 
-void BlockType::saveBlock( Block *zBlock, Framework::Writer *zWriter )
+void BlockType::saveBlock( Block *zBlock, Framework::StreamWriter *zWriter )
 {
     saveSuperBlock( zBlock, zWriter );
 }

+ 4 - 4
FactoryCraft/BlockType.h

@@ -19,16 +19,16 @@ private:
 protected:
     BlockType( int id );
 
-    virtual void loadSuperBlock( Block *zBlock, Framework::Reader *zReader );
-    virtual void saveSuperBlock( Block *zBlock, Framework::Writer *zWriter );
+    virtual void loadSuperBlock( Block *zBlock, Framework::StreamReader *zReader );
+    virtual void saveSuperBlock( Block *zBlock, Framework::StreamWriter *zWriter );
     virtual void createSuperBlock( Block *zBlock, Item *zItem );
     virtual void createSuperItem( Block *zBlock, Item *zItem );
     virtual Block *createBlock( Framework::Vec3<int> position, Game *zTarget ) = 0;
     virtual Item *createItem( Game *zTarget ) = 0;
 
 public:
-    virtual Block *loadBlock( Framework::Vec3<int> position, Game *zTarget, Framework::Reader *zReader );
-    virtual void saveBlock( Block *zBlock, Framework::Writer *zWriter );
+    virtual Block *loadBlock( Framework::Vec3<int> position, Game *zTarget, Framework::StreamReader *zReader );
+    virtual void saveBlock( Block *zBlock, Framework::StreamWriter *zWriter );
     virtual Item *getItemFromBlock( Block *zBlock, Game *zTarget );
     virtual Block *createBlockAt( Framework::Vec3<int> position, Game *zTarget, Item *zUsedItem );
 

+ 4 - 4
FactoryCraft/Chunk.cpp

@@ -4,7 +4,7 @@
 
 
 Chunk::Chunk( Framework::Punkt location, Game *zGame, int dimensionId )
-    : EventThrower(),
+    : ReferenceCounter(),
     zGame( zGame ),
     dimensionId( dimensionId ),
     location( location )
@@ -17,7 +17,7 @@ Chunk::Chunk( Framework::Punkt location, Game *zGame, int dimensionId )
     zNeighbours[ 3 ] = 0;
 }
 
-Chunk::Chunk( Framework::Punkt location, Game *zGame, int dimensionId, Framework::Reader *zReader )
+Chunk::Chunk( Framework::Punkt location, Game *zGame, int dimensionId, Framework::StreamReader *zReader )
     : Chunk( location, zGame, dimensionId )
 {
     load( zReader );
@@ -130,7 +130,7 @@ void Chunk::setNeighbor( Direction dir, Chunk *zChunk )
     }
 }
 
-void Chunk::load( Framework::Reader *zReader )
+void Chunk::load( Framework::StreamReader *zReader )
 {
     for( int x = 0; x < CHUNK_SIZE; x++ )
     {
@@ -150,7 +150,7 @@ void Chunk::load( Framework::Reader *zReader )
     }
 }
 
-void Chunk::save( Framework::Writer *zWriter )
+void Chunk::save( Framework::StreamWriter *zWriter )
 {
     for( int x = 0; x < CHUNK_SIZE; x++ )
     {

+ 4 - 4
FactoryCraft/Chunk.h

@@ -10,7 +10,7 @@
 
 class Game;
 
-class Chunk : public EventThrower
+class Chunk : public virtual Framework::ReferenceCounter
 {
 private:
     Game *zGame;
@@ -21,14 +21,14 @@ private:
 
 public:
     Chunk( Framework::Punkt location, Game *zGame, int dimensionId );
-    Chunk( Framework::Punkt location, Game *zGame, int dimensionId, Framework::Reader *zReader );
+    Chunk( Framework::Punkt location, Game *zGame, int dimensionId, Framework::StreamReader *zReader );
     ~Chunk();
     Block *getBlockAt( Framework::Vec3<int> cLocation ) const;
     Block *zBlockAt( Framework::Vec3<int> cLocation ) const;
     void putBlockAt( Framework::Vec3<int> location, Block *block );
     void setNeighbor( Direction dir, Chunk *zChunk );
-    void load( Framework::Reader *zReader );
-    void save( Framework::Writer *zWriter );
+    void load( Framework::StreamReader *zReader );
+    void save( Framework::StreamWriter *zWriter );
     int getDimensionId() const;
     Framework::Punkt getCenter() const;
     Game *zGameObj() const;

+ 0 - 212
FactoryCraft/Datenbank.cpp

@@ -1,212 +0,0 @@
-#include "Datenbank.h"
-#include <iostream>
-
-// Inhalt der LSDatenbank Klasse aus Datenbank.h
-// Konstruktor
-LSDatenbank::LSDatenbank( InitDatei *zIni )
-    : ReferenceCounter()
-{
-    datenbank = new Datenbank( zIni->zWert( "DBBenutzer" )->getText(), zIni->zWert( "DBPasswort" )->getText(),
-                               zIni->zWert( "DBName" )->getText(), zIni->zWert( "DBIP" )->getText(),
-                               (unsigned short)TextZuInt( zIni->zWert( "DBPort" )->getText(), 10 ) );
-    if( !datenbank->istOk() )
-    {
-        std::cout << "LS: Die Verbindung zur Datenbank konnte nicht hergestellt werden.\nDas Programm wird beendet.";
-        exit( 1 );
-    }
-    InitializeCriticalSection( &cs );
-    Text befehl = "SELECT port, admin_port  FROM server WHERE id = ";
-    befehl += zIni->zWert( "ServerId" )->getText();
-    lock();
-    datenbank->befehl( befehl );
-    Result res = datenbank->getResult();
-    unlock();
-    if( res.zeilenAnzahl == 1 )
-    {
-        zIni->addWert( "ServerPort", res.values[ 0 ] );
-        zIni->addWert( "AdminServerPort", res.values[ 1 ] );
-    }
-    res.destroy();
-}
-
-// Destruktor
-LSDatenbank::~LSDatenbank()
-{
-    datenbank->release();
-    DeleteCriticalSection( &cs );
-}
-
-// nicht constant
-void LSDatenbank::lock()
-{
-    EnterCriticalSection( &cs );
-}
-
-void LSDatenbank::unlock()
-{
-    LeaveCriticalSection( &cs );
-}
-
-int LSDatenbank::istAdministrator( const char *name, const char *passwort )
-{
-    Text *befehl = new Text( "SELECT id FROM benutzer WHERE name = '" );
-    Text n( name );
-    n.ersetzen( "'", "''" );
-    befehl->append( (char *)n );
-    befehl->append( "' AND passwort = md5( '" );
-    Text p( passwort );
-    p.ersetzen( "'", "''" );
-    befehl->append( (char *)p );
-    befehl->append( "' )" );
-    lock();
-    datenbank->befehl( befehl->getText() );
-    Result res = datenbank->getResult();
-    unlock();
-    befehl->release();
-    int ret = 0;
-    if( res.zeilenAnzahl > 0 )
-        ret = TextZuInt( res.values[ 0 ].getText(), 10 );
-    res.destroy();
-    return ret;
-}
-
-bool LSDatenbank::adminHatRecht( int id, int recht )
-{
-    Text *befehl = new Text( "SELECT * FROM benutzer_rechte WHERE benutzer_id = " );
-    befehl->append( id );
-    befehl->append( " AND rechte_id = " );
-    befehl->append( recht );
-    lock();
-    datenbank->befehl( befehl->getText() );
-    int ret = datenbank->getZeilenAnzahl();
-    unlock();
-    befehl->release();
-    return ret != 0;
-}
-
-bool LSDatenbank::proveKlient( int num, int sNum )
-{
-    Text *befehl = new Text( "SELECT * FROM server_client WHERE server_id = " );
-    befehl->append( sNum );
-    befehl->append( " AND client_id = " );
-    befehl->append( num );
-    lock();
-    datenbank->befehl( befehl->getText() );
-    Result res = datenbank->getResult();
-    unlock();
-    befehl->release();
-    bool ret = 0;
-    if( res.zeilenAnzahl == 1 )
-        ret = 1;
-    res.destroy();
-    return ret;
-}
-
-Text *LSDatenbank::getKlientKey( int cId )
-{
-    lock();
-    if( !datenbank->befehl( Text( "SELECT schluessel FROM client WHERE id = " ) += cId ) )
-    {
-        unlock();
-        return 0;
-    }
-    Result res = datenbank->getResult();
-    unlock();
-    if( !res.zeilenAnzahl )
-    {
-        res.destroy();
-        return 0;
-    }
-    Text *ret = new Text( res.values[ 0 ].getText() );
-    res.destroy();
-    return ret;
-}
-
-void LSDatenbank::unregisterKlient( int num, int sNum )
-{
-    Text *befehl = new Text( "DELETE FROM server_client WHERE client_id = " );
-    befehl->append( num );
-    befehl->append( " AND server_id = " );
-    befehl->append( sNum );
-    lock();
-    datenbank->befehl( befehl->getText() );
-    int za = datenbank->getZeilenAnzahl();
-    unlock();
-    if( za == 1 )
-    {
-        befehl->setText( "UPDATE server SET tasks = tasks - 1 WHERE id = " );
-        befehl->append( sNum );
-        lock();
-        datenbank->befehl( befehl->getText() );
-        unlock();
-    }
-    befehl->release();
-}
-
-bool LSDatenbank::setServerStatus( int id, int status )
-{
-    Text *befehl = new Text( "UPDATE server SET server_status_id = " );
-    *befehl += status;
-    *befehl += "WHERE id = ";
-    *befehl += id;
-    lock();
-    if( !datenbank->befehl( befehl->getText() ) )
-    {
-        unlock();
-        befehl->release();
-        return 0;
-    }
-    bool ret = datenbank->getZeilenAnzahl() != 0;
-    unlock();
-    befehl->release();
-    return ret;
-}
-
-bool LSDatenbank::setMaxClients( int id, int maxC )
-{
-    Text *befehl = new Text( "UPDATE server SET max_tasks = " );
-    befehl->append( maxC );
-    befehl->append( " WHERE id = " );
-    befehl->append( id );
-    lock();
-    if( !datenbank->befehl( befehl->getText() ) )
-    {
-        unlock();
-        befehl->release();
-        return 0;
-    }
-    bool ret = datenbank->getZeilenAnzahl() > 0;
-    unlock();
-    befehl->release();
-    return ret;
-}
-
-bool LSDatenbank::serverIstNichtPausiert( int id )
-{
-    Text *befehl = new Text( "SELECT server_status_id FROM server WHERE id = " );
-    befehl->append( id );
-    lock();
-    if( !datenbank->befehl( befehl->getText() ) )
-    {
-        unlock();
-        befehl->release();
-        return 0;
-    }
-    Result res = datenbank->getResult();
-    unlock();
-    befehl->release();
-    if( !res.zeilenAnzahl )
-    {
-        res.destroy();
-        return 0;
-    }
-    bool ret = (int)res.values[ 0 ] == 3;
-    res.destroy();
-    return ret;
-}
-
-// constant
-Text *LSDatenbank::getLetzterFehler() const
-{
-    return datenbank->getLetzterFehler();
-}

+ 0 - 42
FactoryCraft/Datenbank.h

@@ -1,42 +0,0 @@
-#pragma once
-
-#include <sql.h>
-#include <Text.h>
-#include <InitDatei.h>
-
-using namespace Framework;
-using namespace sql;
-
-namespace Admin_Recht
-{
-    const int LSStarten = 12;
-    const int LSBeenden = 13;
-    const int LSPausieren = 14;
-    const int LSMCChange = 15;
-}
-
-class LSDatenbank : public virtual Framework::ReferenceCounter
-{
-private:
-    Datenbank *datenbank;
-    CRITICAL_SECTION cs;
-
-public:
-    // Konstruktor
-    LSDatenbank( InitDatei *zIni );
-    // Destruktor
-    ~LSDatenbank();
-    // nicht constant
-    void lock();
-    void unlock();
-    int istAdministrator( const char *name, const char *passwort );
-    bool adminHatRecht( int id, int recht );
-    bool proveKlient( int num, int sNum );
-    Text *getKlientKey( int cId );
-    void unregisterKlient( int num, int sNum );
-    bool setServerStatus( int id, int status );
-    bool setMaxClients( int id, int maxC );
-    bool serverIstNichtPausiert( int id );
-    // constant
-    Text *getLetzterFehler() const;
-};

+ 64 - 6
FactoryCraft/Dimension.cpp

@@ -8,29 +8,46 @@ using namespace Framework;
 
 Dimension::Dimension( int id )
     : dimensionId( id ),
-    chunks( new Trie<Chunk>() )
+    chunks( new Trie<Chunk>() ),
+    entities( new RCArray<Entity>() )
 {}
 
 Dimension::~Dimension()
 {
+    entities->release();
     chunks->release();
 }
 
-void Dimension::getAddrOf( Punkt cPos, char *addr )
+void Dimension::tickEntities( Game *zGame )
+{
+    int index = 0;
+    Array<int> removed;
+    for( auto entity = entities->getIterator(); entity; entity++, index++ )
+    {
+        if( zChunk( Punkt( entity->getPosition().x, entity->getPosition().y ) ) )
+            entity->tick( this, zGame );
+        if( entity->isRemoved() )
+            removed.add( index, 0 );
+    }
+    for( auto i = removed.getIterator(); i; i++ )
+        entities->remove( i );
+}
+
+void Dimension::getAddrOf( Punkt cPos, char *addr ) const
 {
     *(int *)addr = cPos.x;
     *( (int *)addr + 1 ) = cPos.y;
     addr[ 8 ] = 0;
 }
 
-void Dimension::getAddrOfWorld( Punkt wPos, char *addr )
+void Dimension::getAddrOfWorld( Punkt wPos, char *addr ) const
 {
     wPos.x = (int)floor( ( (float)wPos.x + CHUNK_SIZE / 2 ) / CHUNK_SIZE );
     wPos.y = (int)floor( ( (float)wPos.y + CHUNK_SIZE / 2 ) / CHUNK_SIZE );
     getAddrOf( wPos, addr );
 }
 
-Chunk *Dimension::zChunk( Punkt wPos )
+Chunk *Dimension::zChunk( Punkt wPos ) const
 {
     char addr[ 9 ];
     getAddrOfWorld( wPos, addr );
@@ -42,6 +59,11 @@ Block *Dimension::zBlock( Vec3<int> location )
     return zChunk( Punkt( location.x, location.y ) )->zBlockAt( Vec3<int>( ( location.x + CHUNK_SIZE / 2 ) % CHUNK_SIZE, ( location.y + CHUNK_SIZE / 2 ) % CHUNK_SIZE, location.z ) );
 }
 
+void Dimension::addEntity( Entity *entity )
+{
+    entities->add( entity );
+}
+
 void Dimension::addChunk( Chunk *chunk )
 {
     char addr[ 9 ];
@@ -82,14 +104,14 @@ void Dimension::addChunk( Chunk *chunk )
         chunk->release();
 }
 
-void Dimension::save( Framework::Writer *zWriter )
+void Dimension::save( Text worldDir ) const
 {
     for( auto chunk = chunks->getIterator(); chunk; chunk++ )
     {
         if( !chunk._ )
             continue;
         Datei *file = new Datei();
-        Text filePath = chunk->zGameObj()->getWorldDirectory() + "/dim/" + chunk->getDimensionId() + "/";
+        Text filePath = worldDir + "/dim/" + dimensionId + "/";
         filePath.appendHex( chunk->getCenter().x );
         filePath += "_";
         filePath.appendHex( chunk->getCenter().y );
@@ -100,4 +122,40 @@ void Dimension::save( Framework::Writer *zWriter )
         file->close();
         file->release();
     }
+    Text filePath = worldDir + "/dim/" + dimensionId + "/entities";
+    Datei *file = new Datei();
+    file->setDatei( filePath );
+    if( file->open( Datei::Style::schreiben ) )
+    {
+        for( auto entity = entities->getIterator(); entity; entity++ )
+        {
+            if( entity->zType()->getId() != PlayerEntityType::ID )
+            {
+                if( !entity->isRemoved() )
+                {
+                    int type = entity->zType()->getId();
+                    file->schreibe( (char *)&type, 4 );
+                    StaticRegistry<EntityType>::INSTANCE.zElement( type )->saveEntity( entity, file );
+                }
+            }
+            else
+            {
+                Datei pFile;
+                pFile.setDatei( worldDir + "/player/" + ( (Player *)entity.val() )->getName() );
+                if( pFile.open( Datei::Style::schreiben ) )
+                    PlayerEntityType::INSTANCE->saveEntity( entity, &pFile );
+            }
+        }
+        file->close();
+    }
+}
+
+int Dimension::getDimensionId() const
+{
+    return dimensionId;
+}
+
+bool Dimension::hasChunck( int x, int y ) const
+{
+    return zChunk( Punkt( x, y ) );
 }

+ 10 - 4
FactoryCraft/Dimension.h

@@ -9,15 +9,21 @@ class Dimension : public virtual Framework::ReferenceCounter
 private:
     int dimensionId;
     Framework::Trie<Chunk> *chunks;
-    void getAddrOf( Framework::Punkt cPos, char *addr );
-    void getAddrOfWorld( Framework::Punkt wPos, char *addr );
-    Chunk *zChunk( Framework::Punkt wPos );
+    Framework::RCArray<Entity> *entities;
+    void getAddrOf( Framework::Punkt cPos, char *addr ) const;
+    void getAddrOfWorld( Framework::Punkt wPos, char *addr ) const;
+    Chunk *zChunk( Framework::Punkt wPos ) const;
 
 public:
     Dimension( int id );
     ~Dimension();
 
+    void tickEntities( Game *zGame );
+
     Block *zBlock( Framework::Vec3<int> location );
+    void addEntity( Entity *entity );
     void addChunk( Chunk *chunk );
-    void save( Framework::Writer *zWriter );
+    void save( Framework::Text worldDir ) const;
+    int getDimensionId() const;
+    bool hasChunck( int x, int y ) const;
 };

+ 86 - 0
FactoryCraft/Entity.cpp

@@ -0,0 +1,86 @@
+#include "Entity.h"
+
+Entity::Entity( const EntityType *zType, Framework::Vec3<float> location, int dimensionId )
+    : Inventory( location ),
+    zEntityType( zType ),
+    currentDimensionId( dimensionId ),
+    removed( 0 )
+{}
+
+void Entity::onDeath()
+{}
+
+void Entity::tick( const Dimension *zDimension, Game *zGame )
+{
+    // TODO
+}
+
+void Entity::setPosition( Framework::Vec3<float> pos )
+{
+    location = pos;
+}
+
+float Entity::getMaxHP() const
+{
+    return maxHP;
+}
+
+float Entity::getCurrentHP() const
+{
+    return currentHP;
+}
+
+float Entity::getStamina() const
+{
+    return stamina;
+}
+
+float Entity::getMaxStamina() const
+{
+    return maxStamina;
+}
+
+float Entity::getHunger() const
+{
+    return hunger;
+}
+
+float Entity::getMaxHunger() const
+{
+    return maxHunger;
+}
+
+float Entity::getThirst() const
+{
+    return thirst;
+}
+
+float Entity::getMaxThirst() const
+{
+    return maxThirst;
+}
+
+Framework::Vec3<float> Entity::getSpeed() const
+{
+    return speed;
+}
+
+Framework::Vec3<float> Entity::getPosition() const
+{
+    return location;
+}
+
+int Entity::getCurrentDimensionId() const
+{
+    return currentDimensionId;
+}
+
+bool Entity::isRemoved() const
+{
+    return removed;
+}
+
+const EntityType *Entity::zType() const
+{
+    return zEntityType;
+}

+ 33 - 3
FactoryCraft/Entity.h

@@ -7,16 +7,46 @@
 #include "Inventory.h"
 
 class EntityType;
+class Dimension;
+class Game;
 
 class Entity : public Inventory
 {
-private:
+protected:
     float maxHP;
     float currentHP;
-    Framework::Vec3<float> position;
-    EntityType *zEntityType;
+    float stamina;
+    float maxStamina;
+    float hunger;
+    float maxHunger;
+    float thirst;
+    float maxThirst;
+    Framework::Vec3<float> speed;
+    const EntityType *zEntityType;
+    int currentDimensionId;
+    bool removed;
+
+    virtual void onDeath();
+    Entity( const EntityType *zType, Framework::Vec3<float> location, int dimensionId );
 
 public:
+    virtual void tick( const Dimension *zDimension, Game *zGame );
+
+    void setPosition( Framework::Vec3<float> pos );
+    float getMaxHP() const;
+    float getCurrentHP() const;
+    float getStamina() const;
+    float getMaxStamina() const;
+    float getHunger() const;
+    float getMaxHunger() const;
+    float getThirst() const;
+    float getMaxThirst() const;
+    Framework::Vec3<float> getSpeed() const;
+    Framework::Vec3<float> getPosition() const;
+    int getCurrentDimensionId() const;
+    bool isRemoved() const;
+
+    const EntityType *zType() const;
 
     friend Effect;
     friend EntityType;

+ 70 - 0
FactoryCraft/EntityType.cpp

@@ -0,0 +1,70 @@
+#include "EntityType.h"
+#include "Entity.h"
+
+EntityType::EntityType( int id )
+    : ReferenceCounter(),
+    id( id )
+{
+    StaticRegistry<EntityType>::INSTANCE.registerT( this, id );
+}
+
+void EntityType::loadSuperEntity( Entity *zEntity, Framework::StreamReader *zReader ) const
+{
+    zEntity->loadInventory( zReader );
+    zReader->lese( (char *)&zEntity->maxHP, 4 );
+    zReader->lese( (char *)&zEntity->currentHP, 4 );
+    zReader->lese( (char *)&zEntity->stamina, 4 );
+    zReader->lese( (char *)&zEntity->maxStamina, 4 );
+    zReader->lese( (char *)&zEntity->hunger, 4 );
+    zReader->lese( (char *)&zEntity->maxHunger, 4 );
+    zReader->lese( (char *)&zEntity->thirst, 4 );
+    zReader->lese( (char *)&zEntity->maxThirst, 4 );
+    zReader->lese( (char *)&zEntity->speed.x, 4 );
+    zReader->lese( (char *)&zEntity->speed.y, 4 );
+    zReader->lese( (char *)&zEntity->speed.z, 4 );
+    zReader->lese( (char *)&zEntity->currentDimensionId, 4 );
+}
+
+void EntityType::saveSuperEntity( Entity *zEntity, Framework::StreamWriter *zWriter ) const
+{
+    zEntity->saveInventory( zWriter );
+    zWriter->schreibe( (char *)&zEntity->maxHP, 4 );
+    zWriter->schreibe( (char *)&zEntity->currentHP, 4 );
+    zWriter->schreibe( (char *)&zEntity->stamina, 4 );
+    zWriter->schreibe( (char *)&zEntity->maxStamina, 4 );
+    zWriter->schreibe( (char *)&zEntity->hunger, 4 );
+    zWriter->schreibe( (char *)&zEntity->maxHunger, 4 );
+    zWriter->schreibe( (char *)&zEntity->thirst, 4 );
+    zWriter->schreibe( (char *)&zEntity->maxThirst, 4 );
+    zWriter->schreibe( (char *)&zEntity->speed.x, 4 );
+    zWriter->schreibe( (char *)&zEntity->speed.y, 4 );
+    zWriter->schreibe( (char *)&zEntity->speed.z, 4 );
+    zWriter->schreibe( (char *)&zEntity->currentDimensionId, 4 );
+}
+
+void EntityType::createSuperEntity( Entity *zEntity ) const
+{}
+
+Entity *EntityType::loadEntity( Game *zTarget, Framework::StreamReader *zReader ) const
+{
+    Entity *entity = createEntity( Framework::Vec3<float>( 0, 0, 0 ), 0, zTarget );
+    loadSuperEntity( entity, zReader );
+    return entity;
+}
+
+void EntityType::saveEntity( Entity *zEntity, Framework::StreamWriter *zWriter ) const
+{
+    saveSuperEntity( zEntity, zWriter );
+}
+
+Entity *EntityType::createEntityAt( Framework::Vec3<float> position, int dimensionId, Game *zTarget ) const
+{
+    Entity *entity = createEntity( position, dimensionId, zTarget );
+    createSuperEntity( entity );
+    return entity;
+}
+
+int EntityType::getId() const
+{
+    return id;
+}

+ 7 - 8
FactoryCraft/EntityType.h

@@ -18,16 +18,15 @@ private:
 protected:
     EntityType( int id );
 
-    virtual void loadSuperEntity( Entity *zEntity, Framework::Reader *zReader );
-    virtual void saveSuperEntity( Entity *zEntity, Framework::Writer *zWriter );
-    virtual void createSuperEntity( Entity *zEntity );
-    virtual void saveSuperEntity( Entity *zEntity );
-    virtual Entity *createEntity( Game *zTarget ) = 0;
+    virtual void loadSuperEntity( Entity *zEntity, Framework::StreamReader *zReader ) const;
+    virtual void saveSuperEntity( Entity *zEntity, Framework::StreamWriter *zWriter ) const;
+    virtual void createSuperEntity( Entity *zEntity ) const;
+    virtual Entity *createEntity( Framework::Vec3<float> position, int dimensionId, Game *zTarget ) const = 0;
 
 public:
-    virtual Entity *loadEntity( Framework::Vec3<float> position, Game *zTarget, Framework::Reader *zReader );
-    virtual void saveEntity( Entity *zEntity, Framework::Writer *zWriter );
-    virtual Entity *createEntityAt( Framework::Vec3<float> position, Game *zTarget );
+    virtual Entity *loadEntity( Game *zTarget, Framework::StreamReader *zReader ) const;
+    virtual void saveEntity( Entity *zEntity, Framework::StreamWriter *zWriter ) const;
+    virtual Entity *createEntityAt( Framework::Vec3<float> position, int dimensionId, Game *zTarget ) const;
 
     int getId() const;
 };

+ 8 - 14
FactoryCraft/FactoryCraft.vcxproj

@@ -80,7 +80,7 @@
     <OutDir>$(RemoteRootDir)/Server/$(ProjectName)/debug/</OutDir>
     <IntDir>$(RemoteRootDir)/Server/$(ProjectName)/debug/</IntDir>
     <RemoteProjectDir>$(RemoteRootDir)/Server/$(ProjectName)/debug</RemoteProjectDir>
-    <IncludePath>..\..\..\..\Allgemein\Framework;../../../Framework/debug;..\..\..\..\Allgemein\Network\Network;../../../Network/debug/Network;..\..\..\..\Allgemein\sql\sql;../../../sql/debug/sql;../../../KsgScript/debug/KsgScript;..\..\..\..\Allgemein\KSGScript\KSGScript\Include;$(IncludePath)</IncludePath>
+    <IncludePath>..\..\..\..\..\Allgemein\Framework;../../../Framework/debug;..\..\..\..\..\Allgemein\Network\Network;../../../Network/debug/Network;../../../KsgScript/debug/KsgScript;..\..\..\..\..\Allgemein\KSGScript\KSGScript\Include;$(IncludePath)</IncludePath>
     <RemoteTargetPath>$(RemoteProjectDir)/$(TargetName)$(TargetExt)</RemoteTargetPath>
     <RemoteLinkLocalCopyOutput>false</RemoteLinkLocalCopyOutput>
   </PropertyGroup>
@@ -88,11 +88,10 @@
     <OutDir>$(RemoteRootDir)/Server/$(ProjectName)/release/</OutDir>
     <IntDir>$(RemoteRootDir)/Server/$(ProjectName)/release/</IntDir>
     <RemoteProjectDir>$(RemoteRootDir)/Server/$(ProjectName)/release</RemoteProjectDir>
-    <IncludePath>..\..\..\..\Allgemein\Framework;../../../Framework/release;..\..\..\..\Allgemein\Network\Network;../../../Network/release/Network;..\..\..\..\Allgemein\sql\sql;../../../sql/release/sql;../../../KsgScript/release/KsgScript;..\..\..\..\Allgemein\KSGScript\KSGScript\Include;$(IncludePath)</IncludePath>
+    <IncludePath>..\..\..\..\..\Allgemein\Framework;../../../Framework/release;..\..\..\..\..\Allgemein\Network\Network;../../../Network/release/Network;../../../KsgScript/release/KsgScript;..\..\..\..\..\Allgemein\KSGScript\KSGScript\Include;$(IncludePath)</IncludePath>
     <RemoteTargetPath>$(RemoteProjectDir)/$(TargetName)$(TargetExt)</RemoteTargetPath>
   </PropertyGroup>
   <ItemGroup>
-    <ClInclude Include="AbstractEventListener.h" />
     <ClInclude Include="AddChunkUpdate.h" />
     <ClInclude Include="Area.h" />
     <ClInclude Include="BasicBlocks.h" />
@@ -100,21 +99,14 @@
     <ClInclude Include="BiomGenerator.h" />
     <ClInclude Include="BiomInterpolator.h" />
     <ClInclude Include="Block.h" />
-    <ClInclude Include="BlockDestroyedEvent.h" />
-    <ClInclude Include="BlockPlacedEvent.h" />
     <ClInclude Include="BlockType.h" />
     <ClInclude Include="Chunk.h" />
     <ClInclude Include="Constants.h" />
-    <ClInclude Include="Datenbank.h" />
     <ClInclude Include="DimensionGenerator.h" />
     <ClInclude Include="Effect.h" />
     <ClInclude Include="EffectFactory.h" />
     <ClInclude Include="Entity.h" />
     <ClInclude Include="EntityType.h" />
-    <ClInclude Include="Event.h" />
-    <ClInclude Include="EventListener.h" />
-    <ClInclude Include="DefaultEventListener.h" />
-    <ClInclude Include="EventThrower.h" />
     <ClInclude Include="Game.h" />
     <ClInclude Include="GrasslandBiom.h" />
     <ClInclude Include="Inventory.h" />
@@ -124,7 +116,6 @@
     <ClInclude Include="ItemSlot.h" />
     <ClInclude Include="ItemStack.h" />
     <ClInclude Include="ItemType.h" />
-    <ClInclude Include="LocationChangedEvent.h" />
     <ClInclude Include="Noise.h" />
     <ClInclude Include="OverworldDimension.h" />
     <ClInclude Include="PerlinNoise.h" />
@@ -148,9 +139,11 @@
     <ClCompile Include="Block.cpp" />
     <ClCompile Include="BlockType.cpp" />
     <ClCompile Include="Chunk.cpp" />
-    <ClCompile Include="Datenbank.cpp" />
     <ClCompile Include="Dimension.cpp" />
     <ClCompile Include="DimensionGenerator.cpp" />
+    <ClCompile Include="Entity.cpp" />
+    <ClCompile Include="EntityType.cpp" />
+    <ClCompile Include="Game.cpp" />
     <ClCompile Include="GrasslandBiom.cpp" />
     <ClCompile Include="Inventory.cpp" />
     <ClCompile Include="Item.cpp" />
@@ -162,6 +155,7 @@
     <ClCompile Include="Noise.cpp" />
     <ClCompile Include="OverworldDimension.cpp" />
     <ClCompile Include="PerlinNoise.cpp" />
+    <ClCompile Include="Player.cpp" />
     <ClCompile Include="Server.cpp" />
     <ClCompile Include="Start.cpp" />
     <ClCompile Include="StaticInitializerOrder.cpp" />
@@ -175,7 +169,7 @@
   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
     <Link>
       <AdditionalLibraryDirectories>$(RemoteRootDir)/sql/debug;$(RemoteRootDir)/Network/debug;$(RemoteRootDir)/Framework/debug;/usr/lib/;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
-      <LibraryDependencies>dbgFramework;dbgNetwork;dbgSQL;pq;pthread;ssl</LibraryDependencies>
+      <LibraryDependencies>dbgFramework;dbgNetwork;pthread;ssl</LibraryDependencies>
       <AdditionalOptions>-Wl,-rpath,../lib %(AdditionalOptions)</AdditionalOptions>
       <OutputFile>$(RemoteProjectDir)/$(TargetName)$(TargetExt)</OutputFile>
     </Link>
@@ -186,7 +180,7 @@
   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
     <Link>
       <AdditionalLibraryDirectories>$(RemoteRootDir)/sql/release;$(RemoteRootDir)/Network/release;$(RemoteRootDir)/Framework/release;/usr/lib/;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
-      <LibraryDependencies>Framework;Network;SQL;pq;pthread;ssl</LibraryDependencies>
+      <LibraryDependencies>Framework;Network;pthread;ssl</LibraryDependencies>
       <AdditionalOptions>-Wl,-rpath,../lib %(AdditionalOptions)</AdditionalOptions>
     </Link>
   </ItemDefinitionGroup>

+ 12 - 36
FactoryCraft/FactoryCraft.vcxproj.filters

@@ -1,12 +1,6 @@
 <?xml version="1.0" encoding="utf-8"?>
 <Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
   <ItemGroup>
-    <Filter Include="events">
-      <UniqueIdentifier>{f323a7f5-5758-46c2-b0fd-6cebe18074f1}</UniqueIdentifier>
-    </Filter>
-    <Filter Include="listeners">
-      <UniqueIdentifier>{36254dc9-eb64-40ed-a14a-dcbfaea372a7}</UniqueIdentifier>
-    </Filter>
     <Filter Include="world">
       <UniqueIdentifier>{75490044-5425-4526-abd2-44130408d418}</UniqueIdentifier>
     </Filter>
@@ -57,33 +51,12 @@
     </Filter>
   </ItemGroup>
   <ItemGroup>
-    <ClInclude Include="Event.h">
-      <Filter>events</Filter>
-    </ClInclude>
-    <ClInclude Include="LocationChangedEvent.h">
-      <Filter>events</Filter>
-    </ClInclude>
-    <ClInclude Include="BlockDestroyedEvent.h">
-      <Filter>events</Filter>
-    </ClInclude>
-    <ClInclude Include="EventListener.h">
-      <Filter>listeners</Filter>
-    </ClInclude>
-    <ClInclude Include="DefaultEventListener.h">
-      <Filter>listeners</Filter>
-    </ClInclude>
-    <ClInclude Include="AbstractEventListener.h">
-      <Filter>listeners</Filter>
-    </ClInclude>
     <ClInclude Include="Chunk.h">
       <Filter>world</Filter>
     </ClInclude>
     <ClInclude Include="Block.h">
       <Filter>world</Filter>
     </ClInclude>
-    <ClInclude Include="BlockPlacedEvent.h">
-      <Filter>events</Filter>
-    </ClInclude>
     <ClInclude Include="BlockType.h">
       <Filter>world</Filter>
     </ClInclude>
@@ -111,9 +84,6 @@
     <ClInclude Include="ItemSlot.h">
       <Filter>inventory</Filter>
     </ClInclude>
-    <ClInclude Include="EventThrower.h">
-      <Filter>events</Filter>
-    </ClInclude>
     <ClInclude Include="Effect.h">
       <Filter>effects</Filter>
     </ClInclude>
@@ -192,17 +162,11 @@
     <ClInclude Include="Server.h">
       <Filter>server</Filter>
     </ClInclude>
-    <ClInclude Include="Datenbank.h">
-      <Filter>server</Filter>
-    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="Server.cpp">
       <Filter>server</Filter>
     </ClCompile>
-    <ClCompile Include="Datenbank.cpp">
-      <Filter>server</Filter>
-    </ClCompile>
     <ClCompile Include="BlockType.cpp">
       <Filter>world</Filter>
     </ClCompile>
@@ -290,5 +254,17 @@
     <ClCompile Include="Area.cpp">
       <Filter>world</Filter>
     </ClCompile>
+    <ClCompile Include="Entity.cpp">
+      <Filter>entities</Filter>
+    </ClCompile>
+    <ClCompile Include="EntityType.cpp">
+      <Filter>entities</Filter>
+    </ClCompile>
+    <ClCompile Include="Player.cpp">
+      <Filter>entities</Filter>
+    </ClCompile>
+    <ClCompile Include="Game.cpp">
+      <Filter>game</Filter>
+    </ClCompile>
   </ItemGroup>
 </Project>

+ 239 - 0
FactoryCraft/Game.cpp

@@ -0,0 +1,239 @@
+#include "Game.h"
+#include "Zeit.h"
+#include "Player.h"
+#include "OverworldDimension.h"
+
+using namespace Framework;
+
+GameClient::GameClient( Player *zPlayer, FCKlient *client )
+    : ReferenceCounter(),
+    zPlayer( zPlayer ),
+    client( client ),
+    writer( client->zClient() ),
+    online( 1 )
+{}
+
+GameClient::~GameClient()
+{
+    client->release();
+}
+
+void GameClient::sendWorldUpdate( WorldUpdate *zUpdate )
+{
+    cs.Enter();
+    writer.schreibe( (char *)&Message::WORLD_UPDATE, 1 );
+    zUpdate->write( &writer );
+    cs.Leave();
+}
+
+void GameClient::reply( Game *zGame )
+{
+    cs.Enter();
+    for( auto req = requests.getIterator(); req; req++ )
+    {
+        // TODO
+    }
+    requests.leeren();
+    cs.Leave();
+}
+
+void GameClient::logout()
+{
+    online = 0;
+}
+
+void GameClient::addMessage( StreamReader *reader )
+{
+    short len = 0;
+    reader->lese( (char *)&len, 2 );
+    InMemoryBuffer *buffer = new InMemoryBuffer();
+    char *tmp = new char[ len ];
+    reader->lese( tmp, len );
+    buffer->schreibe( tmp, len );
+    delete[]tmp;
+    cs.Enter();
+    requests.add( buffer );
+    cs.Leave();
+}
+
+bool GameClient::isOnline() const
+{
+    return online;
+}
+
+Player *GameClient::zEntity() const
+{
+    return zPlayer;
+}
+
+
+Game::Game( Framework::Text name, Framework::Text worldsDir )
+    : Thread(),
+    name( name ),
+    dimensions( new RCArray<Dimension>() ),
+    updates( new RCArray<WorldUpdate>() ),
+    clients( new RCArray<GameClient>() ),
+    generator( 0 ),
+    loader( new WorldLoader( this ) ),
+    ticker( new TickOrganizer() ),
+    path( (const char *)( worldsDir + "/" + name ) ),
+    stop( 0 ),
+    tickId( 0 )
+{
+    if( !DateiExistiert( worldsDir + "/" + name ) )
+        DateiPfadErstellen( worldsDir + "/" + name + "/" );
+    int seed = 0;
+    int index = 0;
+    for( char *n = name; n; n++ )
+        seed += (int)pow( (float)*n * 31, ( float )++index );
+    generator = new WorldGenerator( seed, this );
+    start();
+}
+
+Game::~Game()
+{
+    dimensions->release();
+    updates->release();
+    clients->release();
+    generator->release();
+    loader->release();
+}
+
+void Game::thread()
+{
+    ZeitMesser m;
+    while( !stop )
+    {
+        m.messungStart();
+        ticker->nextTick();
+        int index = 0;
+        Array<int> removed;
+        cs.Enter();
+        for( auto player = clients->getIterator(); player; player++, index++ )
+        {
+            if( !player->isOnline() )
+            {
+                Datei pFile;
+                pFile.setDatei( path + "/player/" + player->zEntity()->getName() );
+                if( pFile.open( Datei::Style::schreiben ) )
+                    PlayerEntityType::INSTANCE->saveEntity( player->zEntity(), &pFile );
+                removed.add( player, 0 );
+            }
+        }
+        for( auto i = removed.getIterator(); i; i++ )
+            clients->remove( i );
+        cs.Leave();
+        for( auto dim = dimensions->getIterator(); dim; dim++ )
+            dim->tickEntities( this );
+        while( updates->z( 0 ) )
+        {
+            WorldUpdate *update = updates->z( 0 );
+            for( auto client = clients->getIterator(); client; client++ )
+                client->sendWorldUpdate( update );
+            if( !zDimension( update->getAffectedDimension() ) )
+                addDimension( new Dimension( update->getAffectedDimension() ) );
+            update->onUpdate( zDimension( update->getAffectedDimension() ) );
+            updates->remove( 0 );
+        }
+        for( auto client = clients->getIterator(); client; client++ )
+            client->reply( this );
+        m.messungEnde();
+        double sec = m.getSekunden();
+        if( sec < 0.05 )
+            Sleep( (int)( ( 0.05 - sec ) * 1000 ) );
+    }
+    save();
+}
+
+void Game::requestWorldUpdate( WorldUpdate *update )
+{
+    cs.Enter();
+    updates->add( update );
+    cs.Leave();
+}
+
+GameClient *Game::addPlayer( FCKlient *client, Framework::Text name )
+{
+    cs.Enter();
+    Datei pFile;
+    pFile.setDatei( path + "/player/" + name );
+    Player *player;
+    if( !pFile.existiert() || !pFile.open( Datei::Style::lesen ) )
+    {
+        player = (Player *)PlayerEntityType::INSTANCE->createEntityAt( Vec3<float>( 0, 0, 0 ), OverworldDimension::ID, this );
+    }
+    else
+    {
+        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() } );
+    while( !zDimension( OverworldDimension::ID ) )
+    {
+        cs.Leave();
+        Sleep( 1000 );
+        cs.Enter();
+    }
+    zDimension( OverworldDimension::ID )->addEntity( player );
+    GameClient *gameClient = new GameClient( player, client );
+    clients->add( gameClient );
+    cs.Leave();
+    return dynamic_cast<GameClient *>( gameClient->getThis() );
+}
+
+bool Game::doesChunkExist( int x, int y, int dimension ) const
+{
+    Dimension *dim = zDimension( dimension );
+    return ( dim && dim->hasChunck( x, y ) ) || loader->existsChunk( x, y, dimension );
+}
+
+Block *Game::zBlockAt( Framework::Vec3<int> location, int dimension ) const
+{
+    Dimension *dim = zDimension( dimension );
+    if( dim )
+        return dim->zBlock( location );
+    return 0;
+}
+
+Dimension *Game::zDimension( int id ) const
+{
+    for( auto dim = dimensions->getIterator(); dim; dim++ )
+    {
+        if( dim->getDimensionId() == id )
+            return dim;
+    }
+    return 0;
+}
+
+Framework::Punkt Game::getChunkCenter( int x, int y ) const
+{
+    return Punkt( (int)floor( ( (float)x + CHUNK_SIZE / 2 ) / CHUNK_SIZE ), (int)floor( ( (float)y + CHUNK_SIZE / 2 ) / CHUNK_SIZE ) );
+}
+
+Framework::Text Game::getWorldDirectory() const
+{
+    return path;
+}
+
+void Game::requestArea( Area area )
+{
+    generator->requestGeneration( area );
+    loader->requestLoading( area );
+}
+
+void Game::save() const
+{
+    for( auto dim = dimensions->getIterator(); dim; dim++ )
+        dim->save( path );
+}
+
+void Game::requestStop()
+{
+    stop = 1;
+    warteAufThread( 1000000 );
+}
+
+void Game::addDimension( Dimension *d )
+{
+    dimensions->add( d );
+}

+ 46 - 4
FactoryCraft/Game.h

@@ -10,27 +10,69 @@
 #include "Constants.h"
 #include "WorldUpdate.h"
 #include "WorldLoader.h"
+#include "TickOrganizer.h"
+#include "Server.h"
+#include "InMemoryBuffer.h"
+
+class FCKlient;
+
+class GameClient : public virtual Framework::ReferenceCounter
+{
+private:
+    Player *zPlayer;
+    FCKlient *client;
+    NetworkWriter writer;
+    CriticalSection cs;
+    RCArray<InMemoryBuffer> requests;
+    bool online;
+
+public:
+    GameClient( Player *zPlayer, FCKlient *client );
+    ~GameClient();
+
+    void sendWorldUpdate( WorldUpdate *zUpdate );
+    void reply( Game *zGame );
+    void logout();
+    void addMessage( StreamReader *reader );
+    bool isOnline() const;
+    Player *zEntity() const;
+
+private:
+    class Message
+    {
+    public:
+        static const unsigned char WORLD_UPDATE = 2;
+    };
+};
 
 class Game : public virtual Framework::Thread
 {
 private:
     Framework::Text name;
-    Framework::RCArray<Dimension> *dimension;
-    Framework::RCArray<Entity> *entities;
+    Framework::RCArray<Dimension> *dimensions;
     Framework::RCArray<WorldUpdate> *updates;
+    Framework::RCArray<GameClient> *clients;
     WorldGenerator *generator;
     WorldLoader *loader;
+    TickOrganizer *ticker;
+    Framework::Text path;
+    bool stop;
     __int64 tickId;
+    CriticalSection cs;
 
     void thread() override;
 public:
-    Game();
+    Game( Framework::Text name, Framework::Text worldsDir );
     ~Game();
     void requestWorldUpdate( WorldUpdate *update );
+    GameClient *addPlayer( FCKlient *client, Framework::Text name );
     bool doesChunkExist( int x, int y, int dimension ) const;
     Block *zBlockAt( Framework::Vec3<int> location, int dimension ) const;
+    Dimension *zDimension( int id ) const;
     Framework::Punkt getChunkCenter( int x, int y ) const;
     Framework::Text getWorldDirectory() const;
     void requestArea( Area area );
-    void save();
+    void save() const;
+    void requestStop();
+    void addDimension( Dimension *d );
 };

+ 37 - 0
FactoryCraft/Inventory.cpp

@@ -273,6 +273,43 @@ void Inventory::afterPullStack( ItemSlot *zSlot, Direction dir, const Item *zIte
 void Inventory::afterPushStack( ItemSlot *zSlot, Direction dir, const Item *zItem, int count )
 {}
 
+void Inventory::loadInventory( Framework::StreamReader *zReader )
+{
+    for( auto iterator = pushSlotsOrder->getIterator(); iterator; iterator++ )
+    {
+        int size = 0;
+        zReader->lese( (char *)&size, 4 );
+        if( size != 0 )
+        {
+            int id = 0;
+            zReader->lese( (char *)&id, 4 );
+            Item *item = StaticRegistry<ItemType>::INSTANCE.zElement( id )->loadItem( zReader );
+            iterator->addItems( new ItemStack( item, size ), NO_DIRECTION );
+        }
+    }
+}
+
+void Inventory::saveInventory( Framework::StreamWriter *zWriter )
+{
+    for( auto iterator = pushSlotsOrder->getIterator(); iterator; iterator++ )
+    {
+        const ItemStack *stack = iterator->zStack();
+        int value = 0;
+        if( !stack || !stack->zItem() )
+        {
+            zWriter->schreibe( (char *)&value, 4 );
+        }
+        else
+        {
+            value = stack->getSize();
+            zWriter->schreibe( (char *)&value, 4 );
+            value = stack->zItem()->zItemType()->getId();
+            zWriter->schreibe( (char *)&value, 4 );
+            stack->zItem()->zItemType()->saveItem( stack->zItem(), zWriter );
+        }
+    }
+}
+
 void Inventory::localTransaction( Array< ItemSlot * > *zSourceSlots, Array< ItemSlot * > *zTargetSlots, ItemFilter *zFilter, int count )
 {
     cs.Enter();

+ 2 - 0
FactoryCraft/Inventory.h

@@ -48,6 +48,8 @@ protected:
     virtual bool allowPushStack( ItemSlot *zSlot, Direction dir, const Item *zItem, int &count );
     virtual void afterPullStack( ItemSlot *zSlot, Direction dir, const Item *zItem, int count );
     virtual void afterPushStack( ItemSlot *zSlot, Direction dir, const Item *zItem, int count );
+    virtual void loadInventory( Framework::StreamReader *zReader );
+    virtual void saveInventory( Framework::StreamWriter *zWriter );
 
 public:
     Inventory( const Framework::Vec3<float> location );

+ 2 - 2
FactoryCraft/ItemSlot.h

@@ -8,8 +8,8 @@ class ItemSlot : public virtual Framework::ReferenceCounter
 private:
     ItemStack *items;
     int maxSize;
-    int allowedPullSide;
-    int allowedPushSides;
+    Directions allowedPullSide;
+    Directions allowedPushSides;
     int pullPriority;
     int pushPriority;
     bool allowHigherStackSize;

+ 4 - 4
FactoryCraft/ItemType.cpp

@@ -20,7 +20,7 @@ ItemType::~ItemType()
         levelUpRule->release();
 }
 
-void ItemType::loadSuperItem( Item *zItem, Framework::Reader *zReader ) const
+void ItemType::loadSuperItem( Item *zItem, Framework::StreamReader *zReader ) const
 {
     zReader->lese( (char *)&zItem->damage, 4 );
     zReader->lese( (char *)&zItem->maxDamage, 4 );
@@ -40,7 +40,7 @@ void ItemType::loadSuperItem( Item *zItem, Framework::Reader *zReader ) const
     zReader->lese( zItem->name, len );
 }
 
-void ItemType::saveSuperItem( Item *zItem, Framework::Writer *zWriter ) const
+void ItemType::saveSuperItem( const Item *zItem, Framework::StreamWriter *zWriter ) const
 {
     zWriter->schreibe( (char *)&zItem->damage, 4 );
     zWriter->schreibe( (char *)&zItem->maxDamage, 4 );
@@ -83,14 +83,14 @@ void ItemType::levelUpItemSkill( ItemSkill *zSkill ) const
         levelUpRule->applyOn( zSkill );
 }
 
-Item *ItemType::loadItem( Framework::Reader *zReader ) const
+Item *ItemType::loadItem( Framework::StreamReader *zReader ) const
 {
     Item *item = createItem();
     loadSuperItem( item, zReader );
     return item;
 }
 
-void ItemType::saveItem( Item *zItem, Framework::Writer *zWriter ) const
+void ItemType::saveItem( const Item *zItem, Framework::StreamWriter *zWriter ) const
 {
     saveSuperItem( zItem, zWriter );
 }

+ 4 - 4
FactoryCraft/ItemType.h

@@ -22,8 +22,8 @@ protected:
 
     ItemType( int id, ItemSkillLevelUpRule *levelUpRule, const ItemType *zBrokenType );
 
-    virtual void loadSuperItem( Item *zItem, Framework::Reader *zReader ) const;
-    virtual void saveSuperItem( Item *zItem, Framework::Writer *zWriter ) const;
+    virtual void loadSuperItem( Item *zItem, Framework::StreamReader *zReader ) const;
+    virtual void saveSuperItem( const Item *zItem, Framework::StreamWriter *zWriter ) const;
 
 public:
     ~ItemType();
@@ -34,7 +34,7 @@ public:
     virtual ItemStack *createItemStack( int size ) const;
     virtual ItemSkill *createDefaultItemSkill() const;
     virtual void levelUpItemSkill( ItemSkill *zSkill ) const;
-    virtual Item *loadItem( Framework::Reader *zReader ) const;
-    virtual void saveItem( Item *zItem, Framework::Writer *zWriter ) const;
+    virtual Item *loadItem( Framework::StreamReader *zReader ) const;
+    virtual void saveItem( const Item *zItem, Framework::StreamWriter *zWriter ) const;
     virtual Item *cloneItem( Item *zItem ) const;
 };

+ 30 - 0
FactoryCraft/Player.cpp

@@ -0,0 +1,30 @@
+#include "Player.h"
+
+Player::Player( Framework::Vec3<float> location, int dimensionId )
+    : Entity( PlayerEntityType::INSTANCE, location, dimensionId )
+{}
+
+void Player::setName( Framework::Text name )
+{
+    this->name = name;
+}
+
+const char *Player::getName() const
+{
+    return name;
+}
+
+PlayerEntityType::PlayerEntityType()
+    : EntityType( ID )
+{}
+
+void PlayerEntityType::loadSuperEntity( Entity *zEntity, Framework::StreamReader *zReader ) const
+{}
+
+void PlayerEntityType::saveSuperEntity( Entity *zEntity, Framework::StreamWriter *zWriter ) const
+{}
+
+Entity *PlayerEntityType::createEntity( Framework::Vec3<float> position, int dimensionId, Game *zTarget ) const
+{
+    return new Player( position, dimensionId );
+}

+ 9 - 1
FactoryCraft/Player.h

@@ -8,8 +8,12 @@ class PlayerEntityType;
 class Player : public Entity
 {
 private:
+    Framework::Text name;
 
 public:
+    Player( Framework::Vec3<float> location, int dimensionId );
+    void setName( Framework::Text name );
+    const char *getName() const;
 
     friend PlayerEntityType;
 };
@@ -18,10 +22,14 @@ class PlayerEntityType : public EntityType
 {
     REGISTRABLE( PlayerEntityType )
 
+protected:
+    virtual void loadSuperEntity( Entity *zEntity, Framework::StreamReader *zReader ) const override;
+    virtual void saveSuperEntity( Entity *zEntity, Framework::StreamWriter *zWriter ) const override;
+
 public:
     PlayerEntityType();
 
-    Entity *createEntity( Game *zTarget ) override;
+    virtual Entity *createEntity( Framework::Vec3<float> position, int dimensionId, Game *zTarget ) const override;
 };
 
 REGISTER( PlayerEntityType, EntityType )

+ 76 - 556
FactoryCraft/Server.cpp

@@ -2,86 +2,51 @@
 #include <iostream>
 #include <Klient.h>
 #include <Globals.h>
+#include <HttpRequest.h>
+#include <JSON.h>
 
 // Inhalt der LoginServer Klasse aus LoginServer.h
 // Konstruktor 
 FactoryCraftServer::FactoryCraftServer( InitDatei *zIni )
-    : Thread()
+    : ReferenceCounter()
 {
     Network::Start( 100 );
-    std::cout << "FC: Verbindung mit Datenbank wird hergestellt...\n";
-    db = new LSDatenbank( zIni );
     klientAnzahl = 0;
     klients = new RCArray< FCKlient >();
     empfangen = 0;
     gesendet = 0;
-    fehler = new Text();
     ini = dynamic_cast<InitDatei *>( zIni->getThis() );
     id = *zIni->zWert( "ServerId" );
-    server = new Server();
-    aServer = new SSLServer();
-    aServer->setPrivateKeyPassword( zIni->zWert( "SSLPasswort" )->getText() );
-    aServer->setCertificateFile( zIni->zWert( "SSLCert" )->getText() );
-    aServer->setPrivateKeyFile( zIni->zWert( "SSLKey" )->getText() );
-    std::cout << "FC: Starten des Admin Servers...\n";
-    if( !aServer->verbinde( (unsigned short)TextZuInt( ini->zWert( "AdminServerPort" )->getText(), 10 ), 10 ) )
-    {
-        std::cout << "FC: Der Admin Server konnte nicht gestartet werden. Das Programm wird beendet.\n";
-        exit( 1 );
-    }
-    db->setServerStatus( id, 2 );
-    end = 0;
-    nichtPausiert = 0;
+    server = new SSLServer();
+    server->setPrivateKeyPassword( zIni->zWert( "SSLPasswort" )->getText() );
+    server->setCertificateFile( zIni->zWert( "SSLCert" )->getText() );
+    server->setPrivateKeyFile( zIni->zWert( "SSLKey" )->getText() );
+    game = new Game( zIni->zWert( "World" )->getText(), zIni->zWert( "SaveDir" )->getText() );
     InitializeCriticalSection( &cs );
-    if( zIni->zWert( "Aktiv" )->istGleich( "TRUE" ) )
-    {
-        serverStarten();
-        serverFortsetzen();
-    }
 }
 
 // Destruktor 
 FactoryCraftServer::~FactoryCraftServer()
 {
-    fehler->release();
     server->trenne();
     server->release();
-    aServer->trenne();
-    aServer->release();
     if( klients )
         klients->release();
     ini->release();
-    db->release();
+    game->requestStop();
+    game->release();
     DeleteCriticalSection( &cs );
 }
 
 // nicht constant 
-void FactoryCraftServer::runn()
-{
-    while( !end && aServer->isConnected() )
-    {
-        SSLSKlient *klient;
-        klient = aServer->getKlient();
-        if( end && klient )
-        {
-            klient->trenne();
-            klient = (SSLSKlient *)klient->release();
-            Sleep( 1000 );
-            return;
-        }
-        if( !klient )
-            continue;
-        FCAKlient *clHandle = new FCAKlient( klient, dynamic_cast<FactoryCraftServer *>( getThis() ) );
-        clHandle->start();
-    }
-}
-
-void FactoryCraftServer::thread()
+void FactoryCraftServer::run()
 {
+    if( server )
+        server->release();
+    server->verbinde( (unsigned short)TextZuInt( ini->zWert( "SSLPort" )->getText(), 10 ), 10 );
     while( server->isConnected() )
     {
-        SKlient *klient;
-        klient = server->getKlient();
+        SSLSKlient *klient = server->getKlient();
         if( !klient )
             continue;
         Framework::getThreadRegister()->cleanUpClosedThreads();
@@ -96,121 +61,22 @@ void FactoryCraftServer::thread()
 
 void FactoryCraftServer::close()
 {
-    db->setServerStatus( id, 1 );
     server->trenne();
-#ifdef WIN32
-    warteAufThread( 1000 );
-#endif
     EnterCriticalSection( &cs );
     for( int i = 0; i < klientAnzahl; i++ )
         klients->z( i )->absturz();
     klients = ( RCArray< FCKlient > * )klients->release();
     klientAnzahl = 0;
     LeaveCriticalSection( &cs );
-    ende();
-    run = 0;
-    end = 1;
-    Klient *klient = new Klient();
-    klient->verbinde( aServer->getPort(), "127.0.0.1" );
-    Sleep( 500 );
-    aServer->trenne();
-    klient->release();
 }
 
-bool FactoryCraftServer::serverStarten()
-{
-    if( nichtPausiert )
-    {
-        fehler->setText( "Der Server konnte nicht gestartet werden: Der Server läuft bereits." );
-        return 0;
-    }
-    if( server )
-        server->release();
-    server = new Server();
-    if( server->verbinde( (unsigned short)TextZuInt( ini->zWert( "ServerPort" )->getText(), 10 ), 10 ) )
-    {
-        nichtPausiert = 1;
-        start();
-        return 1;
-    }
-    else
-    {
-        serverBeenden();
-        fehler->setText( "Der Server konnte nicht gestartet werden: Eventuell ist der Port in benutzung." );
-        return 0;
-    }
-}
-
-bool FactoryCraftServer::serverPause()
-{
-    if( !nichtPausiert )
-    {
-        fehler->setText( "Der Server konnte nicht pausiert werden: Der Server läuft nicht." );
-        return 0;
-    }
-    if( !db->setServerStatus( id, 2 ) )
-    {
-        fehler->setText( "Der Server konnte nicht pausiert werden: " );
-        fehler->append( db->getLetzterFehler() );
-        return 0;
-    }
-    return 1;
-}
-
-bool FactoryCraftServer::serverFortsetzen()
-{
-    if( !nichtPausiert )
-    {
-        fehler->setText( "Der Server konnte nicht fortgesetzt werden: Der Server läuft nicht." );
-        return 0;
-    }
-    if( !db->setServerStatus( id, 3 ) )
-    {
-        fehler->setText( "Der Server konnte nicht fortgesetzt werden: " );
-        fehler->append( db->getLetzterFehler() );
-        return 0;
-    }
-    return 1;
-}
-
-bool FactoryCraftServer::serverBeenden()
-{
-    if( !nichtPausiert )
-    {
-        fehler->setText( "Der Server konnte nicht beendet werden: Der Server läuft nicht." );
-        return 0;
-    }
-    if( db->serverIstNichtPausiert( id ) )
-    {
-        fehler->setText( "Der Server konnte nicht beendet werden: Der Server muss erst pausiert werden." );
-        return 0;
-    }
-    nichtPausiert = 0;
-    ende();
-    if( server )
-        server->trenne();
-    return 1;
-}
-
-bool FactoryCraftServer::setMaxKlients( int mc )
-{
-    if( !db->setMaxClients( id, mc ) )
-    {
-        fehler->setText( "Die maximale Anzahl der Clients konnte nicht gesetzt werden:\n" );
-        fehler->append( db->getLetzterFehler() );
-        return 0;
-    }
-    ini->setWert( "MaxClients", Text() += mc );
-    return 1;
-}
-
-bool FactoryCraftServer::absturzKlient( int klientId )
+bool FactoryCraftServer::absturzKlient( int accountId )
 {
     bool gefunden = 0;
     EnterCriticalSection( &cs );
     for( int i = 0; i < klientAnzahl; i++ )
     {
-        if( klients->z( i ) && klients->z( i )->getKlientNummer() == klientId )
+        if( klients->z( i ) && klients->z( i )->getAccountId() == accountId )
         {
             klients->z( i )->absturz();
             klients->remove( i );
@@ -251,346 +117,32 @@ void FactoryCraftServer::addEmpfangen( int bytes )
     empfangen += bytes;
 }
 
-// constant
-bool FactoryCraftServer::istAn() const
-{
-    return db->serverIstNichtPausiert( id );
-}
-
-Server *FactoryCraftServer::zServer() const
-{
-    return server;
-}
-
-LSDatenbank *FactoryCraftServer::zDB() const
-{
-    return db;
-}
-
 bool FactoryCraftServer::hatClients() const
 {
     return klientAnzahl > 0;
 }
 
-int FactoryCraftServer::getId() const
-{
-    return id;
-}
-
-char *FactoryCraftServer::getLetzterFehler() const
-{
-    return fehler->getText();
-}
-
-
-// Inhalt der LSAKlient Klasse aus LoginServer.h
-// Konstruktor 
-FCAKlient::FCAKlient( SSLSKlient *klient, FactoryCraftServer *ls )
-    : Thread()
-{
-    this->klient = klient;
-    name = new Text( "" );
-    passwort = new Text( "" );
-    adminId = 0;
-    version = 0;
-    this->ls = ls;
-}
-
-// Destruktor 
-FCAKlient::~FCAKlient()
-{
-    klient->trenne();
-    klient->release();
-    ls->release();
-    name->release();
-    passwort->release();
-}
-
-// nicht constant 
-void FCAKlient::thread()
-{
-    while( 1 )
-    {
-        char c = 0;
-        if( !klient->getNachricht( &c, 1 ) )
-            break;
-        else
-        {
-            bool br = 0;
-            switch( c )
-            {
-            case 1: // Login
-                if( 1 )
-                {
-                    klient->sende( "\1", 1 );
-                    unsigned char nLen = 0;
-                    klient->getNachricht( (char *)&nLen, 1 );
-                    char *n = new char[ nLen + 1 ];
-                    n[ (int)nLen ] = 0;
-                    if( nLen )
-                        klient->getNachricht( n, nLen );
-                    unsigned char pLen = 0;
-                    klient->getNachricht( (char *)&pLen, 1 );
-                    char *p = new char[ pLen + 1 ];
-                    p[ (int)pLen ] = 0;
-                    if( pLen )
-                        klient->getNachricht( p, pLen );
-                    int adminId = ls->zDB()->istAdministrator( n, p );
-                    if( adminId )
-                    {
-                        klient->sende( "\1", 1 );
-                        name->setText( n );
-                        passwort->setText( p );
-                        this->adminId = adminId;
-                    }
-                    else
-                        errorZuKlient( "Falsche Kombination aus Name und Passwort." );
-                    delete[] n;
-                    delete[] p;
-                }
-                break;
-            case 2: // Logout
-                adminId = 0;
-                name->setText( "" );
-                passwort->setText( "" );
-                klient->sende( "\1", 1 );
-                break;
-            case 3: // Trennen
-                br = 1;
-                klient->sende( "\1", 1 );
-                break;
-            case 4: // Server starten
-                if( !adminId )
-                    errorZuKlient( "Du musst dich einloggen." );
-                else
-                {
-                    if( ls->zDB()->adminHatRecht( adminId, Admin_Recht::LSStarten ) )
-                    {
-                        if( !ls->serverStarten() )
-                        {
-                            Text *err = new Text();
-                            err->append( ls->getLetzterFehler() );
-                            errorZuKlient( err->getText() );
-                            err->release();
-                        }
-                        else
-                            klient->sende( "\1", 1 );
-                    }
-                    else
-                        errorZuKlient( "Du bist nicht berechtigt den Server zu starten." );
-                }
-                break;
-            case 5: // Server beenden
-                if( !adminId )
-                    errorZuKlient( "Du musst dich einloggen." );
-                else
-                {
-                    if( ls->zDB()->adminHatRecht( adminId, Admin_Recht::LSBeenden ) )
-                    {
-                        if( ls->serverBeenden() )
-                            klient->sende( "\1", 1 );
-                        else
-                        {
-                            Text *err = new Text();
-                            err->append( ls->getLetzterFehler() );
-                            errorZuKlient( err->getText() );
-                            err->release();
-                        }
-                    }
-                    else
-                        errorZuKlient( "Du bist nicht berechtigt den Server zu beenden." );
-                }
-                break;
-            case 6: // Programm Schließen
-                if( !adminId )
-                    errorZuKlient( "Du musst dich einloggen." );
-                else
-                {
-                    bool ok = 0;
-                    if( ls->isRunning() )
-                    {
-                        if( ls->zDB()->adminHatRecht( adminId, Admin_Recht::LSBeenden ) )
-                        {
-                            if( ls->serverBeenden() )
-                                ok = 1;
-                            else
-                            {
-                                Text *err = new Text();
-                                err->append( ls->getLetzterFehler() );
-                                errorZuKlient( err->getText() );
-                                err->release();
-                            }
-                        }
-                        else
-                            errorZuKlient( "Du bist nicht berechtigt den Server zu beenden." );
-                    }
-                    else
-                        ok = 1;
-                    if( ok && ls->hatClients() )
-                    {
-                        errorZuKlient( "Es sind noch Klients Online. Bitte versuche es später erneut." );
-                        break;
-                    }
-                    if( ok )
-                    {
-                        klient->sende( "\1", 1 );
-                        std::cout << "LS: Der Server wird von Benutzer " << adminId << " heruntergefahren.\n";
-                        ls->close();
-                        br = 1;
-                    }
-                }
-                break;
-            case 7: // Progtamm abstürzen
-                if( !adminId )
-                    errorZuKlient( "Du musst dich einloggen." );
-                else
-                {
-                    bool ok = 0;
-                    if( ls->isRunning() )
-                    {
-                        if( ls->zDB()->adminHatRecht( adminId, Admin_Recht::LSBeenden ) )
-                        {
-                            ls->serverBeenden();
-                            ok = 1;
-                        }
-                        else
-                            errorZuKlient( "Du bist nicht berechtigt den Server zu beenden." );
-                    }
-                    else
-                        ok = 1;
-                    if( ok )
-                    {
-                        klient->sende( "\1", 1 );
-                        std::cout << "LS: Der Server wurde von Benutzer " << adminId << " terminiert.\n";
-                        ls->close();
-                        br = 1;
-                    }
-                }
-                break;
-            case 8: // Status Frage
-                if( 1 )
-                {
-                    char status = 0;
-                    if( ls->isRunning() )
-                    {
-                        status = 1;
-                        if( ls->istAn() )
-                            status = 2;
-                    }
-                    klient->sende( "\1", 1 );
-                    klient->sende( &status, 1 );
-                }
-                break;
-            case 9: // Server pausieren
-                if( !adminId )
-                    errorZuKlient( "Du musst dich einloggen." );
-                else
-                {
-                    klient->sende( "\1", 1 );
-                    char pause = 0;
-                    klient->getNachricht( &pause, 1 );
-                    if( ls->zDB()->adminHatRecht( adminId, Admin_Recht::LSPausieren ) )
-                    {
-                        bool ok = 0;
-                        if( pause )
-                            ok = ls->serverPause();
-                        else
-                            ok = ls->serverFortsetzen();
-                        if( ok )
-                            klient->sende( "\1", 1 );
-                        else
-                        {
-                            Text *err = new Text();
-                            err->append( ls->getLetzterFehler() );
-                            errorZuKlient( err->getText() );
-                            err->release();
-                        }
-                    }
-                    else
-                    {
-                        if( pause )
-                            errorZuKlient( "Du bist nicht berechtigt den Server zu pausieren." );
-                        else
-                            errorZuKlient( "Du bist nicht berechtigt den Server fortzusetzen." );
-                    }
-                }
-                break;
-            case 0xA: // maximale Anzahl der Clients setzen
-                if( !adminId )
-                    errorZuKlient( "Du musst dich einloggen." );
-                else
-                {
-                    klient->sende( "\1", 1 );
-                    int maxC = 0;
-                    klient->getNachricht( (char *)&maxC, 4 );
-                    if( ls->zDB()->adminHatRecht( adminId, Admin_Recht::LSMCChange ) )
-                    {
-                        if( ls->setMaxKlients( maxC ) )
-                            klient->sende( "\1", 1 );
-                        else
-                        {
-                            Text *err = new Text();
-                            err->append( ls->getLetzterFehler() );
-                            errorZuKlient( err->getText() );
-                            err->release();
-                        }
-                    }
-                    else
-                        errorZuKlient( "Du bist nicht berechtigt die maximale Anzahl der Clients zu verändern." );
-                }
-                break;
-            case 0xC: // klient absturtz
-                if( 1 )
-                {
-                    klient->sende( "\1", 1 );
-                    int klientId = 0;
-                    klient->getNachricht( (char *)&klientId, 4 );
-                    if( klientId && ls->absturzKlient( klientId ) )
-                        klient->sende( "\1", 1 );
-                    else
-                        klient->sende( "\0", 1 );
-                }
-                break;
-            default:
-                errorZuKlient( "Unbekannte Nachricht!" );
-                break;
-            }
-            if( br )
-                break;
-            ls->addEmpfangen( klient->getDownloadBytes( 1 ) );
-            ls->addGesendet( klient->getUploadBytes( 1 ) );
-        }
-    }
-    ls->addEmpfangen( klient->getDownloadBytes( 1 ) );
-    ls->addGesendet( klient->getUploadBytes( 1 ) );
-    delete this;
-}
-
-void FCAKlient::errorZuKlient( const char *nachricht ) const // sendet eine Fehlernachricht zum Klient
-{
-    klient->sende( "\3", 1 );
-    char len = (char)textLength( nachricht );
-    klient->sende( &len, 1 );
-    klient->sende( nachricht, len );
-}
-
 
 // Inhalt der LSKlient aus LoginServer.h
 // Konstruktor
-FCKlient::FCKlient( SKlient *klient, FactoryCraftServer *ls )
+FCKlient::FCKlient( SSLSKlient *klient, FactoryCraftServer *ls )
     : Thread()
 {
     this->klient = klient;
-    unsigned char key[ 20 ] = { 143, 166, 245, 235, 76, 75, 116, 80, 26, 178, 142, 176, 109, 53, 106, 222, 223, 55, 139, 111 };
-    klient->setSendeKey( (char *)key, 20 );
-    klient->setEmpfangKey( (char *)key, 20 );
-    klientNummer = 0;
+    accountId = 0;
     this->ls = ls;
+    reader = new NetworkReader( klient );
 }
 
 // Destruktor 
 FCKlient::~FCKlient()
 {
+    if( zGameClient )
+    {
+        zGameClient->logout();
+        zGameClient = (GameClient *)zGameClient->release();
+    }
+    delete reader;
     klient->release();
     ls->release();
 }
@@ -600,7 +152,6 @@ void FCKlient::absturz()
 {
     ende();
     klient->trenne();
-    ls->zDB()->unregisterKlient( klientNummer, ls->getId() );
 }
 
 void FCKlient::thread()
@@ -608,7 +159,7 @@ void FCKlient::thread()
     while( 1 )
     {
         char c = 0;
-        if( !klient->getNachrichtEncrypted( &c, 1 ) )
+        if( !klient->getNachricht( &c, 1 ) )
             break;
         else
         {
@@ -616,76 +167,63 @@ void FCKlient::thread()
             switch( c )
             {
             case 1: // Klient identifikation
-                klient->getNachrichtEncrypted( (char *)&klientNummer, 4 );
-                if( !ls->zDB()->proveKlient( klientNummer, ls->getId() ) )
-                {
-                    klientNummer = 0;
-                    errorZuKlient( "Du bist nicht für diesen Server eingetragen" );
-                }
-                else
-                {
-                    Text *key = ls->zDB()->getKlientKey( klientNummer );
-                    if( !key )
-                        errorZuKlient( "Es konnte kein Schlüssel ermittelt werden." );
-                    else
-                    {
-                        klient->sendeEncrypted( "\1", 1 );
-                        klient->setEmpfangKey( *key, key->getLength() );
-                        klient->setSendeKey( *key, key->getLength() );
-                        key->release();
-                    }
-                }
-                break;
-            case 2: // Main / Erhaltung Server message
-                if( 1 )
+            {
+                int accountId = 0;
+                klient->getNachricht( (char *)&accountId, 4 );
+                unsigned char secretLength = 0;
+                klient->getNachricht( (char *)&secretLength, 1 );
+                char *secret = new char[ secretLength + 1 ];
+                klient->getNachricht( secret, (int)secretLength );
+                secret[ secretLength ] = 0;
+                Text data = "{\"account_id\":";
+                data += accountId;
+                data += ", \"secret\": \"";
+                data += secret;
+                data += "\"}";
+                bool ok = false;
+                HTTP::Answer *answer = HTTP::PostRequest( "/game_client/api/verify_client.php", "koljastrohm-games.com", data, "application/json", 443, true ).execute();
+                if( answer->getStatusCode() == 200 )
                 {
-                    char befehl = 0;
-                    klient->getNachrichtEncrypted( &befehl, 1 );
-                    switch( befehl )
+                    JSON::JSONObject obj( answer->getData() );
+                    if( obj.hasValue( "verified" ) )
                     {
-                    case 2: // klient absturtz
-                        if( 1 )
+                        JSON::JSONValue *value = obj.getValue( "verified" );
+                        if( value->getType() == JSON::BOOLEAN )
                         {
-                            int klientId = 0;
-                            klient->getNachrichtEncrypted( (char *)&klientId, 4 );
-                            if( klientId && ls->absturzKlient( klientId ) )
-                                klient->sendeEncrypted( "\1", 1 );
-                            else
-                                klient->sendeEncrypted( "\0", 1 );
+                            if( ( (JSON::JSONBool *)value )->getBool() )
+                            {
+                                this->accountId = accountId;
+                                if( zGameClient )
+                                {
+                                    zGameClient->logout();
+                                    zGameClient = (GameClient *)zGameClient->release();
+                                }
+                                zGameClient = ls->zGame()->addPlayer( dynamic_cast<FCKlient *>( getThis() ), Text( accountId ) );
+                                klient->sende( "\1", 1 );
+                                ok = true;
+                            }
                         }
-                        break;
-                    default:
-                        errorZuKlient( "Befehl nicht bekannt!" );
-                        break;
+                        value->release();
                     }
                 }
+                answer->release();
+                delete[]secret;
+                if( !ok )
+                    klient->sende( "\0", 1 );
                 break;
-            case 3: // Verbindungsende
+            }
+            case 2: // Verbindungsende
                 br = 1;
-                klient->sendeEncrypted( "\1", 1 );
-                break;
-            case 4: // unregister Klient
-                if( !klientNummer )
+                if( zGameClient )
                 {
-                    errorZuKlient( "Du bist nicht Identifiziert." );
-                    break;
-                }
-                ls->zDB()->unregisterKlient( klientNummer, ls->getId() );
-                klient->sendeEncrypted( "\1", 1 );
-                break;
-            case 0x7: // ping
-                if( 1 )
-                {
-                    if( !klientNummer )
-                    {
-                        errorZuKlient( "Du bist nicht Identifiziert." );
-                        break;
-                    }
-                    klient->sendeEncrypted( "\1", 1 );
+                    zGameClient->logout();
+                    zGameClient = (GameClient *)zGameClient->release();
                 }
+                klient->sende( "\1", 1 );
                 break;
             default:
-                errorZuKlient( "Unbekannte Nachricht!" );
+                if( zGameClient )
+                    zGameClient->addMessage( reader );
                 break;
             }
             if( br )
@@ -699,30 +237,12 @@ void FCKlient::thread()
     ls->removeKlient( this ); // delete this
 }
 
-// constant
-void FCKlient::errorZuKlient( const char *nachricht ) const // sendet eine Fehlernachricht zum Klient
+int FCKlient::getAccountId() const // gibt die KlientId zurück
 {
-    klient->sendeEncrypted( "\3", 1 );
-    char len = (char)textLength( nachricht );
-    klient->sendeEncrypted( &len, 1 );
-    klient->sendeEncrypted( nachricht, len );
+    return accountId;
 }
 
-int FCKlient::getKlientNummer() const // gibt die KlientId zurück
+SSLSKlient *FCKlient::zClient() const
 {
-    return klientNummer;
+    return klient;
 }
-
-// Inhalt der MSGWeiterleitung Klasse aus LoginServer.h
-// Konstruktor
-MSGWeiterleitung::MSGWeiterleitung( FactoryCraftServer *ls )
-    : ReferenceCounter()
-{
-    this->ls = ls;
-}
-
-// Destruktor
-MSGWeiterleitung::~MSGWeiterleitung()
-{
-    ls->release();
-}

+ 16 - 59
FactoryCraft/Server.h

@@ -5,29 +5,27 @@
 #include <Datei.h>
 #include <Text.h>
 #include <InitDatei.h>
-#include "Datenbank.h"
+
+#include "Game.h"
 
 using namespace Framework;
 using namespace Network;
 
 class FCKlient;
+class GameClient;
 
-class FactoryCraftServer : public Thread
+class FactoryCraftServer : virtual public ReferenceCounter
 {
 private:
-    Server *server;
-    SSLServer *aServer;
+    SSLServer *server;
     InitDatei *ini;
-    LSDatenbank *db;
     CRITICAL_SECTION cs;
     RCArray< FCKlient > *klients;
-    Text *fehler;
+    Game *game;
     int klientAnzahl;
     int id;
-    bool nichtPausiert;
     int empfangen;
     int gesendet;
-    bool end;
 
 public:
     // Konstruktor 
@@ -35,75 +33,34 @@ public:
     // Destruktor 
     virtual ~FactoryCraftServer();
     // nicht constant
-    void runn();
-    void thread();
+    void run();
     void close();
-    bool serverStarten();
-    bool serverPause();
-    bool serverFortsetzen();
-    bool serverBeenden();
-    bool setMaxKlients( int mc );
-    bool absturzKlient( int klientId );
+    bool absturzKlient( int accountId );
     bool removeKlient( FCKlient *zKlient );
     void addGesendet( int bytes );
     void addEmpfangen( int bytes );
-    // conatant 
-    bool istAn() const;
-    Server *zServer() const;
-    LSDatenbank *zDB() const;
     bool hatClients() const;
-    int getId() const;
-    char *getLetzterFehler() const;
-};
-
-class FCAKlient : public Thread
-{
-private:
-    SSLSKlient *klient;
-    Text *name;
-    Text *passwort;
-    int adminId;
-    FactoryCraftServer *ls;
-    int version;
-
-public:
-    // Konstruktor 
-    FCAKlient( SSLSKlient *klient, FactoryCraftServer *ls );
-    // Destruktor 
-    virtual ~FCAKlient();
-    // nicht constant
-    void thread();
-    void errorZuKlient( const char *nachricht ) const; // sendet eine Fehlernachricht zum AKlient
+    Game *zGame() const;
 };
 
 class FCKlient : public Thread
 {
 private:
-    SKlient *klient;
-    unsigned int klientNummer;
+    SSLSKlient *klient;
+    unsigned int accountId;
     FactoryCraftServer *ls;
+    GameClient *zGameClient;
+    NetworkReader *reader;
 
 public:
     // Konstruktor 
-    FCKlient( SKlient *klient, FactoryCraftServer *ls );
+    FCKlient( SSLSKlient *klient, FactoryCraftServer *ls );
     // Destruktor 
     virtual ~FCKlient();
     // nicht constant 
     void absturz();
     void thread();
     // constant
-    void errorZuKlient( const char *nachricht ) const; // sendet eine Fehlernachricht zum Klient
-    int getKlientNummer() const;
-};
-
-class MSGWeiterleitung : public virtual ReferenceCounter
-{
-private:
-    FactoryCraftServer *ls;
-
-public:
-    // Konstruktor
-    MSGWeiterleitung( FactoryCraftServer *ls );
-    // Destruktor
-    ~MSGWeiterleitung();
+    int getAccountId() const;
+    SSLSKlient *zClient() const;
 };

+ 10 - 13
FactoryCraft/Start.cpp

@@ -17,7 +17,7 @@ int main()
 
     Framework::initFramework();
     Zeit *z = getZeit();
-    Text *pfad = new Text( "../log/main/" );
+    Text *pfad = new Text( "log/" );
     pfad->append( z->getZeit( "y-m-d h-i-s.log" ) );
     z->release();
     DateiPfadErstellen( pfad->getText() );
@@ -27,22 +27,22 @@ int main()
     std::cout.rdbuf( file.rdbuf() );
     pfad->release();
 
-    std::cout << "MS: Startet...\n";
-    std::cout << "MS: Lese init Datei ../data/msInit.ini ...\n";
+    std::cout << "Startet...\n";
+    std::cout << "Lese init Datei fcInit.ini ...\n";
 
-    InitDatei *dat = new InitDatei( "../data/msInit.ini" );
+    InitDatei *dat = new InitDatei( "fcInit.ini" );
     if( !dat->laden() )
     {
-        std::cout << "MS: error: Datei konnte nicht gelesen werden. Das Programm wird geschlossen.\n";
+        std::cout << "error: Datei konnte nicht gelesen werden. Das Programm wird geschlossen.\n";
         dat->release();
         exit( 1 );
     }
-    const char *wichtig[] = { "ServerId", "DBBenutzer", "DBPasswort", "DBName", "DBIP", "DBPort", "Aktiv", "SSLPort", "SSLCert", "SSLKey", "SSLPasswort" };
+    const char *wichtig[] = { "SSLPort", "SSLCert", "SSLKey", "SSLPasswort" };
     for( const char *w : wichtig )
     {
         if( !dat->wertExistiert( w ) )
         {
-            std::cout << "MS: error: Der Wert '" << w << "' wurde nicht gefunden. Das Programm wird geschlossen.\n";
+            std::cout << "error: Der Wert '" << w << "' wurde nicht gefunden. Das Programm wird geschlossen.\n";
             dat->release();
             exit( 1 );
         }
@@ -50,15 +50,12 @@ int main()
 
     FactoryCraftServer *mserver = new FactoryCraftServer( dat );
 
-    std::cout << "MS: Der Admin Server läuft. Startforgang beendet.\n";
-    mserver->runn();
-    SSLKlient exitClient;
-    exitClient.verbinde( (unsigned short)(int)*dat->zWert( "SSLPort" ), "127.0.0.1" );
+    std::cout << "Der Server läuft. Startforgang beendet.\n";
+    mserver->run();
 
-    mserver->ende();
     mserver->release();
     dat->release();
-    std::cout << "MS: Der Server ist heruntergefahren.\n";
+    std::cout << "Der Server ist heruntergefahren.\n";
     file.close();
     std::cout.rdbuf( sbuf );
     Framework::releaseFramework();

+ 2 - 0
FactoryCraft/StaticInitializerOrder.cpp

@@ -6,6 +6,7 @@ int count_DimensionGenerator = 0;
 int count_ItemType = 0;
 int count_BlockType = 0;
 int count_WorldUpdateType = 0;
+int count_EntityType = 0;
 
 #undef REGISTER
 #define REGISTER(c, typ)               \
@@ -15,3 +16,4 @@ const c *c::INSTANCE = new c();
 #include "BasicBlocks.h"
 #include "OverworldDimension.h"
 #include "AddChunkUpdate.h"
+#include "Player.h"

+ 8 - 0
FactoryCraft/TickOrganizer.cpp

@@ -36,6 +36,14 @@ void TickOrganizer::nextTick()
             waiting |= workers[ i ]->isWaiting();
     } while( waiting );
     queue->startNextTick( &tickSources );
+    waiting = 0;
+    do
+    {
+        if( waiting )
+            queue->waitForEmpty();
+        for( int i = 0; i < workerCount; i++ )
+            waiting |= workers[ i ]->isWaiting();
+    } while( waiting );
 }
 
 void TickOrganizer::addTickSource( Block *zBlock )

+ 32 - 2
FactoryCraft/WorldLoader.cpp

@@ -12,6 +12,26 @@ WorldLoader::WorldLoader( Game *zGame )
     zGame( zGame ),
     exit( 0 )
 {
+    Datei d;
+    d.setDatei( zGame->getWorldDirectory() + "/dim" );
+    RCArray<Text> *names = d.getDateiListe();
+    for( auto name = names->getIterator(); name; name++ )
+    {
+        Datei entities;
+        entities.setDatei( zGame->getWorldDirectory() + "/dim/" + Text( name->getText() ) + "/entities" );
+        if( entities.open( Datei::Style::lesen ) )
+        {
+            Dimension *dim = new Dimension( *name.val() );
+            while( !entities.istEnde() )
+            {
+                int type = 0;
+                entities.lese( (char *)&type, 4 );
+                dim->addEntity( StaticRegistry<EntityType>::INSTANCE.zElement( type )->loadEntity( zGame, &entities ) );
+            }
+            zGame->addDimension( dim );
+        }
+    }
+    names->release();
     start();
 }
 
@@ -33,7 +53,7 @@ void WorldLoader::thread()
         cs.Leave();
         if( !hasNext )
         {
-            sleep( 1 );
+            Sleep( 1000 );
             continue;
         }
         Punkt start = zGame->getChunkCenter( next.startX, next.startY );
@@ -66,7 +86,7 @@ void WorldLoader::thread()
     }
 }
 
-void WorldLoader::requestGeneration( Area request )
+void WorldLoader::requestLoading( Area request )
 {
     cs.Enter();
     requestQueue.add( request );
@@ -78,4 +98,14 @@ void WorldLoader::exitAndWait()
     exit = 1;
     warteAufThread( 10000 );
     ende();
+}
+
+bool WorldLoader::existsChunk( int x, int y, int dimension ) const
+{
+    Text filePath = zGame->getWorldDirectory() + "/dim/" + dimension + "/";
+    filePath.appendHex( x );
+    filePath += "_";
+    filePath.appendHex( y );
+    filePath += ".chunk";
+    return DateiExistiert( filePath );
 }

+ 3 - 1
FactoryCraft/WorldLoader.h

@@ -1,6 +1,7 @@
 #pragma once
 
 #include <Thread.h>
+#include <HashMap.h>
 
 #include "Area.h"
 
@@ -18,6 +19,7 @@ public:
     WorldLoader( Game *zGame );
     ~WorldLoader();
     void thread() override;
-    void requestGeneration( Area request );
+    void requestLoading( Area request );
     void exitAndWait();
+    bool existsChunk( int x, int y, int dimension ) const;
 };

+ 1 - 1
FactoryCraft/WorldUpdate.h

@@ -19,7 +19,7 @@ public:
     WorldUpdate( int dimensionId, Framework::Vec3<int> minAffected, Framework::Vec3<int> maxAffected );
 
     virtual void onUpdate( Dimension *zDimension ) = 0;
-    virtual void write( Framework::Writer *zWriter ) = 0;
+    virtual void write( Framework::StreamWriter *zWriter ) = 0;
 
     int getAffectedDimension() const;
     const Framework::Vec3<int> &getMinAffectedPoint() const;