Index: branches/network_merged/src/lib/network/network_game_manager.cc
===================================================================
--- branches/network_merged/src/lib/network/network_game_manager.cc	(revision 6338)
+++ branches/network_merged/src/lib/network/network_game_manager.cc	(revision 6340)
@@ -20,4 +20,8 @@
 #define DEBUG_MODULE_NETWORK
 
+#include "factory.h"
+#include "network_stream.h"
+#include "converter.h"
+
 /* include your own header */
 #include "network_game_manager.h"
@@ -27,4 +31,6 @@
 using namespace std;
 
+NetworkGameManager* NetworkGameManager::singletonRef = NULL;
+
 /*!
  * Standard constructor
@@ -32,6 +38,18 @@
 NetworkGameManager::NetworkGameManager()
 {
+  PRINTF(0)("START\n");
+
   /* set the class id for the base object */
-  this->setClassID(CL_ENTITY_MANAGER, "EntityManager");
+  this->setClassID(CL_NETWORK_GAME_MANAGER, "NetworkGameManager");
+
+  allOutBuffer.length = 0;
+
+  allOutBuffer.maxLength = 10*1024;
+
+  allOutBuffer.buffer = new byte[10*1024];
+
+  newUniqueID = MAX_CONNECTIONS + 2;
+
+  hasRequestedWorld = false;
 }
 
@@ -41,13 +59,142 @@
 NetworkGameManager::~NetworkGameManager()
 {
-}
-
-
-void NetworkGameManager::writeBytes(const byte* data, int length)
-{
+  for ( int i = 0; i<outBuffer.size(); i++)
+  {
+    if ( outBuffer[i].buffer )
+      delete outBuffer[i].buffer;
+  }
+
+  if ( allOutBuffer.buffer )
+    delete allOutBuffer.buffer;
+}
+
+
+int NetworkGameManager::writeBytes(const byte* data, int length, int sender)
+{
+  int i = 0;
+  byte b;
+
+  while ( i<length )
+  {
+    b = data[i++];
+
+    PRINTF(0)("WriteBytes: b = %d\n", b);
+
+    if ( isServer() )
+    {
+      if ( b == REQUEST_CREATE )
+      {
+        if ( !handleRequestCreate( i, data, length, sender ) )
+          return i;
+        continue;
+      }
+      if ( b == REQUEST_REMOVE )
+      {
+        if ( !handleRequestRemove( i, data, length, sender ) )
+          return i;
+        continue;
+      }
+    }
+    else
+    {
+      if ( b == CREATE_ENTITY )
+      {
+        if ( !handleCreateEntity( i, data, length, sender ) )
+          return i;
+        continue;
+      }
+      if ( b == REMOVE_ENTITY )
+      {
+        if ( !handleRemoveEntity( i, data, length, sender ) )
+          return i;
+        continue;
+      }
+      if ( b == CREATE_ENTITY_LIST )
+      {
+        if ( !handleCreateEntityList( i, data, length, sender ) )
+          return i;
+        continue;
+      }
+      if ( b == REMOVE_ENTITY_LIST )
+      {
+        if ( !handleRemoveEntityList( i, data, length, sender ) )
+          return i;
+        continue;
+      }
+      if ( b == YOU_ARE_ENTITY )
+      {
+        if ( !handleYouAreEntity( i, data, length, sender ) )
+          return i;
+        continue;
+      }
+    }
+
+    if ( b == REQUEST_SYNC )
+    {
+      if ( !handleRequestSync( i, data, length, sender ) )
+        return i;
+      continue;
+    }
+
+    if ( b == REQUEST_ENTITY_LIST )
+    {
+      PRINTF(0)("sending THE list\n");
+      sendEntityList( sender );
+      continue;
+    }
+
+    //if we get her something with data is wrong
+    PRINTF(1)("Data is not in the right format! i=%d\n", i);
+    return i;
+  }
+
+  return i;
 }
 
 int NetworkGameManager::readBytes(byte* data, int maxLength, int * reciever)
 {
+  if ( !isServer() && !hasRequestedWorld )
+  {
+    SYNCHELP_WRITE_BEGIN();
+    byte b = REQUEST_ENTITY_LIST;
+    SYNCHELP_WRITE_BYTE( b );
+    hasRequestedWorld = true;
+    PRINTF(0)("the world is enough! id=%d\n", this->getUniqueID());
+    return SYNCHELP_WRITE_N;
+  }
+  for ( int i = 0; i<outBuffer.size(); i++ )
+  {
+    *reciever = i;
+    if ( outBuffer[i].length>0 )
+    {
+      int nbytes = outBuffer[i].length;
+      outBuffer[i].length = 0;
+
+      if ( nbytes > maxLength )
+      {
+        PRINTF(1)("OutBuffer.length (%d) > (%d) networkStreamBuffer.maxLength\n", nbytes, maxLength);
+        return 0;
+      }
+
+      memcpy(data, outBuffer[i].buffer, nbytes);
+      return nbytes;
+    }
+  }
+
+  *reciever = 0;
+  int nbytes = allOutBuffer.length;
+  allOutBuffer.length = 0;
+
+  if ( nbytes <=0 )
+    return 0;
+
+  if ( nbytes > maxLength )
+  {
+    PRINTF(1)("OutBuffer.length (%d) > (%d) networkStreamBuffer.length\n", nbytes, maxLength);
+    return 0;
+  }
+
+  memcpy( data, allOutBuffer.buffer, nbytes );
+  return nbytes;
 }
 
@@ -63,10 +210,72 @@
 /*!
  * Checks whether this is connected to a server or a client
- * and afterwards creates the needed entity if possible
+ * and afterwards creates the needed entity
  * @param classID: The ID of the class of which an entity should be created
  */
-void NetworkGameManager::createEntity(int classID)
-{
-}
+void NetworkGameManager::createEntity( ClassID classID, int owner )
+{
+  if ( this->isServer() )
+  {
+    if ( newUniqueID < 0 )
+    {
+      PRINTF(1)("Cannot create entity! There are no more uniqueIDs left!\n");
+      return;
+    }
+
+    this->executeCreateEntity( classID, newUniqueID++, owner );
+  }
+  else
+  {
+    this->requestCreateEntity( classID );
+  }
+}
+
+
+/*!
+ * Checks whether this is connected to a server or a client
+ * and afterwards creates the needed entity
+ * @param classID: The ID of the class of which an entity should be created
+ */
+BaseObject* NetworkGameManager::createEntity( TiXmlElement* element)
+{
+  if ( this->isServer() )
+  {
+    if ( newUniqueID < 0 )
+    {
+      PRINTF(1)("Cannot create entity! There are no more uniqueIDs left!\n");
+      return NULL;
+    }
+    newUniqueID++;
+
+    BaseObject * b = Factory::fabricate( element );
+
+    if ( !b )
+    {
+      PRINTF(1)("Could not fabricate Object with classID %x\n", element->Value() );
+      return NULL;
+    }
+
+
+    if ( b->isA(CL_SYNCHRONIZEABLE) )
+    {
+      Synchronizeable * s = dynamic_cast<Synchronizeable*>(b);
+      s->setUniqueID( newUniqueID );
+      s->setOwner( 0 );
+      this->networkStream->connectSynchronizeable( *s );
+      return b;
+    }
+    else
+    {
+      PRINTF(1)("Class %s is not a synchronizeable!\n", b->getClassName() );
+      delete b;
+    }
+  }
+  else
+  {
+    PRINTF(1)("This node is not a server and cannot create id %x\n", element->Value());
+  }
+  return NULL;
+}
+
 
 /*!
@@ -77,4 +286,12 @@
 void NetworkGameManager::removeEntity(int uniqueID)
 {
+  if ( this->isServer() )
+  {
+    this->executeRemoveEntity( uniqueID );
+  }
+  else
+  {
+    this->requestRemoveEntity( uniqueID );
+  }
 }
 
@@ -85,6 +302,10 @@
  * @param classID: The ID of the class of which an entity should be created
  */
-void NetworkGameManager::requestCreateEntity(int classID)
-{
+void NetworkGameManager::requestCreateEntity(ClassID classID)
+{
+  if ( !writeToClientBuffer( allOutBuffer, (byte)REQUEST_CREATE ) )
+    return;
+  if ( !writeToClientBuffer( allOutBuffer, (int)classID ) )
+    return;
 }
 
@@ -95,4 +316,8 @@
 void NetworkGameManager::requestRemoveEntity(int uniqueID)
 {
+  if ( !writeToClientBuffer( allOutBuffer, (byte)REQUEST_REMOVE ) )
+    return;
+  if ( !writeToClientBuffer( allOutBuffer, uniqueID ) )
+    return;
 }
 
@@ -102,6 +327,16 @@
  * @param classID: The ID of the class of which an entity should be created
  */
-void NetworkGameManager::executeCreateEntity(int classID)
-{
+void NetworkGameManager::executeCreateEntity(ClassID classID, int uniqueID, int owner)
+{
+  if ( !writeToClientBuffer( allOutBuffer, (byte)CREATE_ENTITY ) )
+    return;
+  if ( !writeToClientBuffer( allOutBuffer, (int)classID ) )
+    return;
+  if ( !writeToClientBuffer( allOutBuffer, uniqueID ) )
+    return;
+  if ( !writeToClientBuffer( allOutBuffer, owner ) )
+    return;
+
+  doCreateEntity( classID, uniqueID, owner );
 }
 
@@ -113,4 +348,10 @@
 void NetworkGameManager::executeRemoveEntity(int uniqueID)
 {
+  if ( !writeToClientBuffer( allOutBuffer, (byte)REMOVE_ENTITY ) )
+    return;
+  if ( !writeToClientBuffer( allOutBuffer, uniqueID ) )
+    return;
+
+  doRemoveEntity(uniqueID);
 }
 
@@ -119,5 +360,452 @@
  * @return: true if the entity can be created, false otherwise
  */
-bool NetworkGameManager::canCreateEntity(int classID)
-{
-}
+bool NetworkGameManager::canCreateEntity(ClassID classID)
+{
+  return true;
+}
+
+/*!
+ * Sends the Entities to the new connected client
+ * @param userID: The ID of the user
+ */
+void NetworkGameManager::sendEntityList( int userID )
+{
+  if ( !isServer() )
+    return;
+
+  if ( userID >= outBuffer.size() )
+    resizeBufferVector( userID );
+
+  SynchronizeableList::const_iterator it, e;
+
+  it = this->networkStream->getSyncBegin();
+  e = this->networkStream->getSyncEnd();
+
+  if ( !writeToClientBuffer( outBuffer[userID], (byte)CREATE_ENTITY_LIST ) )
+    return;
+
+  // -2 because you must not send network_game_manager and handshake
+  if ( !writeToClientBuffer( outBuffer[userID], networkStream->getSyncCount() ) )
+    return;
+
+  //PRINTF(0)("SendEntityList: n = %d\n", networkStream->getSyncCount()-2 );
+
+  while ( it != e )
+  {
+
+    if ( !writeToClientBuffer( outBuffer[userID], (int)((*it)->getLeafClassID()) ) )
+      return;
+      //PRINTF(0)("SendEntityList: ClassID = %x\n", (*it)->getRealClassID());
+
+    if ( !writeToClientBuffer( outBuffer[userID], (int)((*it)->getUniqueID()) ) )
+      return;
+
+    if ( !writeToClientBuffer( outBuffer[userID], (int)((*it)->getOwner()) ) )
+      return;
+
+    it++;
+  }
+
+
+}
+
+/**
+ * Creates a buffer for user n
+ * @param n The ID of the user
+ */
+void NetworkGameManager::resizeBufferVector( int n )
+{
+  for ( int i = outBuffer.size(); i<=n; i++)
+  {
+    clientBuffer outBuf;
+
+    outBuf.length = 0;
+
+    outBuf.maxLength = 5*1024;
+
+    outBuf.buffer = new byte[5*1014];
+
+    outBuffer.push_back(outBuf);
+  }
+}
+
+/**
+ * Creates the entity on this host
+ * @param classID: ClassID of the entity to create
+ * @param uniqueID: Unique ID to assign to the synchronizeable
+ * @param owner: owner of this synchronizealbe
+ */
+void NetworkGameManager::doCreateEntity( ClassID classID, int uniqueID, int owner )
+{
+  BaseObject * b = Factory::fabricate( classID );
+
+  if ( !b )
+  {
+    PRINTF(1)("Could not fabricate Object with classID %x\n", classID);
+    return;
+  }
+
+  if ( b->isA(CL_SYNCHRONIZEABLE) )
+  {
+    Synchronizeable * s = dynamic_cast<Synchronizeable*>(b);
+    s->setUniqueID( uniqueID );
+    s->setOwner( owner );
+    this->networkStream->connectSynchronizeable( *s );
+    if ( !isServer() )
+      s->setIsOutOfSync( true );
+    PRINTF(0)("Fabricated %s with id %d\n", s->getClassName(), s->getUniqueID());
+  }
+  else
+  {
+    PRINTF(1)("Class with ID %x is not a synchronizeable!", (int)classID);
+    delete b;
+  }
+}
+
+/**
+ * Removes a entity on this host
+ * @param uniqueID: unique ID assigned with the entity to remove
+ */
+void NetworkGameManager::doRemoveEntity( int uniqueID )
+{
+  SynchronizeableList::const_iterator it,e;
+  it = this->networkStream->getSyncBegin();
+  e = this->networkStream->getSyncEnd();
+
+  while ( it != e )
+  {
+    if ( (*it)->getUniqueID() == uniqueID )
+    {
+      delete *it;
+      break;
+    }
+    it++;
+  }
+}
+
+/**
+ * Tell the synchronizeable that a user's synchronizeable is out of sync
+ * @param uniqueID: unique ID assigned with the entity which is out of sync
+ * @param userID: user ID who's synchronizeable is out of sync
+ */
+void NetworkGameManager::doRequestSync( int uniqueID, int userID )
+{
+  SynchronizeableList::const_iterator it,e;
+  it = this->networkStream->getSyncBegin();
+  e = this->networkStream->getSyncEnd();
+
+  while ( it != e )
+  {
+    if ( (*it)->getUniqueID() == uniqueID )
+    {
+      (*it)->requestSync( userID );
+      break;
+    }
+    it++;
+  }
+}
+
+/**
+ * Copies length bytes to the clientBuffer with error checking
+ * @param clientBuffer: the clientBuffer to write to
+ * @param data: buffer to the data
+ * @param length: length of data
+ * @return false on error true else
+ */
+bool NetworkGameManager::writeToClientBuffer( clientBuffer &cb, byte * data, int length )
+{
+  if ( length > cb.maxLength-cb.length )
+  {
+    PRINTF(1)("No space left in clientBuffer\n");
+    return false;
+  }
+
+  memcpy( cb.buffer+cb.length, data, length );
+  return true;
+}
+
+/**
+ * Reads data from clientBuffer with error checking
+ * @param clientBuffer: the clientBuffer to read from
+ * @param data: pointer to the buffer
+ * @param length:
+ * @return
+ */
+bool NetworkGameManager::readFromClientBuffer( clientBuffer &cb, byte * data, int length )
+{
+  if ( cb.length < length )
+  {
+    PRINTF(0)("There is not enough data in clientBuffer\n");
+    return 0;
+  }
+
+  memcpy( data, cb.buffer+cb.length-length, length );
+  return true;
+}
+
+/**
+ * Tells this client that he has to control this entity
+ * @param uniqueID: the entity's uniqeID
+ */
+void NetworkGameManager::doYouAre( int uniqueID )
+{
+  //TODO: what has to be done
+}
+
+/**
+ * Tells a remote client that he has to control this entity
+ * @param uniqueID: the entity's uniqeID
+ * @param userID: the users ID
+ */
+void NetworkGameManager::sendYouAre( int uniqueID, int userID )
+{
+  if ( !isServer() )
+    return;
+
+  if ( userID != 0 )
+  {
+    if ( !writeToClientBuffer( outBuffer[userID], (byte)YOU_ARE_ENTITY ) )
+      return;
+
+    if ( !writeToClientBuffer( outBuffer[userID], uniqueID ) )
+      return;
+  }
+  else
+  {
+    doYouAre(uniqueID);
+  }
+}
+
+bool NetworkGameManager::handleRequestCreate( int & i, const byte * data, int length, int sender )
+{
+  if ( INTSIZE > length-i )
+  {
+    PRINTF(1)("Cannot read classID from buffer! Not enough data left!\n");
+    return false;
+  }
+  int classID;
+  i += Converter::byteArrayToInt( &data[i], &classID );
+
+  createEntity( (ClassID)classID );
+
+  return true;
+}
+
+bool NetworkGameManager::handleRequestRemove( int & i, const byte * data, int length, int sender )
+{
+  if ( INTSIZE > length-i )
+  {
+    PRINTF(1)("Cannot read uniqueID from buffer! Not enough data left!\n");
+    return false;
+  }
+  int uniqueID;
+  i += Converter::byteArrayToInt( &data[i], &uniqueID );
+
+  removeEntity( uniqueID );
+
+  return true;
+}
+
+bool NetworkGameManager::handleCreateEntity( int & i, const byte * data, int length, int sender )
+{
+  if ( INTSIZE > length-i )
+  {
+    PRINTF(1)("Cannot read classID from buffer! Not enough data left!\n");
+    return false;
+  }
+  int classID;
+  i += Converter::byteArrayToInt( &data[i], &classID );
+
+  if ( INTSIZE > length-i )
+  {
+    PRINTF(1)("Cannot read uniqueID from buffer! Not enough data left!\n");
+    return false;
+  }
+  int uniqueID;
+  i += Converter::byteArrayToInt( &data[i], &uniqueID );
+
+  if ( INTSIZE > length-i )
+  {
+    PRINTF(1)("Cannot read owner from buffer! Not enough data left!\n");
+    return false;
+  }
+  int owner;
+  i += Converter::byteArrayToInt( &data[i], &owner );
+
+  doCreateEntity( (ClassID)classID, uniqueID, owner );
+
+  return true;
+}
+
+bool NetworkGameManager::handleRemoveEntity( int & i, const byte * data, int length, int sender )
+{
+  if ( INTSIZE > length-i )
+  {
+    PRINTF(1)("Cannot read uniqueID from buffer! Not enough data left!\n");
+    return false;
+  }
+  int uniqueID;
+  i += Converter::byteArrayToInt( &data[i], &uniqueID );
+
+  doRemoveEntity( uniqueID );
+
+  return true;
+}
+
+bool NetworkGameManager::handleCreateEntityList( int & i, const byte * data, int length, int sender )
+{
+  if ( INTSIZE > length-i )
+  {
+    PRINTF(1)("Cannot read n from buffer! Not enough data left!\n");
+    return false;
+  }
+
+  PRINTF(0)("HandleCreateEntityList:  data[i..i+3] = %d %d %d %d\n", data[i], data[i+1], data[i+2], data[i+3]);
+
+  int n;
+  i += Converter::byteArrayToInt( &data[i], &n );
+
+
+  PRINTF(0)("HandleCreateEntityList: n = %d\n", n);
+
+  int classID, uniqueID, owner;
+
+  for ( int j = 0; j<n; j++ )
+  {
+
+    if ( INTSIZE > length-i )
+    {
+      PRINTF(1)("Cannot read classID from buffer! Not enough data left!\n");
+      return false;
+    }
+    i += Converter::byteArrayToInt( &data[i], &classID );
+
+    if ( INTSIZE > length-i )
+    {
+      PRINTF(1)("Cannot read uniqueID from buffer! Not enough data left!\n");
+      return false;
+    }
+    i += Converter::byteArrayToInt( &data[i], &uniqueID );
+
+    if ( INTSIZE > length-i )
+    {
+      PRINTF(1)("Cannot read owner from buffer! Not enough data left!\n");
+      return false;
+    }
+    i += Converter::byteArrayToInt( &data[i], &owner );
+
+    if ( classID != CL_NETWORK_GAME_MANAGER && classID != CL_HANDSHAKE )
+      doCreateEntity( (ClassID)classID, uniqueID, owner );
+
+  }
+  return true;
+}
+
+bool NetworkGameManager::handleRemoveEntityList( int & i, const byte * data, int length, int sender )
+{
+  if ( INTSIZE > length-i )
+  {
+    PRINTF(1)("Cannot read n from buffer! Not enough data left!\n");
+    return false;
+  }
+  int n;
+  i += Converter::byteArrayToInt( &data[i], &n );
+
+  int uniqueID;
+
+  for ( int j = 0; j<n; j++ )
+  {
+
+    if ( INTSIZE > length-i )
+    {
+      PRINTF(1)("Cannot read uniqueID from buffer! Not enough data left!\n");
+      return false;
+    }
+    i += Converter::byteArrayToInt( &data[i], &uniqueID );
+
+    doRemoveEntity( uniqueID );
+  }
+
+  return true;
+}
+
+bool NetworkGameManager::handleYouAreEntity( int & i, const byte * data, int length, int sender )
+{
+  if ( INTSIZE > length-i )
+  {
+    PRINTF(1)("Cannot read uniqueID from buffer! Not enough data left!\n");
+    return false;
+  }
+
+  int uniqueID;
+  i += Converter::byteArrayToInt( &data[i], &uniqueID );
+
+  doYouAre( uniqueID );
+
+  return true;
+}
+
+bool NetworkGameManager::handleRequestSync( int & i, const byte * data, int length, int sender )
+{
+  if ( INTSIZE > length-i )
+  {
+    PRINTF(1)("Cannot read uniqueID from buffer! Not enough data left!\n");
+    return false;
+  }
+  int uniqueID;
+  i += Converter::byteArrayToInt( &data[i], &uniqueID );
+
+  doRequestSync( uniqueID, sender );
+
+  return true;
+}
+
+bool NetworkGameManager::writeToClientBuffer( clientBuffer & cb, byte b )
+{
+  if ( cb.maxLength-cb.length < 1 )
+  {
+    PRINTF(1)("Cannot write to clientBuffer! Not enough space for 1 byte\n");
+    return false;
+  }
+
+  cb.buffer[cb.length++] = b;
+
+  return true;
+}
+
+bool NetworkGameManager::writeToClientBuffer( clientBuffer & cb, int i )
+{
+  int n = Converter::intToByteArray( i, cb.buffer+cb.length, cb.maxLength-cb.length );
+  cb.length += n;
+
+  if ( n <= 0 )
+  {
+    PRINTF(1)("Cannot write to clientBuffer! Not enough space for 1 int\n");
+    return false;
+  }
+
+  return true;
+}
+
+void NetworkGameManager::sync( int uniqueID, int owner )
+{
+  if ( owner==this->getHostID() )
+    return;
+
+  if ( !isServer() )
+    executeRequestSync( uniqueID, 0 );
+  else
+    executeRequestSync( uniqueID, owner );
+}
+
+void NetworkGameManager::executeRequestSync( int uniqueID, int user )
+{
+  if ( user >= outBuffer.size() )
+    resizeBufferVector( user );
+
+  if ( !writeToClientBuffer( outBuffer[user], (byte)REQUEST_SYNC ) )
+    return;
+  if ( !writeToClientBuffer( outBuffer[user], uniqueID ) )
+    return;
+}
+
