Browse Source

Projektdateien hinzufügen.

Kolja Strohm 6 years ago
parent
commit
9276316568
38 changed files with 5440 additions and 0 deletions
  1. 12 0
      Data/ssInit.ini
  2. 34 0
      Spiel Server.sln
  3. 1102 0
      SpielServer/Datenbank.cpp
  4. 75 0
      SpielServer/Datenbank.h
  5. 112 0
      SpielServer/HistorieSender.cpp
  6. 35 0
      SpielServer/HistorieSender.h
  7. 208 0
      SpielServer/KartenLeser.cpp
  8. 38 0
      SpielServer/KartenLeser.h
  9. 32 0
      SpielServer/SSDatenbankV.h
  10. 38 0
      SpielServer/SSKlientV.h
  11. 629 0
      SpielServer/Spiel.cpp
  12. 72 0
      SpielServer/Spiel.h
  13. 412 0
      SpielServer/SpielErstellt.cpp
  14. 76 0
      SpielServer/SpielErstellt.h
  15. 40 0
      SpielServer/SpielKlasse.h
  16. 1803 0
      SpielServer/SpielServer.cpp
  17. 180 0
      SpielServer/SpielServer.h
  18. 118 0
      SpielServer/SpielServer.vcxproj
  19. 75 0
      SpielServer/SpielServer.vcxproj.filters
  20. 23 0
      SpielServer/Statistik.h
  21. 35 0
      SpielServer/Strukturen.cpp
  22. 25 0
      SpielServer/Strukturen.h
  23. BIN
      SpielServer/readme/images/ArchOptions.gif
  24. BIN
      SpielServer/readme/images/ChangeRemote.gif
  25. BIN
      SpielServer/readme/images/ManageConnections.gif
  26. BIN
      SpielServer/readme/images/OutputTypes.gif
  27. BIN
      SpielServer/readme/images/debuggerexport.png
  28. BIN
      SpielServer/readme/images/firstconnection.png
  29. BIN
      SpielServer/readme/images/linker.png
  30. BIN
      SpielServer/readme/images/postbuild.png
  31. 85 0
      SpielServer/readme/readme.html
  32. 119 0
      SpielServer/readme/stylesheet.css
  33. 60 0
      SpielServer/start.cpp
  34. 2 0
      build.bat
  35. BIN
      spiele/Asteroids/maps/Test/data.map
  36. BIN
      spiele/Asteroids/maps/Test/sts.ltgd
  37. BIN
      spiele/Asteroids/models/ship.m2
  38. BIN
      spiele/Linie/maps/Normal/sts.ltgd

+ 12 - 0
Data/ssInit.ini

@@ -0,0 +1,12 @@
+DBBenutzer=spielserveru
+DBPasswort=LTSpielServerPW
+DBName=koljadb
+DBIP=127.0.0.1
+DBPort=5432
+ServerName=Test
+ServerPort=49136
+ServerIP=192.168.178.20
+AdminServerPort=49135
+Aktiv=FALSE
+MaxClients=50
+MaxSpiele=50

+ 34 - 0
Spiel Server.sln

@@ -0,0 +1,34 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 15
+VisualStudioVersion = 15.0.26020.0
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SpielServer", "SpielServer\SpielServer.vcxproj", "{FEE06987-1A98-4953-8A84-F7D1CECF18F4}"
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|ARM = Debug|ARM
+		Debug|x64 = Debug|x64
+		Debug|x86 = Debug|x86
+		Release|ARM = Release|ARM
+		Release|x64 = Release|x64
+		Release|x86 = Release|x86
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{FEE06987-1A98-4953-8A84-F7D1CECF18F4}.Debug|ARM.ActiveCfg = Debug|ARM
+		{FEE06987-1A98-4953-8A84-F7D1CECF18F4}.Debug|ARM.Build.0 = Debug|ARM
+		{FEE06987-1A98-4953-8A84-F7D1CECF18F4}.Debug|x64.ActiveCfg = Debug|x64
+		{FEE06987-1A98-4953-8A84-F7D1CECF18F4}.Debug|x64.Build.0 = Debug|x64
+		{FEE06987-1A98-4953-8A84-F7D1CECF18F4}.Debug|x86.ActiveCfg = Debug|x86
+		{FEE06987-1A98-4953-8A84-F7D1CECF18F4}.Debug|x86.Build.0 = Debug|x86
+		{FEE06987-1A98-4953-8A84-F7D1CECF18F4}.Release|ARM.ActiveCfg = Release|ARM
+		{FEE06987-1A98-4953-8A84-F7D1CECF18F4}.Release|ARM.Build.0 = Release|ARM
+		{FEE06987-1A98-4953-8A84-F7D1CECF18F4}.Release|x64.ActiveCfg = Release|x64
+		{FEE06987-1A98-4953-8A84-F7D1CECF18F4}.Release|x64.Build.0 = Release|x64
+		{FEE06987-1A98-4953-8A84-F7D1CECF18F4}.Release|x86.ActiveCfg = Release|x86
+		{FEE06987-1A98-4953-8A84-F7D1CECF18F4}.Release|x86.Build.0 = Release|x86
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+EndGlobal

+ 1102 - 0
SpielServer/Datenbank.cpp

@@ -0,0 +1,1102 @@
+#include "Datenbank.h"
+#include <Text.h>
+#include <Datei.h>
+#include <Zeit.h>
+#include <iostream>
+
+// Inhalt der SSDatenbank Klasse aus Datenbank.h
+// Konstruktor
+SSDatenbank::SSDatenbank( InitDatei *zIni )
+{
+	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 << "SS: Die Verbindung zur Datenbank konnte nicht hergestellt werden.\nDas Programm wird beendet.";
+        exit( 1 );
+    }
+	InitializeCriticalSection( &cs );
+    ini = zIni->getThis();
+	ref = 1;
+    Text befehl = "SELECT port, admin_port, ip 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 ] );
+        zIni->addWert( "ServerIp", res.values[ 2 ] );
+    }
+    res.destroy();
+}
+
+// Destruktor
+SSDatenbank::~SSDatenbank()
+{
+	datenbank->release();
+	DeleteCriticalSection( &cs );
+    ini->release();
+}
+
+// nicht constant
+void SSDatenbank::lock()
+{
+	EnterCriticalSection( &cs );
+}
+
+void SSDatenbank::unlock()
+{
+	LeaveCriticalSection( &cs );
+}
+
+Text *SSDatenbank::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;
+}
+
+int SSDatenbank::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 SSDatenbank::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 SSDatenbank::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 SSDatenbank::setMaxSpiele( int id, int maxS )
+{
+	Text *befehl = new Text( "UPDATE server SET max_tasks = " );
+	befehl->append( maxS );
+	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 SSDatenbank::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;
+}
+
+int SSDatenbank::getAccountId( int clientId )
+{
+	if( !clientId )
+		return 0;
+	Text *befehl = new Text( "SELECT account_id FROM account_client WHERE client_id = " );
+	befehl->append( clientId );
+	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;
+	}
+	int ret = TextZuInt( res.values[ 0 ].getText(), 10 );
+	res.destroy();
+	return ret;
+}
+
+Text *SSDatenbank::getSpielArtName( int spielId )
+{
+	if( !spielId )
+		return new Text( "" );
+	Text *befehl = new Text( "SELECT name FROM spiel_art WHERE id = " );
+	befehl->append( spielId );
+	lock();
+	if( !datenbank->befehl( befehl->getText() ) )
+	{
+		unlock();
+		befehl->release();
+		return new Text( "" );
+	}
+	Result res = datenbank->getResult();
+	unlock();
+	befehl->release();
+	if( !res.zeilenAnzahl )
+	{
+		res.destroy();
+		return new Text( "" );
+	}
+	Text *ret = new Text( res.values[ 0 ].getText() );
+	res.destroy();
+	return ret;
+}
+
+Text *SSDatenbank::getKarteName( int karteId )
+{
+	if( !karteId )
+		return new Text( "Inoffiziell" );
+	Text *befehl = new Text( "SELECT name FROM karte WHERE id = " );
+	befehl->append( karteId );
+	lock();
+	if( !datenbank->befehl( befehl->getText() ) )
+	{
+		unlock();
+		befehl->release();
+		return new Text( "Inoffiziell" );
+	}
+	Result res = datenbank->getResult();
+	unlock();
+	befehl->release();
+	if( !res.zeilenAnzahl )
+	{
+		res.destroy();
+		return new Text( "Inoffiziell" );
+	}
+	Text *ret = new Text( res.values[ 0 ].getText() );
+	res.destroy();
+	return ret;
+}
+
+int SSDatenbank::getSpielArtId( int karteId )
+{
+	if( !karteId )
+		return 0;
+	Text *befehl = new Text( "SELECT spiel_art_id FROM karte WHERE id = " );
+	befehl->append( karteId );
+	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;
+	}
+	int ret = TextZuInt( res.values[ 0 ].getText(), 10 );
+	res.destroy();
+	return ret;
+}
+
+int SSDatenbank::erstelleSpiel( int serverId )
+{
+	if( !serverId )
+		return 0;
+	Text *befehl = new Text( "SELECT such_spieler_fuer_spiel( " );
+	befehl->append( serverId );
+	befehl->append( ")" );
+	lock();
+	if( !datenbank->befehl( befehl->getText() ) )
+	{
+		unlock();
+		befehl->release();
+		return 0;
+	}
+	Result res = datenbank->getResult();
+	unlock();
+	befehl->release();
+	int ret = TextZuInt( res.values[ 0 ].getText(), 10 );
+	res.destroy();
+	return ret;
+}
+
+bool SSDatenbank::deleteSpielErstelltNext( int serverId )
+{
+	if( !serverId )
+		return 0;
+	Text *befehl = new Text( "DELETE FROM server_spiel_next WHERE server_spiel_id = " );
+	befehl->append( serverId );
+	lock();
+	if( !datenbank->befehl( befehl->getText() ) )
+	{
+		unlock();
+		befehl->release();
+		return 0;
+	}
+	unlock();
+	befehl->release();
+	return 1;
+}
+
+int SSDatenbank::getSpielErstelltId( int serverId )
+{
+	if( !serverId )
+		return 0;
+	Text *befehl = new Text( "SELECT spiel_erstellt_id FROM server_spiel_next WHERE server_spiel_id = " );
+	befehl->append( serverId );
+	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;
+	}
+	int ret = TextZuInt( res.values[ 0 ].getText(), 10 );
+	res.destroy();
+	return ret;
+}
+
+int SSDatenbank::getSpielErstelltSpieler( int spielErstelltId, Array< int > *accountIds )
+{
+	if( !spielErstelltId )
+		return 0;
+	Text *befehl = new Text( "SELECT a.account_id FROM spiel_erstellt_spieler a WHERE a.spiel_erstellt_id = " );
+	befehl->append( spielErstelltId );
+	befehl->append( " UNION SELECT a.account_id FROM gruppe_spieler a, spiel_erstellt_gruppe b WHERE a.gruppe_id = b.gruppe_id AND b.spiel_erstellt_id = " );
+	befehl->append( spielErstelltId );
+	lock();
+	if( !datenbank->befehl( befehl->getText() ) )
+	{
+		unlock();
+		befehl->release();
+		return 0;
+	}
+	Result res = datenbank->getResult();
+	unlock();
+	befehl->release();
+	int ret = res.zeilenAnzahl;
+	for( int i = 0; i < ret; i++ )
+		accountIds->set( TextZuInt( res.values[ i ].getText(), 10 ), i );
+	res.destroy();
+	return ret;
+}
+
+int SSDatenbank::getKarteVonErstelltemSpiel( int spielErstelltId )
+{
+	if( !spielErstelltId )
+		return 0;
+	Text *befehl = new Text( "SELECT karte_id FROM spiel_erstellt WHERE id = " );
+	befehl->append( spielErstelltId );
+	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;
+	}
+	int ret = TextZuInt( res.values[ 0 ].getText(), 10 );
+	res.destroy();
+	return ret;
+}
+
+bool SSDatenbank::getChatServerPortIp( int accountId, int *port, Text *zIp )
+{
+	if( !accountId )
+		return 0;
+	Text *befehl = new Text( "SELECT a.port, a.ip FROM server a, account_client b, server_client c WHERE a.server_typ_name = 'chat' AND a.id = c.server_id AND c.client_id = b.client_id AND b.account_id = " );
+	befehl->append( accountId );
+	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;
+	}
+	*port = TextZuInt( res.values[ 0 ].getText(), 10 );
+	zIp->setText( res.values[ 1 ].getText() );
+	res.destroy();
+	return 1;
+}
+
+bool SSDatenbank::spielErstelltAbbruch( int spielErstelltId, int anzahl, Array< int > *accounts, Array< int > *status, Array< bool > *inWarteschlange, RCArray< Zeit > *zeit )
+{
+	if( !spielErstelltId || !anzahl )
+		return 0;
+	Text *befehl = new Text( "BEGIN" );
+	lock();
+	if( !datenbank->befehl( befehl->getText() ) )
+	{
+		unlock();
+		befehl->release();
+		return 0;
+	}
+	befehl->setText( "UPDATE server_spiel_regel SET jetzt_spiele = jetzt_spiele - 1 FROM spiel_erstellt "
+					 "WHERE server_spiel_regel.server_spiel_id = spiel_erstellt.server_spiel_id "
+					 "AND server_spiel_regel.karte_id = spiel_erstellt.karte_id AND spiel_erstellt.id = " );
+	befehl->append( spielErstelltId );
+	if( !datenbank->befehl( befehl->getText() ) )
+	{
+		befehl->setText( "ROLLBACK" );
+		datenbank->befehl( befehl->getText() );
+		unlock();
+		befehl->release();
+		return 0;
+	}
+	befehl->setText( "UPDATE server SET tasks = tasks - 1 FROM spiel_erstellt "
+					 "WHERE server.id = spiel_erstellt.server_spiel_id AND spiel_erstellt.id = " );
+	befehl->append( spielErstelltId );
+	if( !datenbank->befehl( befehl->getText() ) )
+	{
+		befehl->setText( "ROLLBACK" );
+		datenbank->befehl( befehl->getText() );
+		unlock();
+		befehl->release();
+		return 0;
+	}
+	befehl->setText( "SELECT karte_id FROM spiel_erstellt WHERE id = " );
+	befehl->append( spielErstelltId );
+	if( !datenbank->befehl( befehl->getText() ) )
+	{
+		befehl->setText( "ROLLBACK" );
+		datenbank->befehl( befehl->getText() );
+		unlock();
+		befehl->release();
+		return 0;
+	}
+	Result res = datenbank->getResult();
+	if( !res.zeilenAnzahl )
+	{
+		befehl->setText( "ROLLBACK" );
+		datenbank->befehl( befehl->getText() );
+		unlock();
+		befehl->release();
+		res.destroy();
+		return 0;
+	}
+	int karteId = TextZuInt( res.values[ 0 ].getText(), 10 );
+	res.destroy();
+	befehl->setText( "SELECT account_id, anmeldung_zeit FROM spiel_erstellt_spieler WHERE spiel_erstellt_id = " );
+	befehl->append( spielErstelltId );
+	if( !datenbank->befehl( befehl->getText() ) )
+	{
+		befehl->setText( "ROLLBACK" );
+		datenbank->befehl( befehl->getText() );
+		unlock();
+		befehl->release();
+		return 0;
+	}
+	Result acc = datenbank->getResult();
+	befehl->setText( "SELECT gruppe_id, anmeldung_zeit FROM spiel_erstellt_gruppe WHERE spiel_erstellt_id = " );
+	befehl->append( spielErstelltId );
+	if( !datenbank->befehl( befehl->getText() ) )
+	{
+		befehl->setText( "ROLLBACK" );
+		datenbank->befehl( befehl->getText() );
+		unlock();
+		acc.destroy();
+		befehl->release();
+		return 0;
+	}
+	Result gru = datenbank->getResult();
+	befehl->setText( "DELETE FROM spiel_erstellt_spieler WHERE spiel_erstellt_id = " );
+	befehl->append( spielErstelltId );
+	if( !datenbank->befehl( befehl->getText() ) )
+	{
+		befehl->setText( "ROLLBACK" );
+		datenbank->befehl( befehl->getText() );
+		unlock();
+		acc.destroy();
+		gru.destroy();
+		befehl->release();
+		return 0;
+	}
+	befehl->setText( "DELETE FROM spiel_erstellt_gruppe WHERE spiel_erstellt_id = " );
+	befehl->append( spielErstelltId );
+	if( !datenbank->befehl( befehl->getText() ) )
+	{
+		befehl->setText( "ROLLBACK" );
+		datenbank->befehl( befehl->getText() );
+		unlock();
+		acc.destroy();
+		gru.destroy();
+		befehl->release();
+		return 0;
+	}
+	befehl->setText( "DELETE FROM spiel_erstellt WHERE id = " );
+	befehl->append( spielErstelltId );
+	if( !datenbank->befehl( befehl->getText() ) )
+	{
+		befehl->setText( "ROLLBACK" );
+		datenbank->befehl( befehl->getText() );
+		unlock();
+		acc.destroy();
+		gru.destroy();
+		befehl->release();
+		return 0;
+	}
+	for( int i = 0; i < acc.zeilenAnzahl; i++ )
+	{
+		int accId = TextZuInt( acc.values[ i * 2 ].getText(), 10 );
+		for( int j = 0; j < anzahl; j++ )
+		{
+			if( accounts->hat( j ) && accId == accounts->get( j ) )
+			{
+				if( status->hat( j ) && status->get( j ) == 2 )
+				{ // zurück in Warteschlange
+					befehl->setText( "INSERT INTO account_anmeldung_fuer_spiel( account_id, karte_id, anmeldung_zeit ) VALUES( " );
+					befehl->append( accId );
+					befehl->append( ", " );
+					befehl->append( karteId );
+					befehl->append( ", '" );
+					befehl->append( acc.values[ i * 2 + 1 ].getText() );
+					befehl->append( "' )" );
+					if( datenbank->befehl( befehl->getText() ) )
+					{
+						inWarteschlange->set( 1, j );
+						Zeit *jetzt = getZeit();
+						Zeit *anmeldung = new Zeit();
+						anmeldung->setZeit( "y-m-d h:i:s", acc.values[ i * 2 + 1 ].getText() );
+						jetzt->minusZeit( anmeldung );
+						zeit->set( jetzt, j );
+					}
+				}
+				break;
+			}
+		}
+	}
+	acc.destroy();
+	for( int i = 0; i < gru.zeilenAnzahl; i++ )
+	{
+		bool backInWarteschlange = 1;
+		Array< int > *mitglieder = new Array< int >();
+		int mAnzahl = getSpielerAusGruppe( TextZuInt( gru.values[ i * 2 ].getText(), 10 ), mitglieder );
+		for( int j = 0; j < mAnzahl; j++ )
+		{
+			if( mitglieder->hat( j ) )
+			{
+				int akkId = mitglieder->get( j );
+				for( int k = 0; k < anzahl; k++ )
+				{
+					if( accounts->hat( k ) && akkId == accounts->get( k ) )
+						backInWarteschlange &= status->hat( k ) && status->get( k ) == 2;
+				}
+				if( !backInWarteschlange )
+					break;
+			}
+		}
+		if( backInWarteschlange )
+		{
+			befehl->setText( "INSERT INTO grupe_aneldung_fuer_spiel( gruppe_id, anmeldung_zeit ) VALUES( " );
+			befehl->append( TextZuInt( gru.values[ i * 2 ].getText(), 10 ) );
+			befehl->append( ", '" );
+			befehl->append( gru.values[ i * 2 + 1 ].getText() );
+			befehl->append( "' )" );
+			if( datenbank->befehl( befehl->getText() ) )
+			{
+				Zeit *jetzt = getZeit();
+				Zeit *anmeldung = new Zeit();
+				anmeldung->setZeit( "y-m-d h:i:s", gru.values[ i * 2 + 1 ].getText() );
+				jetzt->minusZeit( anmeldung );
+				for( int j = 0; j < mAnzahl; j++ )
+				{
+					int akkId = mitglieder->get( j );
+					for( int k = 0; k < anzahl; k++ )
+					{
+						if( accounts->hat( k ) && akkId == accounts->get( k ) )
+						{
+							inWarteschlange->set( 1, k );
+							zeit->set( jetzt->getThis(), k );
+						}
+					}
+				}
+				jetzt->release();
+			}
+		}
+		mitglieder->release();
+	}
+	gru.destroy();
+	befehl->setText( "COMMIT" );
+	if( !datenbank->befehl( befehl->getText() ) )
+	{
+		unlock();
+		befehl->release();
+		return 0;
+	}
+	unlock();
+	befehl->release();
+	return 1;
+}
+
+int SSDatenbank::spielErstelltFortsetzen( int spielErstelltId )
+{
+	if( !spielErstelltId )
+		return 0;
+	Text *befehl = new Text( "SELECT spiel_erstellt_fortsetzen( " );
+	befehl->append( spielErstelltId );
+	befehl->append( " )" );
+	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;
+	}
+	int ret = TextZuInt( res.values[ 0 ].getText(), 10 );
+	res.destroy();
+	return ret;
+}
+
+void SSDatenbank::spielSetTeams( int spielId, int sAnzahl, Array< int > *accounts, Array< int > *team )
+{
+	Text *befehl = new Text( "" );
+	for( int i = 0; i < sAnzahl; i++ )
+	{
+		if( team->hat( i ) && accounts->hat( i ) )
+		{
+			befehl->setText( "UPDATE spiel_spieler SET team_id = " );
+			befehl->append( team->get( i ) );
+			befehl->append( " WHERE account_id = " );
+			befehl->append( accounts->get( i ) );
+			befehl->append( " AND spiel_id = " );
+			befehl->append( spielId );
+			lock();
+			datenbank->befehl( befehl->getText() );
+			unlock();
+		}
+	}
+	befehl->release();
+}
+
+void SSDatenbank::spielSetSpielerNummern( int spielId, int sAnzahl, Array< int > *accounts, Array< int > *spielerNummern )
+{
+	Text *befehl = new Text( "" );
+	for( int i = 0; i < sAnzahl; i++ )
+	{
+		if( spielerNummern->hat( i ) && accounts->hat( i ) )
+		{
+			befehl->setText( "UPDATE spiel_spieler SET spieler_nummer = " );
+			befehl->append( spielerNummern->get( i ) );
+			befehl->append( " WHERE account_id = " );
+			befehl->append( accounts->get( i ) );
+			befehl->append( " AND spiel_id = " );
+			befehl->append( spielId );
+			lock();
+			datenbank->befehl( befehl->getText() );
+			unlock();
+		}
+	}
+	befehl->release();
+}
+
+int SSDatenbank::getSpielerAusGruppe( int gruppeId, Array< int > *accounts )
+{
+	Text *befehl = new Text( "SELECT account_id FROM gruppe_spieler WHERE gruppe_id = " );
+	befehl->append( gruppeId );
+	lock();
+	if( !datenbank->befehl( befehl->getText() ) )
+	{
+		unlock();
+		befehl->release();
+		return 0;
+	}
+	Result res = datenbank->getResult();
+	unlock();
+	befehl->release();
+	int ret = res.zeilenAnzahl;
+	for( int i = 0; i < ret; i++ )
+		accounts->set( TextZuInt( res.values[ i ].getText(), 10 ), i );
+	res.destroy();
+	return ret;
+}
+
+int SSDatenbank::getAktionForKlient( int serverId, int accountId, int *id )
+{
+	if( !serverId || !accountId )
+		return 0;
+	Text *befehl = new Text( "SELECT a.id FROM spiel_erstellt a, spiel_erstellt_spieler b "
+							 "WHERE b.spiel_erstellt_id = a.id AND b.account_id = " );
+	befehl->append( accountId );
+	befehl->append( " AND a.server_spiel_id = " );
+	befehl->append( serverId );
+	befehl->append( " UNION SELECT a.id FROM spiel_erstellt a, spiel_erstellt_gruppe b, gruppe_spieler d "
+					  "WHERE b.spiel_erstellt_id = a.id AND d.gruppe_id = b.gruppe_id AND d.account_id = " );
+	befehl->append( accountId );
+	befehl->append( " AND a.server_spiel_id = " );
+	befehl->append( serverId );
+	lock();
+	if( !datenbank->befehl( befehl->getText() ) )
+	{
+		unlock();
+		befehl->release();
+		return 0;
+	}
+	Result res = datenbank->getResult();
+	unlock();
+	if( res.zeilenAnzahl )
+	{
+		befehl->release();
+		*id = TextZuInt( res.values[ 0 ].getText(), 10 );
+		res.destroy();
+		return 1;
+	}
+	res.destroy();
+	befehl->setText( "SELECT a.id FROM spiel a, spiel_spieler b WHERE a.id = b.spiel_id AND a.spiel_status_id < 3 AND a.spiel_server_id = " );
+	befehl->append( serverId );
+	befehl->append( " AND b.account_id = " );
+	befehl->append( accountId ); lock();
+	if( !datenbank->befehl( befehl->getText() ) )
+	{
+		unlock();
+		befehl->release();
+		return 0;
+	}
+	res = datenbank->getResult();
+	unlock();
+	befehl->release();
+	if( res.zeilenAnzahl )
+	{
+		*id = TextZuInt( res.values[ 0 ].getText(), 10 );
+		res.destroy();
+		return 2;
+	}
+	res.destroy();
+	return 0;
+}
+
+bool SSDatenbank::setSpielStatusIsRunning( int spielId )
+{
+	if( !spielId )
+		return 0;
+	Text *befehl = new Text( "UPDATE spiel SET spiel_status_id = 2 WHERE id = " );
+	befehl->append( spielId );
+	lock();
+	if( !datenbank->befehl( befehl->getText() ) )
+	{
+		unlock();
+		befehl->release();
+		return 0;
+	}
+	unlock();
+	befehl->release();
+	return 1;
+}
+
+bool SSDatenbank::setSpielStatusBeendet( int spielId, int status )
+{
+	if( !spielId )
+		return 0;
+	Text *befehl = new Text( "UPDATE spiel SET spiel_status_id = " );
+	befehl->append( status );
+	befehl->append( " WHERE id = " );
+	befehl->append( spielId );
+	lock();
+	if( !datenbank->befehl( befehl->getText() ) )
+	{
+		unlock();
+		befehl->release();
+		return 0;
+	}
+	unlock();
+	befehl->setText( "UPDATE spiel SET end_datum = now() WHERE id = " );
+	befehl->append( spielId );
+	lock();
+	if( !datenbank->befehl( befehl->getText() ) )
+	{
+		unlock();
+		befehl->release();
+		return 0;
+	}
+	unlock();
+	befehl->setText( "UPDATE server SET tasks = tasks - 1 FROM spiel WHERE server.id = spiel.spiel_server_id AND spiel.id = " );
+	befehl->append( spielId );
+	lock();
+	if( !datenbank->befehl( befehl->getText() ) )
+	{
+		unlock();
+		befehl->release();
+		return 0;
+	}
+	unlock();
+	befehl->setText( "UPDATE server_spiel_regel SET jetzt_spiele = jetzt_spiele - 1 FROM spiel WHERE server_spiel_regel.server_spiel_id = spiel.spiel_server_id AND server_spiel_regel.karte_id = spiel.karte_id AND spiel.id = " );
+	befehl->append( spielId );
+	lock();
+	if( !datenbank->befehl( befehl->getText() ) )
+	{
+		unlock();
+		befehl->release();
+		return 0;
+	}
+	unlock();
+	befehl->release();
+	return 1;
+}
+
+bool SSDatenbank::setSpielSpielerStatus( int spielId, int accountId, int punkte, int status )
+{
+	if( !spielId || !accountId )
+		return 0;
+	Text *befehl = new Text( "UPDATE spiel_spieler SET spiel_spieler_status_id = " );
+	befehl->append( status );
+	befehl->append( " WHERE spiel_id = " );
+	befehl->append( spielId );
+	befehl->append( " AND account_id = " );
+	befehl->append( accountId );
+	lock();
+	if( !datenbank->befehl( befehl->getText() ) )
+	{
+		unlock();
+		befehl->release();
+		return 0;
+	}
+	unlock();
+	befehl->setText( "UPDATE spiel_spieler SET punkte = " );
+	befehl->append( punkte );
+	befehl->append( " WHERE spiel_id = " );
+	befehl->append( spielId );
+	befehl->append( " AND account_id = " );
+	befehl->append( accountId );
+	lock();
+	if( !datenbank->befehl( befehl->getText() ) )
+	{
+		unlock();
+		befehl->release();
+		return 0;
+	}
+	unlock();
+	if( ( punkte / 10 + status - 1 ) > 0 && ( status == 1 || status == 2 ) )
+	{
+		int kupfer = punkte / 10;
+		kupfer += status - 1;
+		befehl->setText( "UPDATE account SET kupfer = kupfer + " );
+		befehl->append( kupfer );
+		befehl->append( " WHERE id = " );
+		befehl->append( accountId );
+		lock();
+		if( !datenbank->befehl( befehl->getText() ) )
+		{
+			unlock();
+			befehl->release();
+			return 0;
+		}
+		unlock();
+	}
+	befehl->release();
+	return 1;
+}
+
+bool SSDatenbank::addSpielerStatistik( int accountId, int spielId )
+{
+	if( !spielId || !accountId )
+		return 0;
+	Text *befehl = new Text( "SELECT spiel_statistik.* FROM spiel_statistik, spiel, karte "
+							 "WHERE spiel_statistik.spiel_art_id = karte.spiel_art_id AND karte.id = spiel.karte_id "
+							 "AND spiel_statistik.account_id = " );
+	befehl->append( accountId );
+	befehl->append( " AND spiel.id = " );
+	befehl->append( spielId );
+	lock();
+	if( !datenbank->befehl( befehl->getText() ) )
+	{
+		unlock();
+		befehl->release();
+		return 0;
+	}
+	int anz = datenbank->getZeilenAnzahl();
+	unlock();
+	if( !anz )
+	{
+		befehl->setText( "INSERT INTO spiel_statistik( account_id, spiel_art_id ) SELECT " );
+		befehl->append( accountId );
+		befehl->append( " AS account_id, spiel_art.id FROM spiel_art, karte, spiel "
+						  "WHERE spiel_art.id = karte.spiel_art_id AND karte.id = spiel.karte_id AND spiel.id = " );
+		befehl->append( spielId );
+		lock();
+		if( !datenbank->befehl( befehl->getText() ) )
+		{
+			unlock();
+			befehl->release();
+			return 0;
+		}
+		unlock();
+	}
+	befehl->setText( "SELECT spiel_spieler_status_id FROM spiel_spieler WHERE account_id = " );
+	befehl->append( accountId );
+	befehl->append( " AND spiel_id = " );
+	befehl->append( spielId );
+	lock();
+	if( !datenbank->befehl( befehl->getText() ) )
+	{
+		unlock();
+		befehl->release();
+		return 0;
+	}
+	Result res = datenbank->getResult();
+	unlock();
+	if( !res.zeilenAnzahl )
+	{
+		res.destroy();
+		befehl->release();
+		return 0;
+	}
+	int status = TextZuInt( res.values[ 0 ].getText(), 10 );
+	res.destroy();
+	befehl->setText( "UPDATE spiel_statistik SET gespielt = gespielt + 1, " );
+	if( status == 1 )
+		befehl->append( " verloren = spiel_statistik.verloren + 1, " );
+	if( status == 2 )
+		befehl->append( " gewonnen = spiel_statistik.gewonnen + 1, " );
+	befehl->append( " punkte = spiel_statistik.punkte + spiel_spieler.punkte FROM spiel_spieler, karte, spiel "
+					  "WHERE spiel_statistik.account_id = spiel_spieler.account_id "
+					  "AND spiel_statistik.spiel_art_id = karte.spiel_art_id "
+					  "AND karte.id = spiel.karte_id AND spiel_spieler.spiel_id = spiel.id AND spiel.id = " );
+	befehl->append( spielId );
+	befehl->append( " AND spiel_statistik.account_id = " );
+	befehl->append( accountId );
+	lock();
+	if( !datenbank->befehl( befehl->getText() ) )
+	{
+		unlock();
+		befehl->release();
+		return 0;
+	}
+	unlock();
+	befehl->release();
+	return 1;
+}
+
+Text *SSDatenbank::getAccountRufName( int accountId )
+{
+	if( !accountId )
+		return 0;
+	Text *befehl = new Text( "SELECT ruf_name FROM account WHERE id = " );
+	befehl->append( accountId );
+	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;
+	}
+	Text *ret = new Text( res.values[ 0 ].getText() );
+	res.destroy();
+	return ret;
+}
+
+bool SSDatenbank::suchHistorieServer( short *port, Text *ip )
+{
+	lock();
+	if( !datenbank->befehl( "SELECT such_historie_server()" ) )
+	{
+		unlock();
+		return 0;
+	}
+	Result res = datenbank->getResult();
+	unlock();
+	if( !res.zeilenAnzahl || (int)res.values[ 0 ] == 0 )
+	{
+		res.destroy();
+		return 0;
+	}
+	lock();
+	if( !datenbank->befehl( Text( "SELECT port, ip FROM server WHERE id = " ) += res.values[ 0 ].getText() ) )
+	{
+		unlock();
+		res.destroy();
+		return 0;
+	}
+	res.destroy();
+	res = datenbank->getResult();
+	unlock();
+	if( !res.zeilenAnzahl )
+	{
+		res.destroy();
+		return 0;
+	}
+	*port = (short)(int)res.values[ 0 ];
+	*ip = res.values[ 1 ].getText();
+	res.destroy();
+	return 1;
+}
+
+bool SSDatenbank::getKartenServer( int karteId, int *port, Text *ip )
+{
+    Text befehl = "SELECT a.port, a.ip FROM server a, karte b ";
+    befehl += "WHERE a.id = b.server_karten_id AND a.server_status_id = 3 AND b.id = ";
+    befehl += karteId;
+    lock();
+    if( !datenbank->befehl( befehl ) )
+    {
+        unlock();
+        return 0;
+    }
+    Result res = datenbank->getResult();
+    unlock();
+    *port = res.values[ 0 ];
+    ip->setText( res.values[ 1 ] );
+    res.destroy();
+    return 1;
+}
+
+Text *SSDatenbank::getSpielPfad( int karteId )
+{
+    Text befehl = "SELECT a.id FROM spiel_art a, karte b WHERE b.spiel_art_id = a.id AND b.id = ";
+    befehl += karteId;
+    lock();
+    if( !datenbank->befehl( befehl ) )
+    {
+        unlock();
+        return 0;
+    }
+    Result res = datenbank->getResult();
+    unlock();
+    if( !res.zeilenAnzahl )
+    {
+        res.destroy();
+        return 0;
+    }
+    int id = res.values[ 0 ];
+    res.destroy();
+    Text *ret = new Text( ini->zWert( "SpielePfad" )->getText() );
+    ret->append( "/" );
+    ret->append( id );
+    return ret;
+}
+
+// constant
+Text *SSDatenbank::getLetzterFehler() const
+{
+	return datenbank->getLetzterFehler();
+}
+
+// Reference Counting
+SSDatenbankV *SSDatenbank::getThis()
+{
+	ref++;
+	return this;
+}
+
+SSDatenbankV *SSDatenbank::release()
+{
+	ref--;
+	if( !ref )
+		delete this;
+	return 0;
+}

+ 75 - 0
SpielServer/Datenbank.h

@@ -0,0 +1,75 @@
+#ifndef Datenbank_H
+#define Datenbank_H
+
+#include <sql.h>
+#include "SSDatenbankV.h"
+#include <Text.h>
+#include <Array.h>
+#include <Zeit.h>
+#include <InitDatei.h>
+
+using namespace Framework;
+using namespace sql;
+
+namespace Admin_Recht
+{
+	const int SSStarten = 32;
+	const int SSBeenden = 34;
+	const int SSPausieren = 35;
+	const int SSMSChange = 36;
+}
+
+class SSDatenbank : private SSDatenbankV
+{
+private:
+	Datenbank *datenbank;
+	CRITICAL_SECTION cs;
+    InitDatei *ini;
+	int ref;
+
+public:
+	// Konstruktor
+	SSDatenbank( InitDatei *zIni );
+	// Destruktor
+	virtual ~SSDatenbank();
+	// nicht constant
+	void lock();
+	void unlock();
+	Text *getKlientKey( int cId );
+	int istAdministrator( const char *name, const char *passwort );
+	bool adminHatRecht( int id, int recht );
+	bool setServerStatus( int id, int status );
+	bool setMaxSpiele( int id, int maxS );
+	bool serverIstNichtPausiert( int id );
+	virtual int getAccountId( int clientId );
+	virtual Text *getSpielArtName( int spielId );
+	virtual Text *getKarteName( int karteId );
+	virtual int getSpielArtId( int karteId );
+	int erstelleSpiel( int serverId );
+	bool deleteSpielErstelltNext( int serverId );
+	int getSpielErstelltId( int serverId );
+	int getSpielErstelltSpieler( int spielErstelltId, Array< int > *accountIds );
+	int getKarteVonErstelltemSpiel( int spielErstelltId );
+	bool getChatServerPortIp( int accountId, int *port, Text *zIp );
+	bool spielErstelltAbbruch( int spielErstelltId, int anzahl, Array< int > *accounts, Array< int > *status, Array< bool > *inWarteschlange, RCArray< Zeit > *zeit );
+	int spielErstelltFortsetzen( int spielErstelltId );
+	void spielSetTeams( int spielId, int sAnzahl, Array< int > *accounts, Array< int > *team );
+	void spielSetSpielerNummern( int spielId, int sAnzahl, Array< int > *accounts, Array< int > *spielerNummern );
+	int getSpielerAusGruppe( int gruppeId, Array< int > *accounts );
+	int getAktionForKlient( int serverId, int accountId, int *id );
+	bool setSpielStatusIsRunning( int spielId );
+	virtual bool setSpielStatusBeendet( int spielId, int status );
+	virtual bool setSpielSpielerStatus( int spielId, int accountId, int punkte, int status );
+	virtual bool addSpielerStatistik( int accountId, int spielId );
+	virtual Text *getAccountRufName( int accountId );
+    bool suchHistorieServer( short *port, Text *ip );
+    bool getKartenServer( int karteId, int *port, Text *ip );
+    Text *getSpielPfad( int karteId );
+	// constant
+	Text *getLetzterFehler() const;
+	// Reference Counting
+	virtual SSDatenbankV *getThis();
+	virtual SSDatenbankV *release();
+};
+
+#endif

+ 112 - 0
SpielServer/HistorieSender.cpp

@@ -0,0 +1,112 @@
+#include "HistorieSender.h"
+#ifdef WIN32
+#include "../SpielServer.h"
+#else
+#include "SpielServer.h"
+#endif
+#include <Datei.h>
+
+// Inhalt der HistorieSender Klasse aus HistorieSender.h
+// Konstruktor
+HistorieSender::HistorieSender( SpielServer *zSS )
+{
+	this->zSS = zSS;
+	beenden = 0;
+	ref = 1;
+}
+
+// Destruktor
+HistorieSender::~HistorieSender()
+{
+}
+
+// nicht constant
+void HistorieSender::setEnde()
+{
+	beenden = 1;
+}
+
+void HistorieSender::thread()
+{
+	Datei *d = new Datei();
+	d->setDatei( "../spiel log" );
+	while( !beenden )
+	{
+		Sleep( 10000 );
+		int anz = d->getUnterdateiAnzahl();
+		RCArray< Text > *list = d->getDateiListe();
+		int min = 0;
+		for( int i = 0; i < anz; i++ )
+		{
+			if( !list->z( i ) )
+				continue;
+			Text pf( d->zPfad()->getText() );
+			pf += "/";
+			pf += list->z( i )->getText();
+			pf += "/fertig";
+			if( !DateiExistiert( pf ) )
+				continue;
+			if( !min || min >( int )*list->z( i ) )
+				min = *list->z( i );
+		}
+		list->release();
+		if( min )
+		{
+			short port = 0;
+			Text *ip = new Text();
+			if( zSS->zDB()->suchHistorieServer( &port, ip ) )
+			{
+				Klient *k = new Klient();
+				unsigned char key[ 20 ] = { 207, 30, 72, 46, 30, 50, 56, 213, 82, 107, 14, 201, 149, 58, 110, 138, 228, 241, 52, 54 };
+				k->setSendeKey( (char*)key, 20 );
+				k->setEmpfangKey( (char*)key, 20 );
+				if( k->verbinde( port, *ip ) )
+				{
+					zSS->addSpielHistorieId( min );
+					char ret = 0;
+					k->sendeEncrypted( "\5", 1 );
+					k->getNachrichtEncrypted( &ret, 1 );
+					if( ret == 1 )
+					{
+						int server = zSS->getId();
+						k->sendeEncrypted( (char*)&server, 4 );
+						k->sendeEncrypted( (char*)&min, 4 );
+						k->getNachrichtEncrypted( &ret, 1 );
+						if( ret == 1 )
+							DateiRemove( Text( "../spiel log/" ) += min );
+					}
+					if( ret == 3 )
+					{
+						k->getNachrichtEncrypted( &ret, 1 );
+						char *err = new char[ ret ];
+						k->getNachrichtEncrypted( err, ret );
+						delete[] err;
+					}
+					k->sendeEncrypted( "\3", 1 );
+					k->getNachrichtEncrypted( &ret, 1 );
+					k->trenne();
+					k->release();
+					zSS->removeSpielHistorieId( min );
+				}
+			}
+			ip->release();
+		}
+	}
+	d->release();
+	run = 0;
+}
+
+// Reference Counting
+HistorieSender *HistorieSender::getThis()
+{
+	ref++;
+	return this;
+}
+
+HistorieSender *HistorieSender::release()
+{
+	ref--;
+	if( !ref )
+		delete this;
+	return 0;
+}

+ 35 - 0
SpielServer/HistorieSender.h

@@ -0,0 +1,35 @@
+#ifndef HistorieSender_H
+#define HistorieSender_H
+
+#ifdef WIN32
+#include "../../Datenbank/Datenbank.h"
+#else
+#include "Datenbank.h"
+#endif
+#include <Thread.h>
+
+using namespace Framework;
+
+class SpielServer;
+
+class HistorieSender : public Thread
+{
+private:
+	SpielServer *zSS;
+	bool beenden;
+	int ref;
+
+public:
+	// Konstruktor
+	HistorieSender( SpielServer *zSS );
+	// Destruktor
+	virtual ~HistorieSender();
+	// nicht constant
+	void setEnde();
+	virtual void thread();
+	// Reference Counting
+	HistorieSender *getThis();
+	HistorieSender *release();
+};
+
+#endif

+ 208 - 0
SpielServer/KartenLeser.cpp

@@ -0,0 +1,208 @@
+#include "KartenLeser.h"
+#include <Datei.h>
+#ifdef WIN32
+#include "..\..\SpielServer.h"
+#include "..\..\..\Datenbank\Datenbank.h"
+#else
+#include "SpielServer.h"
+#include "Datenbank.h"
+#endif
+
+// Inhalt der KartenLeser Klasse aus KartenLeser.h
+// Konstruktor 
+KartenLeser::KartenLeser( int sNum, int karteId, SpielServer *ss )
+{
+    this->ss = ss;
+    pfad = new Text( "" );
+    ref = 1;
+    this->sNum = sNum;
+    setKarteId( karteId );
+}
+
+// Destruktor
+KartenLeser::~KartenLeser()
+{
+    ss->release();
+    pfad->release();
+}
+
+// nicht constant
+bool KartenLeser::setKarteId( int id )
+{
+    bool retVal = 1;
+    Text pf = ss->zInit()->zWert( "TempMapPfad" )->getText();
+    pf += "/";
+    pf += sNum;
+    if( !DateiExistiert( pf ) )
+    { // Karte Herunterladen
+        Text ip;
+        int port;
+        ss->zDB()->getKartenServer( id, &port, &ip );
+        Klient *klient = new Klient();
+        unsigned char key[ 20 ] = { 24, 15, 53, 87, 38, 73, 154, 38, 246, 90, 39, 133, 11, 199, 22, 80, 26, 132, 95, 54 };
+        klient->setSendeKey( (char*)key, 20 );
+        klient->setEmpfangKey( (char*)key, 20 );
+        if( !klient->verbinde( (unsigned short)port, ip ) )
+        {
+            klient = klient->release();
+            return 0;
+        }
+        klient->sendeEncrypted( "\x7", 1 );
+        char ret = 0;
+        klient->getNachrichtEncrypted( &ret, 1 );
+        if( ret == 1 )
+        {
+            klient->sendeEncrypted( (char*)&id, 4 );
+            klient->getNachrichtEncrypted( &ret, 1 );
+            if( ret == 2 )
+            { // update
+                retVal = 0;
+            }
+            else if( ret == 1 )
+            {
+                int anz = 0;
+                klient->getNachrichtEncrypted( (char*)&anz, 4 );
+                for( int i = 0; i < anz; i++ )
+                {
+                    char len = 0;
+                    klient->getNachrichtEncrypted( &len, 1 );
+                    if( !len )
+                        continue;
+                    char *pfa = new char[ len + 1 ];
+                    pfa[ (int)len ] = 0;
+                    klient->getNachrichtEncrypted( pfa, len );
+                    __int64 size = 0;
+                    klient->getNachrichtEncrypted( (char*)&size, 8 );
+                    char *buffer = new char[ 2048 ];
+                    Text pfad = pf.getText();
+                    pfad += "/";
+                    pfad += pfa;
+                    delete[] pfa;
+                    Datei d;
+                    d.setDatei( pfad );
+                    d.erstellen();
+                    d.open( Datei::Style::schreiben );
+                    while( size )
+                    {
+                        int l = size >= 2048 ? 2048 : (int)size;
+                        klient->getNachricht( buffer, l );
+                        d.schreibe( buffer, l );
+                        size -= l;
+                    }
+                    d.close();
+                    delete[] buffer;
+                }
+            }
+        }
+        if( ret == 3 )
+        {
+            retVal = 0;
+            char byte = 0;
+            klient->getNachrichtEncrypted( &byte, 1 );
+            char *f = new char[ byte + 1 ];
+            f[ (int)byte ] = 0;
+            klient->getNachrichtEncrypted( f, byte );
+            delete[] f;
+        }
+        klient->sendeEncrypted( "\3", 1 );
+        klient->getNachrichtEncrypted( &ret, 1 );
+        klient->trenne();
+        klient->release();
+    }
+    karteId = id;
+    pfad->setText( (char*)pf );
+    return retVal;
+}
+
+bool KartenLeser::ladeSpielerTeamStruktur( SpielerTeamStruktur *sts )
+{
+    if( !pfad->getLength() )
+        return 0;
+    Text *pf = new Text( pfad->getText() );
+    pf->append( "/sts.ltgd" );
+    Datei *datei = new Datei();
+    datei->setDatei( pf );
+    if( !datei->existiert() || datei->istOrdner() )
+    {
+        datei->release();
+        return 0;
+    }
+    datei->open( Datei::Style::lesen );
+    datei->lese( (char*)&sts->spielerAnzahl, 4 );
+    datei->lese( (char*)&sts->teamAnzahl, 4 );
+    if( sts->spielerFarbe )
+        sts->spielerFarbe->release();
+    sts->spielerFarbe = new Array< int >();
+    for( int i = 0; i < sts->spielerAnzahl; i++ )
+    {
+        int farbe = 0;
+        datei->lese( (char*)&farbe, 4 );
+        sts->spielerFarbe->set( farbe, i );
+    }
+    if( sts->teamFarbe )
+        sts->teamFarbe->release();
+    sts->teamFarbe = new Array< int >();
+    for( int i = 0; i < sts->teamAnzahl; i++ )
+    {
+        int farbe = 0;
+        datei->lese( (char*)&farbe, 4 );
+        sts->teamFarbe->set( farbe, i );
+    }
+    if( sts->teamName )
+        sts->teamName->release();
+    sts->teamName = new RCArray< Text >();
+    for( int i = 0; i < sts->teamAnzahl; i++ )
+    {
+        char len = 0;
+        datei->lese( &len, 1 );
+        char *txt = new char[ len + 1 ];
+        txt[ (int)len ] = 0;
+        datei->lese( txt, len );
+        Text *name = new Text( txt );
+        delete[] txt;
+        sts->teamName->set( name, i );
+    }
+    if( sts->teamSize )
+        sts->teamSize->release();
+    sts->teamSize = new Array< int >();
+    for( int i = 0; i < sts->teamAnzahl; i++ )
+    {
+        int size = 0;
+        datei->lese( (char*)&size, 4 );
+        sts->teamSize->set( size, i );
+    }
+    datei->close();
+    datei->release();
+    return 1;
+}
+
+// constant
+int KartenLeser::getKarteId() const
+{
+    return karteId;
+}
+
+Text *KartenLeser::getPfad() const
+{
+    return pfad ? pfad->getThis() : 0;
+}
+
+Text *KartenLeser::zPfad() const
+{
+    return pfad;
+}
+
+// Reference Counting
+KartenLeser *KartenLeser::getThis()
+{
+    ref++;
+    return this;
+}
+
+KartenLeser *KartenLeser::release()
+{
+    ref--;
+    if( !ref )
+        delete this;
+    return 0;
+}

+ 38 - 0
SpielServer/KartenLeser.h

@@ -0,0 +1,38 @@
+#ifndef KartenLeser_H
+#define KartenLeser_H
+
+#include <Klient.h>
+#include <Text.h>
+
+using namespace Framework;
+
+struct SpielerTeamStruktur;
+class SpielServer;
+
+class KartenLeser
+{
+private:
+	SpielServer *ss;
+	int karteId;
+	Text *pfad;
+    int sNum;
+	int ref;
+
+public:
+	// Konstruktor 
+	KartenLeser( int sNum, int karteId, SpielServer *ss );
+	// Destruktor
+	~KartenLeser();
+	// nicht constant
+	bool setKarteId( int id );
+	bool ladeSpielerTeamStruktur( SpielerTeamStruktur *sts );
+	// constant
+	int getKarteId() const;
+	Text *getPfad() const;
+	Text *zPfad() const;
+	// Reference Counting
+	KartenLeser *getThis();
+	KartenLeser *release();
+};
+
+#endif

+ 32 - 0
SpielServer/SSDatenbankV.h

@@ -0,0 +1,32 @@
+#ifndef SSDatenbankV_H
+#define SSDatenbankV_H
+
+#include <Text.h>
+
+using namespace Framework;
+
+class SSDatenbankV
+{
+private:
+
+public:
+    virtual ~SSDatenbankV()
+    {}
+	// nicht constant
+	virtual int getAccountId( int clientId ) = 0;
+	virtual Text *getSpielArtName( int spielId ) = 0;
+	virtual Text *getKarteName( int karteId ) = 0;
+	virtual int getSpielArtId( int karteId ) = 0;
+	virtual Text *getAccountRufName( int accountId ) = 0;
+	virtual bool setSpielStatusBeendet( int spielId, int status ) = 0;
+	virtual bool setSpielSpielerStatus( int spielId, int accountId, int punkte, int status ) = 0;
+	virtual bool addSpielerStatistik( int accountId, int spielId ) = 0;
+    virtual Text *getSpielPfad( int karteId ) = 0;
+	// constant
+
+	// Reference Counting
+	virtual SSDatenbankV *getThis() = 0;
+	virtual SSDatenbankV *release() = 0;
+};
+
+#endif

+ 38 - 0
SpielServer/SSKlientV.h

@@ -0,0 +1,38 @@
+#ifndef SSKlientV_H
+#define SSKlientV_H
+
+#include <Server.h>
+#include <Thread.h>
+#include "Strukturen.h"
+
+using namespace Framework;
+using namespace Network;
+
+class SSKlientV : public Thread
+{
+private:
+
+public:
+    // Konstructor
+    SSKlientV()
+        : Thread()
+    {}
+    virtual ~SSKlientV()
+    {}
+    // nicht constant 
+    virtual void nichtTrennen() = 0;
+    virtual double ping() = 0;
+    virtual void spielNachricht( short len, char *bytes ) = 0;
+    virtual void statistikNachricht( short len, char *bytes ) = 0;
+    virtual void trenne() = 0;
+    virtual void thread() = 0;
+    virtual void errorZuKlientEmpfang( const char *nachricht ) = 0; // sendet eine Fehlernachricht zum Klient
+    virtual void errorZuKlientSende( const char *nachricht ) = 0;
+    // const
+    virtual int getAccountId() const = 0;
+    // Reference Counting
+    virtual SSKlientV *getThis() = 0;
+    virtual SSKlientV *release() = 0;
+};
+
+#endif

+ 629 - 0
SpielServer/Spiel.cpp

@@ -0,0 +1,629 @@
+#include "Spiel.h"
+#include <Zeit.h>
+#ifdef WIN32
+#include "..\..\Datenbank\Datenbank.h"
+#include "..\SpielServer.h"
+#include "Reader\KartenLeser.h"
+#else
+#include "Datenbank.h"
+#include "SpielServer.h"
+#include "KartenLeser.h"
+#include <unistd.h>
+#define Sleep( x )               usleep( (x) * 1000 )
+#include <dlfcn.h>
+#define LoadLibrary( x )         dlopen( (x), RTLD_LAZY )
+#define GetProcAddress           dlsym
+#define FreeLibrary              dlclose
+#endif
+
+typedef SpielKlasse*( *DllStart )( );
+
+// Inhalt der Spiel Klasse aus Spiel.h
+// Konstruktor
+Spiel::Spiel( int id, SpielServer *ss )
+    : Thread()
+{
+    this->ss = ss;
+    this->id = id;
+    klients = new RCArray< SSKlient >();
+    sts = new SpielerTeamStruktur();
+    accounts = new Array< int >();
+    spielerNummern = new Array< int >();
+    status = new Array< int >();
+    prozent = new Array< int >();
+    teamAuswahlFertig = new Array< bool >();
+    spiel = 0;
+    state = 0;
+    spielerAnzahl = 0;
+    karte = 0;
+    spielDll = 0;
+    statistik = 0;
+    ref = 1;
+}
+
+// Destruktor
+Spiel::~Spiel()
+{
+    klients->release();
+    sts->release();
+    accounts->release();
+    spielerNummern->release();
+    status->release();
+    prozent->release();
+    teamAuswahlFertig->release();
+    if( spiel )
+        spiel->release();
+    if( statistik )
+        statistik->release();
+    if( spielDll )
+        FreeLibrary( spielDll );
+    ss->release();
+}
+
+int Spiel::findFreeTeam()
+{
+    int free = 0;
+    int teamIndex = 0;
+    int teamSize = sts->teamSize->get( teamIndex );
+    double max = 0;
+    Array< int > teams;
+    for( int i = 0; i < sts->spielerAnzahl; i++ ) // suche nach teams die prozentual am wenigsten voll sind
+    {
+        bool used = 0;
+        for( int j = 0; j < spielerAnzahl; j++ )
+        {
+            if( spielerNummern->hat( j ) && spielerNummern->get( j ) == i + 1 )
+                used = 1;
+        }
+        if( !used )
+            free++;
+        teamSize--;
+        if( !teamSize )
+        {
+            double teamVal = (double)free / sts->teamSize->get( teamIndex );
+            if( teamVal > max )
+            {
+                teams.leeren();
+                max = teamVal;
+            }
+            if( teamVal >= max )
+                teams.add( teamIndex );
+            free = 0;
+            if( !sts->teamSize->hat( ++teamIndex ) )
+                break;
+            else
+                teamSize = sts->teamSize->get( teamIndex );
+        }
+    } // suche aus den teams eines zufällig aus
+    double randomVal = rand() / ( (double)RAND_MAX + 1 );
+    double diff = 1.0 / teams.getEintragAnzahl();
+    teamIndex = -1;
+    while( randomVal >= 0 )
+    {
+        randomVal -= diff;
+        teamIndex++;
+    }
+    if( teams.hat( teamIndex ) )
+        return teams.get( teamIndex );
+    else
+        return teams.get( 0 );
+}
+
+void Spiel::teamAusgleich()
+{
+    for( int i = 0; i < spielerAnzahl; i++ )
+    {
+        int sNum = spielerNummern->hat( i ) ? spielerNummern->get( i ) : 0;
+        if( !sNum )
+        {
+            int team = findFreeTeam();
+            for( int j = 0; j < team; j++ )
+                sNum += sts->teamSize->get( j );
+            while( true )
+            {
+                sNum++;
+                bool gefunden = 0;
+                for( int k = 0; k < spielerAnzahl; k++ )
+                {
+                    if( spielerNummern->hat( k ) && spielerNummern->get( k ) == sNum )
+                    {
+                        gefunden = 1;
+                        break;
+                    }
+                }
+                if( !gefunden )
+                    break;
+            }
+            spielerNummern->set( sNum, i );
+        }
+    }
+}
+
+// nicht constant
+void Spiel::setAccounts( int anzahl, Array< int > *zAccounts )
+{
+    for( int i = 0; i < anzahl; i++ )
+        accounts->set( zAccounts->hat( i ) ? zAccounts->get( i ) : 0, i );
+    spielerAnzahl = anzahl;
+}
+
+void Spiel::setKlients( int anzahl, RCArray< SSKlient > *zKlients )
+{
+    for( int i = 0; i < anzahl; i++ )
+        klients->set( zKlients->get( i ), i );
+}
+
+void Spiel::setKarteId( int karteId )
+{
+    karte = karteId;
+    KartenLeser *reader = new KartenLeser( id, karte, ss->getThis() );
+    reader->ladeSpielerTeamStruktur( sts );
+    reader->release();
+    start();
+}
+
+bool Spiel::klientVerbunden( SSKlient *klient )
+{
+    int accId = klient->getAccountId();
+    bool ret = 0;
+    for( int i = 0; i < spielerAnzahl; i++ )
+    {
+        if( accounts->hat( i ) && accounts->get( i ) == accId )
+        {
+            if( state == 1 )
+            {
+                klient->erstellungInitialisierung( sts );
+                for( int j = 0; j < spielerAnzahl; j++ )
+                {
+                    if( accounts->hat( j ) && accounts->get( j ) != accId )
+                    {
+                        SSKlient *tmp = klients->z( j );
+                        tmp->erstellungAddSpieler( accId );
+                        klient->erstellungAddSpieler( accounts->get( j ) );
+                        if( spielerNummern->hat( j ) )
+                            klient->erstellungSpielerTeam( accounts->get( j ), spielerNummern->get( j ) );
+                    }
+                }
+            }
+            if( state == 5 && spiel )
+                spiel->klientOnline( klient->getAccountId(), klient );
+            klients->set( klient, i );
+            status->set( 1, i );
+            klient->setSpiel( this );
+            ret = 1;
+            break;
+        }
+    }
+    if( !ret )
+        klient->release();
+    return ret;
+}
+
+bool Spiel::klientWechseltTeam( int accountId, int team )
+{
+    if( state != 1 )
+        return 0;
+    if( team == 0 )
+    {
+        for( int i = 0; i < spielerAnzahl; i++ )
+        {
+            if( accounts->hat( i ) && accounts->get( i ) == accountId )
+                spielerNummern->set( 0, i );
+            SSKlient *tmp = klients->z( i );
+            if( tmp )
+                tmp->erstellungSpielerTeam( accountId, 0 );
+        }
+        return 1;
+    }
+    int von = 1;
+    for( int i = 0; i < team - 1; i++ )
+    {
+        if( sts->teamSize->hat( i ) )
+            von += sts->teamSize->get( i );
+    }
+    int bis = von + ( sts->teamSize->hat( team - 1 ) ? sts->teamSize->get( team - 1 ) : 0 );
+    for( int i = von; i < bis; i++ )
+    {
+        bool verwendet = 0;
+        for( int j = 0; j < spielerAnzahl; j++ )
+        {
+            if( spielerNummern->hat( j ) && spielerNummern->get( j ) == i )
+            {
+                verwendet = 1;
+                break;
+            }
+        }
+        if( !verwendet )
+        {
+            for( int j = 0; j < spielerAnzahl; j++ )
+            {
+                if( accounts->hat( j ) && accounts->get( j ) == accountId )
+                    spielerNummern->set( i, j );
+                SSKlient *tmp = klients->z( j );
+                if( tmp )
+                    tmp->erstellungSpielerTeam( accountId, i );
+            }
+            return 1;
+        }
+    }
+    return 0;
+}
+
+bool Spiel::chatNachricht( char *nachricht )
+{
+    if( state != 1 )
+        return 0;
+    for( int i = 0; i < spielerAnzahl; i++ )
+    {
+        SSKlient *tmp = klients->z( i );
+        if( tmp )
+            tmp->erstellungChatNachricht( nachricht );
+    }
+    return 1;
+}
+
+bool Spiel::klientGetrennt( SSKlient *zKlient )
+{
+    int accId = zKlient->getAccountId();
+    bool ret = 0;
+    for( int i = 0; i < spielerAnzahl; i++ )
+    {
+        if( accounts->hat( i ) && accounts->get( i ) == accId )
+        {
+            if( status->hat( i ) && status->get( i ) != 0 )
+            {
+                if( state == 1 )
+                {
+                    for( int j = 0; j < spielerAnzahl; j++ )
+                    {
+                        if( accounts->hat( j ) && accounts->get( j ) != accId )
+                        {
+                            SSKlient *tmp = klients->z( j );
+                            tmp->erstellungRemoveSpieler( accId );
+                        }
+                    }
+                }
+                if( state == 5 && spiel )
+                    spiel->klientOffline( zKlient->getAccountId() );
+                if( state == 6 )
+                {
+                    if( statistik )
+                        statistik->klientOffline( zKlient->getAccountId() );
+                }
+                zKlient->setSpielErstellt( 0 );
+                spielerNummern->set( 0, i );
+                status->set( 0, i );
+                klients->set( 0, i );
+                ret = 1;
+            }
+            break;
+        }
+    }
+    return ret;
+}
+
+bool Spiel::klientTeamAuswahlFertig( int accountId )
+{
+    for( int i = 0; i < spielerAnzahl; i++ )
+    {
+        if( accounts->hat( i ) && accounts->get( i ) == accountId )
+        {
+            teamAuswahlFertig->set( 1, i );
+            return 1;
+        }
+    }
+    return 0;
+}
+
+bool Spiel::klientBereitZumLaden( int accountId )
+{
+    if( state != 2 )
+        return 0;
+    for( int i = 0; i < spielerAnzahl; i++ )
+    {
+        if( accounts->hat( i ) && accounts->get( i ) == accountId )
+        {
+            status->set( 2, i );
+            return 1;
+        }
+    }
+    return 0;
+}
+
+bool Spiel::klientSpielLadenProzent( int accountId, int prozent )
+{
+    if( state != 3 && state != 2 )
+        return 0;
+    for( int i = 0; i < spielerAnzahl; i++ )
+    {
+        if( accounts->hat( i ) && accounts->get( i ) == accountId )
+        {
+            this->prozent->set( prozent, i );
+            return 1;
+        }
+    }
+    return 0;
+}
+
+bool Spiel::klientBereitZumSpiel( int accountId )
+{
+    if( state != 4 )
+        return 0;
+    for( int i = 0; i < spielerAnzahl; i++ )
+    {
+        if( accounts->hat( i ) && accounts->get( i ) == accountId )
+        {
+            status->set( 3, i );
+            return 1;
+        }
+    }
+    return 0;
+}
+
+bool Spiel::spielNachricht( int accountId, int len, char *bytes )
+{
+    if( state != 5 )
+        return 0;
+    if( spiel )
+    {
+        spiel->nachricht( accountId, len, bytes );
+        return 1;
+    }
+    return 0;
+}
+
+bool Spiel::statistikNachricht( int accountId, int len, char *bytes )
+{
+    if( state != 6 )
+        return 0;
+    if( statistik )
+    {
+        statistik->statistikAnfrage( accountId, (short)len, bytes );
+        return 1;
+    }
+    return 0;
+}
+
+void Spiel::thread()
+{
+    // Klients aktualisieren
+    for( int i = 0; i < spielerAnzahl; i++ )
+    {
+        SSKlient *tmp = klients->z( i );
+        if( tmp )
+        {
+            tmp->setSpielErstellt( 0 );
+            tmp->setSpiel( this );
+        }
+    }
+    // Vortsetzung senden
+    for( int i = 0; i < spielerAnzahl; i++ )
+    {
+        SSKlient *tmp = klients->z( i );
+        if( tmp )
+            tmp->erstellungInitialisierung( sts );
+    }
+    for( int i = 0; i < spielerAnzahl; i++ )
+    {
+        SSKlient *tmp = klients->z( i );
+        if( tmp )
+            tmp->erstellungFortsetzen();
+    }
+    for( int i = 0; i < spielerAnzahl; i++ )
+    {
+        SSKlient *tmp = klients->z( i );
+        if( tmp )
+        {
+            for( int j = 0; j < spielerAnzahl; j++ )
+            {
+                if( accounts->hat( j ) )
+                    tmp->erstellungAddSpieler( accounts->get( j ) );
+            }
+        }
+    }
+    // warten bis alle ein Team gewählt haben
+    double time = 0;
+    state = 1;
+    ZeitMesser *zeit = new ZeitMesser();
+    while( time < 40 )
+    {
+        zeit->messungStart();
+        Sleep( 100 );
+        char verbleibend = (char)( 40 - (char)time );
+        bool weiter = 1;
+        for( int i = 0; i < spielerAnzahl; i++ )
+            weiter &= teamAuswahlFertig->hat( i ) && teamAuswahlFertig->get( i );
+        if( verbleibend < 0 || weiter )
+        {
+            verbleibend = 0;
+            time = 40;
+        }
+        for( int i = 0; i < spielerAnzahl; i++ )
+        {
+            SSKlient *tmp = klients->z( i );
+            if( tmp )
+                tmp->zeitVerbleibend( verbleibend );
+        }
+        zeit->messungEnde();
+        time += zeit->getSekunden();
+    } // Spielernummern Aufteilen
+    zeit->release();
+    state = 2;
+    teamAusgleich();
+    Array< int > *teams = new Array< int >();
+    for( int i = 0; i < spielerAnzahl; i++ )
+    {
+        int sNum = spielerNummern->hat( i ) ? spielerNummern->get( i ) : 0;
+        int tg = 1;
+        for( int j = 0; j < sts->teamAnzahl; j++ )
+        {
+            tg += sts->teamSize->hat( j ) ? sts->teamSize->get( j ) : 0;
+            if( sNum < tg )
+            {
+                teams->set( j, i );
+                break;
+            }
+        }
+    }
+    ss->zDB()->spielSetTeams( id, spielerAnzahl, accounts, teams );
+    ss->zDB()->spielSetSpielerNummern( id, spielerAnzahl, accounts, spielerNummern );
+    teams->release();
+    // Fortsetzung senden
+    for( int i = 0; i < spielerAnzahl; i++ )
+    {
+        SSKlient *tmp = klients->z( i );
+        if( tmp )
+            tmp->spielLadenBeginn();
+    }
+    // Auf bereitschaft warten
+    while( 1 )
+    {
+        Sleep( 100 );
+        bool br = 1;
+        for( int i = 0; i < spielerAnzahl; i++ )
+        {
+            if( klients->z( i ) )
+                br = br && status->hat( i ) && status->get( i ) == 2;
+        }
+        if( br )
+            break;
+    } // Spieler hinzufügen
+    for( int i = 0; i < spielerAnzahl; i++ )
+        spielerNummern->set( ( spielerNummern->hat( i ) ? spielerNummern->get( i ) : 0 ) - 1, i );
+    for( int i = 0; i < spielerAnzahl; i++ )
+    {
+        SSKlient *tmp = klients->z( i );
+        if( tmp )
+        {
+            for( int j = 0; j < spielerAnzahl; j++ )
+                tmp->spielLadenSpielerAdd( accounts->hat( j ) ? accounts->get( j ) : 0, spielerNummern->hat( j ) ? spielerNummern->get( j ) : 0 );
+        }
+    }
+    state = 3;
+    // Warten auf laden
+    while( 1 )
+    {
+        Sleep( 1000 );
+        bool br = 1;
+        for( int i = 0; i < spielerAnzahl; i++ )
+        {
+            SSKlient *tmp = klients->z( i );
+            if( tmp )
+            {
+                int ping = (int)( tmp->ping() * 1000 + 0.5 );
+                for( int j = 0; j < spielerAnzahl; j++ )
+                {
+                    SSKlient *k = klients->z( j );
+                    if( k )
+                    {
+                        k->spielLadenSetSpielerPing( accounts->hat( i ) ? accounts->get( i ) : 0, ping );
+                        k->spielLadenSetSpielerProzent( accounts->hat( i ) ? accounts->get( i ) : 0, prozent->hat( i ) ? prozent->get( i ) : 0 );
+                    }
+                }
+                br = br && prozent->hat( i ) && prozent->get( i ) == 100;
+            }
+        }
+        if( br )
+            break;
+    }
+    state = 4;
+    // Sende Fortsetzung
+    for( int i = 0; i < spielerAnzahl; i++ )
+    {
+        SSKlient *tmp = klients->z( i );
+        if( tmp )
+            tmp->spielLadenFertig();
+    }
+    // Spiel Initialisieren
+    Text *pfad = new Text( ss->zInit()->zWert( "SpielePfad" )->getText() );
+    pfad->append( "/" );
+    pfad->append( ss->zDB()->getSpielArtId( karte ) );
+    pfad->append( "/bin/game" );
+#ifdef WIN32
+    pfad->append( ".dll" );
+#else
+    pfad->append( ".so" );
+#endif
+    spielDll = LoadLibrary( pfad->getText() );
+    if( !spielDll )
+    {
+        // error
+    }
+    pfad->release();
+    DllStart getSpielKlasse = (DllStart)GetProcAddress( spielDll, "getSpielKlasse" );
+    if( !getSpielKlasse )
+    {
+        // error
+    }
+    spiel = getSpielKlasse();
+    spiel->setPSQLK( ss->zDB()->getThis() );
+    spiel->setSpielId( id );
+    spiel->setKarteId( karte );
+    Text tmp = ss->zInit()->zWert( "TempMapPfad" )->getText();
+    tmp += "/";
+    tmp += id;
+    spiel->setTempPfad( tmp );
+    spiel->setAccounts( spielerAnzahl, accounts );
+    spiel->setKlients( spielerAnzahl, ( RCArray< SSKlientV >* )klients );
+    spiel->setSpielerNummern( spielerAnzahl, spielerNummern );
+    // auf klients warten
+    while( 1 )
+    {
+        Sleep( 100 );
+        bool br = 1;
+        for( int i = 0; i < spielerAnzahl; i++ )
+        {
+            if( klients->z( i ) )
+                br = br && status->hat( i ) && status->get( i ) == 3;
+        }
+        if( br )
+            break;
+    }
+    // Spiel starten
+    state = 5;
+    ss->zDB()->setSpielStatusIsRunning( id );
+    spiel->run();
+    // Spiel ist zuende
+    state = 6;
+    statistik = spiel->getStatistik();
+    spiel = spiel->release();
+    statistik->run();
+    // Statistik ist zuende
+    state = 7;
+    statistik = statistik->release();
+    FreeLibrary( spielDll );
+    spielDll = 0;
+    DateiRemove( tmp );
+    ss->removeSpiel( id ); // delete this
+}
+
+// constant
+int Spiel::getId() const
+{
+    return id;
+}
+
+int Spiel::getSpielerNummer( int accountId ) const
+{
+    for( int i = 0; i < spielerAnzahl; i++ )
+    {
+        if( accounts->hat( i ) && accounts->get( i ) == accountId )
+            return spielerNummern->hat( i ) ? spielerNummern->get( i ) : 0;
+    }
+    return 0;
+}
+
+// Reference Counting
+Spiel *Spiel::getThis()
+{
+    ref++;
+    return this;
+}
+
+Spiel *Spiel::release()
+{
+    ref--;
+    if( !ref )
+        delete this;
+    return 0;
+}

+ 72 - 0
SpielServer/Spiel.h

@@ -0,0 +1,72 @@
+#ifndef Spiel_H
+#define Spiel_H
+
+#include "SpielKlasse.h"
+#include <Array.h>
+#ifdef WIN32
+#include "..\Strukturen.h"
+#include "Statistik\Statistik.h"
+#else
+#include "Strukturen.h"
+#include "Statistik.h"
+#define HINSTANCE        void*
+#endif
+
+class SSKlient; // SpielServer.h
+class SpielServer; // SpielServer.h
+
+using namespace Framework;
+using namespace Network;
+
+class Spiel : private Thread
+{
+private:
+	SpielServer *ss;
+	int id;
+	RCArray< SSKlient > *klients;
+	SpielerTeamStruktur *sts;
+	Array< int > *accounts;
+	Array< int > *spielerNummern;
+	Array< int > *status;
+	Array< int > *prozent;
+	Array< bool > *teamAuswahlFertig;
+	SpielKlasse *spiel;
+	StatistikV *statistik;
+	int state;
+	int spielerAnzahl;
+	int karte;
+	HINSTANCE spielDll;
+	int ref;
+
+    int findFreeTeam();
+    void teamAusgleich();
+
+public:
+	// Konstruktor
+	Spiel( int id, SpielServer *ss );
+	// Destruktor
+	virtual ~Spiel();
+	// nicht constant
+	void setAccounts( int anzahl, Array< int > *zAccounts );
+	void setKlients( int anzahl, RCArray< SSKlient > *zKlients );
+	void setKarteId( int karteId );
+	bool klientVerbunden( SSKlient *klient );
+	bool klientWechseltTeam( int accountId, int team );
+	bool chatNachricht( char *nachricht );
+	bool klientGetrennt( SSKlient *zKlient );
+	bool klientTeamAuswahlFertig( int accountId );
+	bool klientBereitZumLaden( int accountId );
+	bool klientSpielLadenProzent( int accountId, int prozent );
+	bool klientBereitZumSpiel( int accountId );
+	bool spielNachricht( int accountId, int len, char *bytes );
+	bool statistikNachricht( int accountId, int len, char *bytes );
+	virtual void thread();
+	// constant
+	int getId() const;
+	int getSpielerNummer( int accountId ) const;
+	// Reference Counting
+	Spiel *getThis();
+	Spiel *release();
+};
+
+#endif

+ 412 - 0
SpielServer/SpielErstellt.cpp

@@ -0,0 +1,412 @@
+#ifdef WIN32
+#include "..\SpielServer.h"
+#include "..\..\Datenbank\Datenbank.h"
+#else
+#include "SpielServer.h"
+#include "Datenbank.h"
+#include <unistd.h>
+#define Sleep( x )   usleep( (x) * 1000 )
+#endif
+#include <Zeit.h>
+
+// Inhalt der SpielErstellt Kasse aus SpielErstellt.h
+// Konstruktor
+SpielErstellt::SpielErstellt( int id, SpielServer *ss )
+: Thread()
+{
+	this->ss = ss;
+	this->id = id;
+	karte = ss->zDB()->getKarteVonErstelltemSpiel( id );
+	spielArt = ss->zDB()->getSpielArtId( karte );
+	accounts = new Array< int >();
+	spielerAnzahl = ss->zDB()->getSpielErstelltSpieler( id, accounts );
+	klients = new RCArray< SSKlient >();
+	status = new Array< int >();
+	verbunden = 0;
+	state = 0;
+	abbr = 0;
+	spielId = 0;
+	ref = 1;
+}
+
+// Destruktor
+SpielErstellt::~SpielErstellt()
+{
+	ss->release();
+	accounts->release();
+	klients->release();
+	status->release();
+}
+
+// nicht constant
+void SpielErstellt::abbruch()
+{
+	abbr = 1;
+}
+
+void SpielErstellt::sendeVerbindungsBefehl()
+{
+	unsigned short sPort = (unsigned short)ss->getPort();
+	char *sIp = ss->getIp();
+	unsigned char *sIp4 = new unsigned char[ 4 ];
+	Text *tmpT = new Text( sIp );
+	Text *ip1 = tmpT->getTeilText( 0, tmpT->positionVon( '.' ) );
+	Text *ip2 = tmpT->getTeilText( tmpT->positionVon( '.' ) + 1, tmpT->positionVon( '.', 1 ) );
+	Text *ip3 = tmpT->getTeilText( tmpT->positionVon( '.', 1 ) + 1, tmpT->positionVon( '.', 2 ) );
+	Text *ip4 = tmpT->getTeilText( tmpT->positionVon( '.', 2 ) + 1 );
+	sIp4[ 0 ] = (unsigned char)TextZuInt( ip1->getText(), 10 );
+	sIp4[ 1 ] = (unsigned char)TextZuInt( ip2->getText(), 10 );
+	sIp4[ 2 ] = (unsigned char)TextZuInt( ip3->getText(), 10 );
+	sIp4[ 3 ] = (unsigned char)TextZuInt( ip4->getText(), 10 );
+	ip1->release();
+	ip2->release();
+	ip3->release();
+	ip4->release();
+	tmpT->release();
+	for( int i = 0; i < spielerAnzahl; i++ )
+	{
+		int accId = accounts->hat( i ) ? accounts->get( i ) : 0;
+		int port = 0;
+		Text *ip = new Text( "" );
+		if( ss->zDB()->getChatServerPortIp( accId, &port, ip ) )
+		{
+			char ret = 0;
+			Klient *klient = new Klient();
+			unsigned char key[ 20 ] = { 78, 20, 190, 133, 10, 175, 51, 96, 62, 1, 180, 194, 126, 50, 211, 154, 105, 227, 22, 101 };
+			klient->setSendeKey( (char*)key, 20 );
+			klient->setEmpfangKey( (char*)key, 20 );
+			klient->verbinde( (unsigned short)port, ip->getText() );
+			klient->sendeEncrypted( "\5\x1D", 2 );
+			klient->getNachrichtEncrypted( &ret, 1 );
+			if( ret != 3 )
+			{
+				klient->sendeEncrypted( (char*)&accId, 4 );
+				klient->sendeEncrypted( (char*)&sPort, 2 );
+				klient->sendeEncrypted( (char*)sIp4, 4 );
+				klient->getNachrichtEncrypted( &ret, 1 );
+			}
+			if( ret == 3 )
+			{
+				char len = 0;
+				klient->getNachrichtEncrypted( &len, 1 );
+				char *err = new char[ len ];
+				klient->getNachrichtEncrypted( err, len );
+				delete[] err;
+			}
+			klient->sendeEncrypted( "\3", 1 );
+			klient->getNachrichtEncrypted( &ret, 1 );
+			ss->addEmpfangen( klient->getDownloadBytes( 1 ) );
+			ss->addGesendet( klient->getUploadBytes( 1 ) );
+			klient->trenne();
+			klient->release();
+		}
+		ip->release();
+	}
+	delete[] sIp4;
+	start();
+}
+
+bool SpielErstellt::klientVerbunden( SSKlient *klient )
+{
+	if( verbunden == spielerAnzahl )
+	{
+		klient->release();
+		return 0;
+	}
+	int accId = klient->getAccountId();
+	bool ret = 0;
+	for( int i = 0; i < spielerAnzahl; i++ )
+	{
+		if( accounts->hat( i ) && accounts->get( i ) == accId )
+		{
+			if( state == 1 )
+				klient->spielGefunden( karte );
+			klients->set( klient, i );
+			status->set( 1, i );
+			verbunden++;
+			klient->setSpielErstellt( this );
+			ret = 1;
+			break;
+		}
+	}
+	if( !ret )
+		klient->release();
+	return ret;
+}
+
+bool SpielErstellt::klientNimmtAn( int accountId )
+{
+	if( !verbunden || state != 1 )
+		return 0;
+	bool ret = 0;
+	for( int i = 0; i < spielerAnzahl; i++ )
+	{
+		if( accounts->hat( i ) && accounts->get( i ) == accountId )
+		{
+			status->set( 2, i );
+			ret = 1;
+			break;
+		}
+	}
+	return ret;
+}
+
+bool SpielErstellt::klientLehntAb( int accountId )
+{
+	if( !verbunden || state != 1 )
+		return 0;
+	bool ret = 0;
+	for( int i = 0; i < spielerAnzahl; i++ )
+	{
+		if( accounts->hat( i ) && accounts->get( i ) == accountId )
+		{
+			status->set( 3, i );
+			ret = 1;
+			break;
+		}
+	}
+	return ret;
+}
+
+bool SpielErstellt::klientGetrennt( SSKlient *zKlient )
+{
+	if( !verbunden )
+		return 0;
+	int accId = zKlient->getAccountId();
+	bool ret = 0;
+	for( int i = 0; i < spielerAnzahl; i++ )
+	{
+		if( accounts->hat( i ) && accounts->get( i ) == accId )
+		{
+			if( status->hat( i ) && status->get( i ) != 0 )
+			{
+				zKlient->setSpielErstellt( 0 );
+				status->set( 0, i );
+				verbunden--;
+				klients->set( 0, i );
+				ret = 1;
+			}
+			break;
+		}
+	}
+	return ret;
+}
+
+void SpielErstellt::thread()
+{
+	state = 1;
+	double time = 0;
+	ZeitMesser *zeit = new ZeitMesser();
+	int nachrichtSenden = 1;
+	while( time < 10 )
+	{ // warten auf annahme von allen Spielern
+		if( abbr )
+			break;
+		zeit->messungStart();
+		Sleep( 100 );
+		bool br = 0;
+		bool st2 = 1;
+		for( int i = 0; i < spielerAnzahl; i++ )
+		{
+			if( status->hat( i ) && status->get( i ) == 3 )
+			{
+				br = 1;
+				for( int j = 0; j < spielerAnzahl; j++ )
+				{
+					if( j != i )
+						status->set( 2, j );
+				}
+				break;
+			}
+			if( st2 )
+				st2 = status->hat( i ) && status->get( i ) == 2;
+		}
+		if( st2 )
+			br = 1;
+		if( br )
+		{
+			zeit->messungEnde();
+			break;
+		}
+		char verbleibend = (char)( 10 - (char)time );
+		if( verbleibend < 0 )
+			verbleibend = 0;
+		if( time > nachrichtSenden )
+		{
+			for( int i = 0; i < spielerAnzahl; i++ )
+			{
+				if( status->hat( i ) && status->get( i ) != 0 )
+				{
+					SSKlient *tmp = klients->z( i );
+					if( tmp )
+						tmp->zeitVerbleibend( verbleibend );
+				}
+			}
+			nachrichtSenden++;
+		}
+		zeit->messungEnde();
+		time += zeit->getSekunden();
+	} // prüfen ob alle Spieler bereit sind
+	state = 2;
+	bool abbruch = verbunden != spielerAnzahl;
+	const char *err = "Ein Spieler konnte nicht erreicht werden.";
+	if( !abbruch )
+	{
+		for( int i = 0; i < spielerAnzahl; i++ )
+		{
+			if( !status->hat( i ) || status->get( i ) != 2 )
+			{
+				abbruch = 1;
+				err = "Ein Spieler ist noch nicht bereit.";
+				break;
+			}
+		}
+	}
+	if( abbr )
+	{
+		err = "Das Spiel wurde Wegen abwesenheit eines Spielers Abgebrochen.";
+		abbruch = 1;
+		for( int j = 0; j < spielerAnzahl; j++ )
+			status->set( 2, j );
+	}
+	if( abbruch )
+	{ // Es sind nicht alle bereit Vorgang abbrechen
+		for( int i = 0; i < spielerAnzahl; i++ )
+		{
+			if( status->hat( i ) && status->get( i ) != 0 )
+			{
+				SSKlient *tmp = klients->z( i );
+				if( tmp )
+					tmp->erstellungAbgebrochen( (char*)err );
+			}
+		}
+		Array< bool > *inWarteschlange = new Array< bool >();
+		RCArray< Zeit > *wZeit = new RCArray< Zeit >();
+		if( ss->zDB()->spielErstelltAbbruch( id, spielerAnzahl, accounts, status, inWarteschlange, wZeit ) ) // zurück in Warteschlange
+		{
+			for( int i = 0; i < spielerAnzahl; i++ )
+			{
+				if( inWarteschlange->hat( i ) && inWarteschlange->get( i ) )
+				{
+					SSKlient *tmp = klients->z( i );
+					if( tmp )
+					{
+						Zeit *zTmp = wZeit->z( i );
+						if( zTmp )
+							tmp->backInWarteschlange( (char)zTmp->zUhrzeit()->getStunde(), (char)zTmp->zUhrzeit()->getMinute(), (char)zTmp->zUhrzeit()->getSekunde() );
+					}
+				}
+			}
+		}
+		inWarteschlange->release();
+		wZeit->release();
+		for( int i = 0; i < spielerAnzahl; i++ )
+		{
+			SSKlient *tmp = klients->z( i );
+			if( tmp )
+				tmp->trenne();
+		}
+		zeit->release();
+		ss->removeSpielErstellt( id ); // delete this
+		return;
+	}
+	// alle Spieler sind bereit Vorgang fortsetzen
+	spielId = ss->zDB()->spielErstelltFortsetzen( id );
+	Spiel *weiter = new Spiel( spielId, ss->getThis() );
+	ss->addSpiel( weiter );
+	weiter->setAccounts( spielerAnzahl, accounts );
+	weiter->setKlients( spielerAnzahl, klients );
+	weiter->setKarteId( karte );
+	ss->removeSpielErstellt( id ); // delete this
+	zeit->release();
+}
+
+// constant
+int SpielErstellt::getId() const
+{
+	return id;
+}
+
+// Reference Counting
+SpielErstellt *SpielErstellt::getThis()
+{
+	ref++;
+	return this;
+}
+
+SpielErstellt *SpielErstellt::release()
+{
+	ref--;
+	if( !ref )
+		delete this;
+	return 0;
+}
+
+// Inhalt der SpielFinden Klasse aus SpielErstellt.h
+// Konstruktor
+SpielFinden::SpielFinden( SpielServer *ss )
+: Thread()
+{
+	this->ss = ss;
+	end = 0;
+	spielServerId = 0;
+	ref = 1;
+}
+
+// Destruktor
+SpielFinden::~SpielFinden()
+{
+	end = 1;
+	warteAufThread( 2000 );
+}
+
+// nicht constant
+void SpielFinden::setEnde()
+{
+	end = 1;
+}
+
+void SpielFinden::setSpielServerId( int id )
+{
+	spielServerId = id;
+}
+
+void SpielFinden::thread()
+{
+	end = 0;
+	while( !end )
+	{
+		for( int i = 0; i < 10 && !end; i++ )
+			Sleep( 1000 );
+		if( end )
+			break;
+		int ret = ss->zDB()->erstelleSpiel( spielServerId );
+		if( !ret )
+		{ // erfolg
+			int id = ss->zDB()->getSpielErstelltId( spielServerId );
+			SpielErstellt *erstellt = new SpielErstellt( id, ss->getThis() );
+			ss->addSpielErstellt( erstellt );
+			erstellt->sendeVerbindungsBefehl();
+			ss->zDB()->deleteSpielErstelltNext( spielServerId );
+		}
+	}
+	run = 0;
+	end = 0;
+}
+
+// constant
+
+// Reference Counting
+SpielFinden *SpielFinden::getThis()
+{
+	ref++;
+	return this;
+}
+
+SpielFinden *SpielFinden::release()
+{
+	ref--;
+	if( !ref )
+		delete this;
+	return 0;
+}

+ 76 - 0
SpielServer/SpielErstellt.h

@@ -0,0 +1,76 @@
+#ifndef SpielErstellt_H
+#define SpielErstellt_H
+
+#include <Klient.h>
+#include <Thread.h>
+#include <Array.h>
+
+using namespace Framework;
+using namespace Network;
+
+class SSKlient;
+struct SpielerTeamStruktur;
+class SpielServer;
+
+class SpielErstellt : public Thread
+{
+private:
+	SpielServer *ss;
+	int id;
+	int spielArt;
+	int karte;
+	int spielerAnzahl;
+	int verbunden;
+	Array< int > *accounts;
+	RCArray< SSKlient > *klients;
+	Array< int > *status;
+	int state;
+	bool abbr;
+	int spielId;
+	int ref;
+
+public:
+	// Konstruktor
+	SpielErstellt( int id, SpielServer *ss );
+	// Destruktor
+	virtual ~SpielErstellt();
+	// nicht constant
+	void abbruch();
+	void sendeVerbindungsBefehl();
+	bool klientVerbunden( SSKlient *klient );
+	bool klientNimmtAn( int accountId );
+	bool klientLehntAb( int accountId );
+	bool klientGetrennt( SSKlient *zKlient );
+	virtual void thread();
+	// constant
+	int getId() const;
+	// Reference Counting
+	SpielErstellt *getThis();
+	SpielErstellt *release();
+};
+
+class SpielFinden : public Thread
+{
+private:
+	SpielServer *ss;
+	bool end;
+	int spielServerId;
+	int ref;
+
+public:
+	// Konstruktor
+	SpielFinden( SpielServer *ss );
+	// Destruktor
+	virtual ~SpielFinden();
+	// nicht constant
+	void setEnde();
+	void setSpielServerId( int id );
+	virtual void thread();
+	// constant
+
+	// Reference Counting
+	SpielFinden *getThis();
+	SpielFinden *release();
+};
+
+#endif

+ 40 - 0
SpielServer/SpielKlasse.h

@@ -0,0 +1,40 @@
+#ifndef SpielKlasse_H
+#define SpielKlasse_H
+
+#include <Server.h>
+#include <Thread.h>
+#include <Array.h>
+
+using namespace Framework;
+class SSDatenbankV;
+class SSKlientV;
+class StatistikV;
+
+class SpielKlasse
+{
+private:
+
+public:
+	virtual ~SpielKlasse()
+	{
+	}
+	// nicht constant
+	virtual void setPSQLK( SSDatenbankV *psqldb ) = 0;
+	virtual void setSpielId( int id ) = 0;
+    virtual void setKarteId( int karteId ) = 0;
+    virtual void setTempPfad( char *pfad ) = 0;
+	virtual void setAccounts( int anzahl, Array< int > *zAccounts ) = 0;
+	virtual void setKlients( int anzahl, RCArray< SSKlientV > *zKlients ) = 0;
+	virtual void setSpielerNummern( int anzahl, Array< int > *spielerNummern ) = 0;
+	virtual void klientOffline( int accountId ) = 0;
+	virtual void klientOnline( int accountId, SSKlientV *zKlient ) = 0;
+	virtual void nachricht( int accountId, int len, char *bytes ) = 0;
+	virtual void run() = 0;
+	// constant
+	virtual StatistikV *getStatistik() const = 0;
+	// Reference Counting 
+	virtual SpielKlasse *getThis() = 0;
+	virtual SpielKlasse *release() = 0;
+};
+
+#endif

+ 1803 - 0
SpielServer/SpielServer.cpp

@@ -0,0 +1,1803 @@
+#include "SpielServer.h"
+#include <iostream>
+#include <Zeit.h>
+#include <Klient.h>
+#include <Globals.h>
+#ifdef WIN32
+#include "..\Datenbank\Datenbank.h"
+#else
+#include "Datenbank.h"
+#endif
+
+// Inhalt der SpielServer Klasse aus SpielServer.h
+// Konstruktor 
+SpielServer::SpielServer( InitDatei *zIni )
+: Thread()
+{
+	Network::Start( 100 );
+	std::cout << "SS: Verbindung mit Datenbank wird hergestellt...\n";
+	db = new SSDatenbank( zIni );
+	empfangen = 0;
+	gesendet = 0;
+	fehler = new Text();
+	ini = zIni->getThis();
+	id = *zIni->zWert( "ServerId" );
+	server = new Server();
+	aServer = new Server();
+	std::cout << "SS: Starten des Admin Servers...\n";
+	if( !aServer->verbinde( (unsigned short)TextZuInt( ini->zWert( "AdminServerPort" )->getText(), 10 ), 10 ) )
+	{
+		std::cout << "SS: Der Admin Server konnte nicht gestartet werden. Das Programm wird beendet.\n";
+		exit( 1 );
+	}
+	db->setServerStatus( id, 2 );
+	end = 0;
+	nichtPausiert = 0;
+	InitializeCriticalSection( &cs );
+	ref = 1;
+    startSpielThread = new SpielFinden( this );
+	if( zIni->zWert( "Aktiv" )->istGleich( "TRUE" ) )
+	{
+		serverStarten();
+		serverFortsetzen();
+	}
+	erstellt = new RCArray< SpielErstellt >();
+	spiele = new RCArray< Spiel >();
+	klients = new RCArray< SSKlient >();
+	spielHistorieId = new Array< int >();
+	spielErstelltAnzahl = 0;
+	spielAnzahl = 0;
+	klientAnzahl = 0;
+	klientAnzahl2 = 0;
+	historieS = new HistorieSender( this );
+	historieS->start();
+}
+
+// Destruktor 
+SpielServer::~SpielServer()
+{
+	historieS->setEnde();
+	historieS->warteAufThread( 20000 );
+	historieS->ende();
+	historieS->release();
+	fehler->release();
+	server->trenne();
+	server->release();
+	aServer->trenne();
+	aServer->release();
+	ini->release();
+	db->release();
+	DeleteCriticalSection( &cs );
+	startSpielThread->release();
+	erstellt->release();
+	spiele->release();
+	if( klients )
+		klients->release();
+	spielHistorieId->release();
+}
+
+// nicht constant
+void SpielServer::lock()
+{
+	EnterCriticalSection( &cs );
+}
+
+void SpielServer::unlock()
+{
+	LeaveCriticalSection( &cs );
+}
+
+void SpielServer::runn()
+{
+	while( !end )
+	{
+		SKlient *klient;
+		klient = aServer->getKlient();
+		if( end && klient )
+		{
+			klient->trenne();
+			klient = klient->release();
+			Sleep( 1000 );
+			return;
+		}
+		if( !klient )
+			return;
+		SSAKlient *slHandle = new SSAKlient( klient, getThis() );
+		slHandle->start();
+	}
+}
+
+void SpielServer::thread()
+{
+	while( 1 )
+	{
+		SKlient *klient;
+		klient = server->getKlient();
+		if( !klient )
+			break;
+		Framework::getThreadRegister()->cleanUpClosedThreads();
+		SSKlient *slHandle = new SSKlient( klient, getThis() );
+		klientAnzahl2++;
+		slHandle->start();
+	}
+}
+
+void SpielServer::close()
+{
+	db->setServerStatus( id, 1 );
+	server->trenne();
+#ifdef WIN32
+	warteAufThread( 1000 );
+#endif
+	lock();
+	for( int i = 0; i < klientAnzahl; i++ )
+		klients->z( i )->absturz();
+	if( klients )
+		 klients = klients->release();
+	klientAnzahl = 0;
+	unlock();
+	ende();
+	run = 0;
+	end = 1;
+	Klient *klient = new Klient();
+	klient->verbinde( aServer->getPort(), "127.0.0.1" );
+	Sleep( 500 );
+	aServer->trenne();
+	klient->release();
+}
+
+bool SpielServer::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();
+		startSpielThread->setSpielServerId( id );
+		startSpielThread->start();
+		return 1;
+	}
+	else
+	{
+		serverBeenden();
+		fehler->setText( "Der Server konnte nicht gestartet werden: Eventuell ist der Port in benutzung." );
+		return 0;
+	}
+}
+
+bool SpielServer::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 SpielServer::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 SpielServer::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;
+	}
+	startSpielThread->setEnde();
+	startSpielThread->warteAufThread( 2000 );
+	startSpielThread->ende();
+	nichtPausiert = 0;
+	ende();
+	if( server )
+		server->trenne();
+	return 1;
+}
+
+bool SpielServer::setMaxSpiele( int ms )
+{
+	if( !db->setMaxSpiele( id, ms ) )
+	{
+		fehler->setText( "Die maximale Anzahl der Spiele konnte nicht gesetzt werden:\n" );
+		fehler->append( db->getLetzterFehler() );
+		return 0;
+	}
+	ini->setWert( "MaxSpiele", Text() += ms );
+	return 1;
+}
+
+void SpielServer::addSpielErstellt( SpielErstellt *erstellt )
+{
+	lock();
+	this->erstellt->set( erstellt, spielErstelltAnzahl );
+	spielErstelltAnzahl++;
+	unlock();
+}
+
+void SpielServer::SpielErstelltAbbruch( int spielErstelltId )
+{
+	lock();
+	for( int i = 0; i < spielErstelltAnzahl; i++ )
+	{
+		if( erstellt->z( i )->getId() == spielErstelltId )
+		{
+			erstellt->z( i )->abbruch();
+			break;
+		}
+	}
+	unlock();
+}
+
+void SpielServer::removeSpielErstellt( int id )
+{
+	lock();
+	bool gefunden = 0;
+	for( int i = 0; i < spielErstelltAnzahl; i++ )
+	{
+		if( erstellt->z( i )->getId() == id )
+		{
+			spielErstelltAnzahl--;
+			SpielErstellt *zse = erstellt->get( i );
+			erstellt->remove( i );
+			unlock();
+			zse->release();
+			gefunden = 1;
+			break;
+		}
+	}
+	if( !gefunden )
+		unlock();
+}
+
+bool SpielServer::registerKlient( SSKlient *klient )
+{
+	lock();
+	bool gefunden = 0;
+	for( int i = 0; i < klientAnzahl; i++ )
+	{
+		SSKlient *tmp = klients->z( i );
+		if( tmp )
+		{
+			if( tmp->getAccountId() == klient->getAccountId() )
+			{
+				klient->getThis();
+				tmp->setSenden( klient );
+				klient->release();
+				gefunden = 1;
+				unlock();
+				return 1;
+			}
+		}
+	}
+	if( !gefunden )
+	{
+		klients->set( klient, klientAnzahl );
+		klientAnzahl++;
+	}
+	unlock();
+	return 0;
+}
+
+bool SpielServer::absturzKlient( int klientId )
+{
+	lock();
+	SSKlient *zKlient = 0;
+	for( int i = 0; i < klientAnzahl; i++ )
+	{
+		if( klients->z( i )->getKlientNummer() == klientId )
+		{
+			zKlient = klients->z( i );
+			break;
+		}
+	}
+	if( !zKlient )
+	{
+		unlock();
+		return 0;
+	}
+	int id = 0;
+	int ak = db->getAktionForKlient( this->id, zKlient->getAccountId(), &id );
+	switch( ak )
+	{
+	case 0: // Information Über Verwendung des Klient ist verlorengegangen (überall abmelden)
+		for( int i = 0; i < spielErstelltAnzahl; i++ )
+		{
+			SpielErstellt *tmp = erstellt->z( i );
+			if( tmp )
+				tmp->klientGetrennt( zKlient );
+		}
+		for( int i = 0; i < spielAnzahl; i++ )
+		{
+			Spiel *tmp = spiele->z( i );
+			if( tmp )
+				tmp->klientGetrennt( zKlient );
+		}
+		break;
+	case 1: // Spiel Erstellt
+		for( int i = 0; i < spielErstelltAnzahl; i++ )
+		{
+			SpielErstellt *tmp = erstellt->z( i );
+			if( tmp )
+			{
+				if( tmp->getId() == id )
+				{
+					tmp->klientGetrennt( zKlient );
+					break;
+				}
+			}
+		}
+		break;
+	case 2: // Spielt
+		for( int i = 0; i < spielAnzahl; i++ )
+		{
+			Spiel *tmp = spiele->z( i );
+			if( tmp && tmp->getId() == id )
+			{
+				tmp->klientGetrennt( zKlient );
+				break;
+			}
+		}
+		break;
+	}
+	bool gefunden = 0;
+	for( int i = 0; i < klientAnzahl; i++ )
+	{
+		if( klients->z( i ) == zKlient )
+		{
+			zKlient->absturz();
+			klientAnzahl--;
+			zKlient->getThis();
+			klients->remove( i );
+			unlock();
+			zKlient->release();
+			gefunden = 1;
+			break;
+		}
+	}
+	if( !gefunden )
+		unlock();
+	return 1;
+}
+
+bool SpielServer::verteileKlient( SSKlient *klient )
+{
+	lock();
+	int id = 0;
+	int ak = db->getAktionForKlient( this->id, klient->getAccountId(), &id );
+	switch( ak )
+	{
+	case 0: // Keine Verwendung für den Klient
+		unlock();
+		return 0;
+		break;
+	case 1: // Spiel Erstellt
+		for( int i = 0; i < spielErstelltAnzahl; i++ )
+		{
+			SpielErstellt *tmp = erstellt->z( i );
+			if( tmp )
+			{
+				if( tmp->getId() == id )
+				{
+					tmp->klientVerbunden( (SSKlient*)klient->getThis() );
+					unlock();
+					return 1;
+				}
+			}
+		}
+		break;
+	case 2: // Spielt
+		for( int i = 0; i < spielAnzahl; i++ )
+		{
+			Spiel *tmp = spiele->z( i );
+			if( tmp )
+			{
+				if( tmp->getId() == id )
+				{
+					tmp->klientVerbunden( (SSKlient*)klient->getThis() );
+					unlock();
+					return 1;
+				}
+			}
+		}
+		break;
+	}
+	unlock();
+	return 0;
+}
+
+void SpielServer::unregisterKlient( SSKlient *zKlient )
+{
+	lock();
+	int id = 0;
+	int ak = db->getAktionForKlient( this->id, zKlient->getAccountId(), &id );
+	switch( ak )
+	{
+	case 0: // Information Über Verwendung des Klient ist verlorengegangen (überall abmelden)
+		for( int i = 0; i < spielErstelltAnzahl; i++ )
+		{
+			SpielErstellt *tmp = erstellt->z( i );
+			if( tmp )
+				tmp->klientGetrennt( zKlient );
+		}
+		for( int i = 0; i < spielAnzahl; i++ )
+		{
+			Spiel *tmp = spiele->z( i );
+			if( tmp )
+				tmp->klientGetrennt( zKlient );
+		}
+		break;
+	case 1: // Spiel Erstellt
+		for( int i = 0; i < spielErstelltAnzahl; i++ )
+		{
+			SpielErstellt *tmp = erstellt->z( i );
+			if( tmp )
+			{
+				if( tmp->getId() == id )
+				{
+					tmp->klientGetrennt( zKlient );
+					break;
+				}
+			}
+		}
+		break;
+	case 2: // Spielt
+		for( int i = 0; i < spielAnzahl; i++ )
+		{
+			Spiel *tmp = spiele->z( i );
+			if( tmp && tmp->getId() == id )
+			{
+				tmp->klientGetrennt( zKlient );
+				break;
+			}
+		}
+		break;
+	}
+	bool gefunden = 0;
+	for( int i = 0; i < klientAnzahl; i++ )
+	{
+		if( klients->z( i ) == zKlient )
+		{
+			klientAnzahl--;
+			zKlient->getThis();
+			klients->remove( i );
+			unlock();
+			zKlient->release();
+			gefunden = 1;
+			break;
+		}
+	}
+	if( !gefunden )
+	{
+		unlock();
+		zKlient->release();
+	}
+}
+
+void SpielServer::klientsMM( SSKlient *k )
+{
+	lock();
+	for( int i = 0; i < klientAnzahl; i++ )
+	{
+		if( klients->z( i ) == k )
+		{
+			klients->z( i )->getThis();
+			klients->z( i )->getThis();
+			klients->remove( i );
+		}
+	}
+	unlock();
+	klientAnzahl2--;
+}
+
+void SpielServer::addSpiel( Spiel *spiel )
+{
+	lock();
+	spiele->add( spiel, spielAnzahl );
+	spielAnzahl++;
+	unlock();
+}
+
+void SpielServer::removeSpiel( int spielId )
+{
+	lock();
+	bool gefunden = 0;
+	for( int i = 0; i < spielAnzahl; i++ )
+	{
+		if( spiele->z( i ) && spiele->z( i )->getId() == spielId )
+		{
+			spielAnzahl--;
+			Spiel *zs = spiele->get( i );
+			spiele->remove( i );
+			unlock();
+			zs->release();
+			gefunden = 1;
+			break;
+		}
+	}
+	if( !gefunden )
+		unlock();
+}
+
+void SpielServer::addGesendet( int bytes )
+{
+	gesendet += bytes;
+}
+
+void SpielServer::addEmpfangen( int bytes )
+{
+	empfangen += bytes;
+}
+
+void SpielServer::addSpielHistorieId( int id )
+{
+	lock();
+	spielHistorieId->add( id );
+	unlock();
+}
+
+bool SpielServer::hatSpielHistorieId( int id )
+{
+	bool ret = 0;
+	lock();
+	int anz = spielHistorieId->getEintragAnzahl();
+	for( int i = 0; i < anz; i++ )
+	{
+		if( spielHistorieId->hat( i ) && spielHistorieId->get( i ) == id )
+		{
+			ret = 1;
+			break;
+		}
+	}
+	unlock();
+	return ret;
+}
+
+void SpielServer::removeSpielHistorieId( int id )
+{
+	lock();
+	int anz = spielHistorieId->getEintragAnzahl();
+	for( int i = 0; i < anz; i++ )
+	{
+		if( spielHistorieId->hat( i ) && spielHistorieId->get( i ) == id )
+		{
+			spielHistorieId->remove( i );
+			break;
+		}
+	}
+	unlock();
+}
+
+// constant
+bool SpielServer::istAn() const
+{
+	return db->serverIstNichtPausiert( id );
+}
+
+Server *SpielServer::zServer() const
+{
+	return server;
+}
+
+SSDatenbank *SpielServer::zDB() const
+{
+	return db;
+}
+
+InitDatei *SpielServer::zInit() const
+{
+    return ini;
+}
+
+bool SpielServer::hatClients() const
+{
+	return klientAnzahl > 0;
+}
+
+int SpielServer::getId() const
+{
+	return id;
+}
+
+char *SpielServer::getLetzterFehler() const
+{
+	return fehler->getText();
+}
+
+char *SpielServer::getIp() const
+{
+	return ini->zWert( "ServerIp" )->getText();
+}
+
+int SpielServer::getPort() const
+{
+	if( !ini->wertExistiert( "ServerPort" ) )
+		return 0;
+	return TextZuInt( ini->zWert( "ServerPort" )->getText(), 10 );
+}
+
+// Reference Counting
+SpielServer *SpielServer::getThis()
+{
+	ref++;
+	return this;
+}
+
+SpielServer *SpielServer::release()
+{
+	ref--;
+	if( !ref )
+		delete this;
+	return 0;
+}
+
+
+// Inhalt der SSAKlient Klasse aus SpielServer.h
+// Konstruktor 
+SSAKlient::SSAKlient( SKlient *klient, SpielServer *ss )
+: Thread()
+{
+	this->klient = klient;
+	unsigned char key[ 20 ] = { 148, 52, 231, 50, 20, 138, 243, 178, 149, 24, 69, 60, 68, 116, 10, 161, 178, 148, 32, 212 };
+	klient->setSendeKey( (char*)key, 20 );
+	klient->setEmpfangKey( (char*)key, 20 );
+	name = new Text( "" );
+	passwort = new Text( "" );
+	adminId = 0;
+	version = 0;
+	this->ss = ss;
+}
+
+// Destruktor 
+SSAKlient::~SSAKlient()
+{
+	klient->trenne();
+	klient->release();
+	ss->release();
+	name->release();
+	passwort->release();
+}
+
+// nicht constant 
+void SSAKlient::thread()
+{
+	while( 1 )
+	{
+		char c = 0;
+		if( !klient->getNachrichtEncrypted( &c, 1 ) )
+			break;
+		else
+		{
+			bool br = 0;
+			switch( c )
+			{
+			case 1: // Login
+				if( 1 )
+				{
+					klient->sendeEncrypted( "\1", 1 );
+					char nLen = 0;
+					klient->getNachrichtEncrypted( &nLen, 1 );
+					char *n = new char[ nLen + 1 ];
+					n[ (int)nLen ] = 0;
+					if( nLen )
+						klient->getNachrichtEncrypted( n, nLen );
+					char pLen = 0;
+					klient->getNachrichtEncrypted( &pLen, 1 );
+					char *p = new char[ pLen + 1 ];
+					p[ (int)pLen ] = 0;
+					if( pLen )
+						klient->getNachrichtEncrypted( p, pLen );
+					int adminId = ss->zDB()->istAdministrator( n, p );
+					if( adminId )
+					{
+						klient->sendeEncrypted( "\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->sendeEncrypted( "\1", 1 );
+				break;
+			case 3: // Trennen
+				br = 1;
+				klient->sendeEncrypted( "\1", 1 );
+				break;
+			case 4: // Server starten
+				if( !adminId )
+					errorZuKlient( "Du musst dich einloggen." );
+				else
+				{
+					if( ss->zDB()->adminHatRecht( adminId, Admin_Recht::SSStarten ) )
+					{
+						if( !ss->serverStarten() )
+						{
+							Text *err = new Text();
+							err->append( ss->getLetzterFehler() );
+							errorZuKlient( err->getText() );
+							err->release();
+						}
+						else
+							klient->sendeEncrypted( "\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( ss->zDB()->adminHatRecht( adminId, Admin_Recht::SSBeenden ) )
+					{
+						if( ss->serverBeenden() )
+							klient->sendeEncrypted( "\1", 1 );
+						else
+						{
+							Text *err = new Text();
+							err->append( ss->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( ss->isRunning() )
+					{
+						if( ss->zDB()->adminHatRecht( adminId, Admin_Recht::SSBeenden ) )
+						{
+							if( ss->serverBeenden() )
+								ok = 1;
+							else
+							{
+								Text *err = new Text();
+								err->append( ss->getLetzterFehler() );
+								errorZuKlient( err->getText() );
+								err->release();
+							}
+						}
+						else
+							errorZuKlient( "Du bist nicht berechtigt den Server zu beenden." );
+					}
+					else
+						ok = 1;
+					if( ok && ss->hatClients() )
+					{
+						errorZuKlient( "Es sind noch Klients Online. Bitte versuche es später erneut." );
+						break;
+					}
+					if( ok )
+					{
+						klient->sendeEncrypted( "\1", 1 );
+						std::cout << "SS: Der Server wird von Benutzer " << adminId << " heruntergefahren.\n";
+						ss->close();
+						br = 1;
+					}
+				}
+				break;
+			case 7: // Progtamm abstürzen
+				if( !adminId )
+					errorZuKlient( "Du musst dich einloggen." );
+				else
+				{
+					bool ok = 0;
+					if( ss->isRunning() )
+					{
+						if( ss->zDB()->adminHatRecht( adminId, Admin_Recht::SSBeenden ) )
+						{
+							ss->serverBeenden();
+							ok = 1;
+						}
+						else
+							errorZuKlient( "Du bist nicht berechtigt den Server zu beenden." );
+					}
+					else
+						ok = 1;
+					if( ok )
+					{
+						klient->sendeEncrypted( "\1", 1 );
+						std::cout << "sS: Der Server wurde von Benutzer " << adminId << " terminiert.\n";
+						ss->close();
+						br = 1;
+					}
+				}
+				break;
+			case 8: // Status Frage
+				if( 1 )
+				{
+					char status = 0;
+					if( ss->isRunning() )
+					{
+						status = 1;
+						if( ss->istAn() )
+							status = 2;
+					}
+					klient->sendeEncrypted( "\1", 1 );
+					klient->sendeEncrypted( &status, 1 );
+				}
+				break;
+			case 9: // Server pausieren
+				if( !adminId )
+					errorZuKlient( "Du musst dich einloggen." );
+				else
+				{
+					klient->sendeEncrypted( "\1", 1 );
+					char pause = 0;
+					klient->getNachrichtEncrypted( &pause, 1 );
+					if( ss->zDB()->adminHatRecht( adminId, Admin_Recht::SSPausieren ) )
+					{
+						bool ok = 0;
+						if( pause )
+							ok = ss->serverPause();
+						else
+							ok = ss->serverFortsetzen();
+						if( ok )
+							klient->sendeEncrypted( "\1", 1 );
+						else
+						{
+							Text *err = new Text();
+							err->append( ss->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 Spiele setzen
+				if( !adminId )
+					errorZuKlient( "Du musst dich einloggen." );
+				else
+				{
+					klient->sendeEncrypted( "\1", 1 );
+					int maxS = 0;
+					klient->getNachrichtEncrypted( (char*)&maxS, 4 );
+					if( ss->zDB()->adminHatRecht( adminId, Admin_Recht::SSMSChange ) )
+					{
+						if( ss->setMaxSpiele( maxS ) )
+							klient->sendeEncrypted( "\1", 1 );
+						else
+						{
+							Text *err = new Text();
+							err->append( ss->getLetzterFehler() );
+							errorZuKlient( err->getText() );
+							err->release();
+						}
+					}
+					else
+						errorZuKlient( "Du bist nicht berechtigt die maximale Anzahl der Clients zu verändern." );
+				}
+				break;
+			case 0xB: // Spiel Historie downloaden
+				if( adminId )
+					errorZuKlient( "Zugriff verweigert." );
+				else
+				{
+					klient->sendeEncrypted( "\1", 1 );
+					int spielId = 0;
+					klient->getNachrichtEncrypted( (char*)&spielId, 4 );
+					if( !ss->hatSpielHistorieId( spielId ) )
+					{
+						errorZuKlient( "Zugriff auf Spiel-Historie verweigert." );
+						break;
+					}
+					Text *pfad = new Text( "../spiel log/" );
+					*pfad += spielId;
+					*pfad += "/fertig";
+					if( !DateiExistiert( *pfad ) )
+					{
+						pfad->release();
+						errorZuKlient( "Die Spiel-Historie wurde nicht gefunden." );
+						break;
+					}
+					klient->sendeEncrypted( "\1", 1 );
+					pfad->remove( "/fertig" );
+					sendeVerzeichnisAnKlient( *pfad, pfad->getLength() + 1 );
+					pfad->release();
+					klient->sendeEncrypted( "\0", 1 );
+				}
+				break;
+            case 0xC: // klient absturtz
+                if( 1 )
+                {
+                    klient->sendeEncrypted( "\1", 1 );
+                    int klientId = 0;
+                    klient->getNachrichtEncrypted( (char*)&klientId, 4 );
+                    if( klientId && ss->absturzKlient( klientId ) )
+                        klient->sendeEncrypted( "\1", 1 );
+                    else
+                        klient->sendeEncrypted( "\0", 1 );
+                }
+                break;
+			default:
+				errorZuKlient( "Unbekannte Nachricht!" );
+				break;
+			}
+			if( br )
+				break;
+			ss->addEmpfangen( klient->getDownloadBytes( 1 ) );
+			ss->addGesendet( klient->getUploadBytes( 1 ) );
+		}
+	}
+	ss->addEmpfangen( klient->getDownloadBytes( 1 ) );
+	ss->addGesendet( klient->getUploadBytes( 1 ) );
+	delete this;
+}
+
+void SSAKlient::sendeVerzeichnisAnKlient( char *pfad, int gpl )
+{
+	Datei *d = new Datei();
+	d->setDatei( pfad );
+	if( d->istOrdner() )
+	{
+		int dAnz = d->getUnterdateiAnzahl();
+		RCArray< Text > *list = d->getDateiListe();
+		for( int i = 0; i < dAnz; i++ )
+		{
+			if( list->z( i ) )
+			{
+				Text *pf = new Text( pfad );
+				pf->append( "/" );
+				pf->append( list->z( i )->getText() );
+				sendeVerzeichnisAnKlient( *pf, gpl );
+				pf->release();
+			}
+		}
+		list->release();
+	}
+	else if( d->existiert() )
+	{
+		__int64 gr = d->getSize();
+		if( gr && d->zPfad()->getLength() - gpl > 0 && d->open( Datei::Style::lesen ) )
+		{
+			char pfLen = (char)( d->zPfad()->getLength() - gpl );
+			klient->sendeEncrypted( &pfLen, 1 );
+			klient->sendeEncrypted( d->zPfad()->getText() + gpl, pfLen );
+			klient->sendeEncrypted( (char*)&gr, 8 );
+			char *bytes = new char[ 2048 ];
+			while( gr )
+			{
+				short len = gr > 2048 ? 2048 : (short)gr;
+				d->lese( bytes, len );
+				klient->sende( bytes, len );
+				gr -= len;
+			}
+			delete[] bytes;
+			d->close();
+		}
+	}
+	d->release();
+}
+
+void SSAKlient::errorZuKlient( const char *nachricht ) const // sendet eine Fehlernachricht zum Klient
+{
+	klient->sendeEncrypted( "\3", 1 );
+	char len = (char)textLength( nachricht );
+	klient->sendeEncrypted( &len, 1 );
+	klient->sendeEncrypted( nachricht, len );
+}
+
+
+// Inhalt der SSKlient Klasse aus SpielServer.h
+// Konstruktor 
+SSKlient::SSKlient( SKlient *klient, SpielServer *ss )
+: SSKlientV()
+{
+	empfangen = klient;
+	unsigned char key[ 20 ] = { 253, 234, 211, 132, 121, 230, 95, 145, 201, 13, 43, 77, 153, 223, 253, 69, 234, 43, 52, 99 };
+	klient->setSendeKey( (char*)key, 20 );
+	klient->setEmpfangKey( (char*)key, 20 );
+	senden = 0;
+	this->ss = ss;
+	accountId = 0;
+	klientNummer = 0;
+	termThread = 1;
+	verbunden = 0;
+	zErstellt = 0;
+	zSpiel = 0;
+	InitializeCriticalSection( &cs );
+	ref = 1;
+}
+
+// Destruktor 
+SSKlient::~SSKlient()
+{
+	lock();
+	unlock();
+	if( verbunden )
+		trenne();
+	if( termThread )
+	{
+		if( verbunden )
+			warteAufThread( 1000 );
+		if( verbunden )
+		{
+			if( empfangen )
+				empfangen->trenne();
+			if( senden )
+				senden->trenne();
+		}
+		if( empfangen )
+			empfangen->release();
+		if( senden )
+			senden->release();
+		DeleteCriticalSection( &cs );
+		ss->klientsMM( this );
+		ss->release();
+		ende(); // Eventuelles Ende des Aktuellen Threades
+	}
+	else
+	{
+		if( verbunden )
+		{
+			if( empfangen )
+				empfangen->trenne();
+			if( senden )
+				senden->trenne();
+		}
+		if( empfangen )
+			empfangen->release();
+		if( senden )
+			senden->release();
+		DeleteCriticalSection( &cs );
+		ss->klientsMM( this );
+		ss->release();
+	}
+}
+
+// nicht constant
+void SSKlient::lock()
+{
+	EnterCriticalSection( &cs );
+}
+
+void SSKlient::unlock()
+{
+	LeaveCriticalSection( &cs );
+}
+
+void SSKlient::absturz()
+{
+	ende();
+	if( senden )
+		senden->trenne();
+	empfangen->trenne();
+}
+
+void SSKlient::setSpielErstellt( SpielErstellt *zErstellt )
+{
+	this->zErstellt = zErstellt;
+}
+
+void SSKlient::setSpiel( Spiel *zSpiel )
+{
+	this->zSpiel = zSpiel;
+}
+
+void SSKlient::nichtTrennen()
+{
+	verbunden = 0;
+}
+
+void SSKlient::spielGefunden( int karteId )
+{
+	if( !senden )
+		return;
+	lock();
+	senden->sendeEncrypted( "\xB", 1 );
+	senden->sendeEncrypted( (char*)&karteId, 4 );
+	unlock();
+	ss->addEmpfangen( senden->getDownloadBytes( 1 ) );
+	ss->addGesendet( senden->getUploadBytes( 1 ) );
+}
+
+void SSKlient::zeitVerbleibend( char sekunden )
+{
+	if( !senden )
+		return;
+	lock();
+	senden->sendeEncrypted( "\1", 1 );
+	senden->sendeEncrypted( &sekunden, 1 );
+	unlock();
+	ss->addEmpfangen( senden->getDownloadBytes( 1 ) );
+	ss->addGesendet( senden->getUploadBytes( 1 ) );
+}
+
+void SSKlient::erstellungAbgebrochen( char *grund )
+{
+	if( !senden )
+		return;
+	char len = (char)textLength( grund );
+	lock();
+	senden->sendeEncrypted( "\2", 1 );
+	senden->sendeEncrypted( &len, 1 );
+	if( len )
+		senden->sendeEncrypted( grund, len );
+	unlock();
+	ss->addEmpfangen( senden->getDownloadBytes( 1 ) );
+	ss->addGesendet( senden->getUploadBytes( 1 ) );
+}
+
+void SSKlient::backInWarteschlange( char st, char min, char sec )
+{
+	if( !senden )
+		return;
+	lock();
+	senden->sendeEncrypted( "\4", 1 );
+	senden->sendeEncrypted( &st, 1 );
+	senden->sendeEncrypted( &min, 1 );
+	senden->sendeEncrypted( &sec, 1 );
+	unlock();
+	ss->addEmpfangen( senden->getDownloadBytes( 1 ) );
+	ss->addGesendet( senden->getUploadBytes( 1 ) );
+}
+
+void SSKlient::erstellungFortsetzen()
+{
+	if( !senden )
+		return;
+	lock();
+	senden->sendeEncrypted( "\5", 1 );
+	unlock();
+	ss->addEmpfangen( senden->getDownloadBytes( 1 ) );
+	ss->addGesendet( senden->getUploadBytes( 1 ) );
+}
+
+void SSKlient::erstellungInitialisierung( SpielerTeamStruktur *sts )
+{
+	if( !senden )
+		return;
+	lock();
+	senden->sendeEncrypted( "\6", 1 );
+	senden->sendeEncrypted( (char*)&sts->spielerAnzahl, 4 );
+	senden->sendeEncrypted( (char*)&sts->teamAnzahl, 4 );
+	for( int i = 0; i < sts->spielerAnzahl; i++ )
+	{
+		int f = sts->spielerFarbe->hat( i ) ? sts->spielerFarbe->get( i ) : 0;
+		senden->sendeEncrypted( (char*)&f, 4 );
+	}
+	for( int i = 0; i < sts->teamAnzahl; i++ )
+	{
+		int f = sts->teamFarbe->hat( i ) ? sts->teamFarbe->get( i ) : 0;
+		senden->sendeEncrypted( (char*)&f, 4 );
+	}
+	for( int i = 0; i < sts->teamAnzahl; i++ )
+	{
+		Text *name = sts->teamName->z( i );
+		char len = (char)name->getLength();
+		senden->sendeEncrypted( &len, 1 );
+		if( len )
+			senden->sendeEncrypted( name->getText(), len );
+	}
+	for( int i = 0; i < sts->teamAnzahl; i++ )
+	{
+		int size = sts->teamSize->hat( i ) ? sts->teamSize->get( i ) : 0;
+		senden->sendeEncrypted( (char*)&size, 4 );
+	}
+	unlock();
+	ss->addEmpfangen( senden->getDownloadBytes( 1 ) );
+	ss->addGesendet( senden->getUploadBytes( 1 ) );
+}
+
+void SSKlient::erstellungAddSpieler( int accountId )
+{
+	if( !senden )
+		return;
+	lock();
+	senden->sendeEncrypted( "\7", 1 );
+	senden->sendeEncrypted( (char*)&accountId, 4 );
+	unlock();
+	ss->addEmpfangen( senden->getDownloadBytes( 1 ) );
+	ss->addGesendet( senden->getUploadBytes( 1 ) );
+}
+
+void SSKlient::erstellungRemoveSpieler( int accountId )
+{
+	if( !senden )
+		return;
+	lock();
+	senden->sendeEncrypted( "\x8", 1 );
+	senden->sendeEncrypted( (char*)&accountId, 4 );
+	unlock();
+	ss->addEmpfangen( senden->getDownloadBytes( 1 ) );
+	ss->addGesendet( senden->getUploadBytes( 1 ) );
+}
+
+void SSKlient::erstellungSpielerTeam( int accountId, int spielerNummer )
+{
+	if( !senden )
+		return;
+	lock();
+	senden->sendeEncrypted( "\x9", 1 );
+	senden->sendeEncrypted( (char*)&accountId, 4 );
+	senden->sendeEncrypted( (char*)&spielerNummer, 4 );
+	unlock();
+	ss->addEmpfangen( senden->getDownloadBytes( 1 ) );
+	ss->addGesendet( senden->getUploadBytes( 1 ) );
+}
+
+void SSKlient::erstellungChatNachricht( char *nachricht )
+{
+	if( !senden )
+		return;
+	char len = (char)textLength( nachricht );
+	if( !len )
+		return;
+	lock();
+	senden->sendeEncrypted( "\xA", 1 );
+	senden->sendeEncrypted( &len, 1 );
+	senden->sendeEncrypted( nachricht, len );
+	unlock();
+	ss->addEmpfangen( senden->getDownloadBytes( 1 ) );
+	ss->addGesendet( senden->getUploadBytes( 1 ) );
+}
+
+void SSKlient::spielLadenBeginn()
+{
+	if( !senden )
+		return;
+	lock();
+	senden->sendeEncrypted( "\xC", 1 );
+	unlock();
+	ss->addEmpfangen( senden->getDownloadBytes( 1 ) );
+	ss->addGesendet( senden->getUploadBytes( 1 ) );
+}
+
+void SSKlient::spielLadenSpielerAdd( int accId, int spielerNumer )
+{
+	if( !senden )
+		return;
+	lock();
+	senden->sendeEncrypted( "\xD", 1 );
+	senden->sendeEncrypted( (char*)&accId, 4 );
+	senden->sendeEncrypted( (char*)&spielerNumer, 4 );
+	unlock();
+	ss->addEmpfangen( senden->getDownloadBytes( 1 ) );
+	ss->addGesendet( senden->getUploadBytes( 1 ) );
+}
+
+void SSKlient::spielLadenSetSpielerProzent( int accId, int prozent )
+{
+	if( !senden )
+		return;
+	lock();
+	senden->sendeEncrypted( "\xE", 1 );
+	senden->sendeEncrypted( (char*)&accId, 4 );
+	senden->sendeEncrypted( (char*)&prozent, 4 );
+	unlock();
+	ss->addEmpfangen( senden->getDownloadBytes( 1 ) );
+	ss->addGesendet( senden->getUploadBytes( 1 ) );
+}
+
+void SSKlient::spielLadenSetSpielerPing( int accId, int ping )
+{
+	if( !senden )
+		return;
+	lock();
+	senden->sendeEncrypted( "\xF", 1 );
+	senden->sendeEncrypted( (char*)&accId, 4 );
+	senden->sendeEncrypted( (char*)&ping, 4 );
+	unlock();
+	ss->addEmpfangen( senden->getDownloadBytes( 1 ) );
+	ss->addGesendet( senden->getUploadBytes( 1 ) );
+}
+
+double SSKlient::ping()
+{
+	if( !senden )
+		return 0;
+	ZeitMesser *zeit = new ZeitMesser();
+	char ret = 0;
+	lock();
+	zeit->messungStart();
+	senden->sendeEncrypted( "\x10", 1 );
+	senden->getNachrichtEncrypted( &ret, 1 );
+	zeit->messungEnde();
+	unlock();
+	double retVal = zeit->getSekunden();
+	zeit->release();
+	ss->addEmpfangen( senden->getDownloadBytes( 1 ) );
+	ss->addGesendet( senden->getUploadBytes( 1 ) );
+	return retVal;
+}
+
+void SSKlient::spielLadenFertig()
+{
+	if( !senden )
+		return;
+	lock();
+	senden->sendeEncrypted( "\x11", 1 );
+	unlock();
+	ss->addEmpfangen( senden->getDownloadBytes( 1 ) );
+	ss->addGesendet( senden->getUploadBytes( 1 ) );
+}
+
+void SSKlient::spielNachricht( short len, char *bytes )
+{
+	if( !senden )
+		return;
+	lock();
+	senden->sendeEncrypted( "\x12", 1 );
+	senden->sende( (char*)&len, 2 );
+	senden->sende( bytes, len );
+	unlock();
+	ss->addEmpfangen( senden->getDownloadBytes( 1 ) );
+	ss->addGesendet( senden->getUploadBytes( 1 ) );
+}
+
+void SSKlient::statistikNachricht( short len, char *bytes )
+{
+	if( !senden )
+		return;
+	lock();
+	senden->sendeEncrypted( "\x13", 1 );
+	senden->sendeEncrypted( (char*)&len, 2 );
+	senden->sendeEncrypted( bytes, len );
+	unlock();
+	ss->addEmpfangen( senden->getDownloadBytes( 1 ) );
+	ss->addGesendet( senden->getUploadBytes( 1 ) );
+}
+
+bool SSKlient::keepAlive()
+{
+	if( !senden || !verbunden )
+		return 0;
+	char res = 0;
+	lock();
+	senden->sendeEncrypted( "\x14", 1 );
+	senden->getNachrichtEncrypted( &res, 1 );
+	unlock();
+	return res == 1;
+}
+
+void SSKlient::trenne()
+{
+	if( !verbunden )
+		return;
+	verbunden = 0;
+	if( !senden )
+		return;
+	lock();
+	senden->sendeEncrypted( "\0", 1 );
+	unlock();
+	ss->addEmpfangen( senden->getDownloadBytes( 1 ) );
+	ss->addGesendet( senden->getUploadBytes( 1 ) );
+}
+
+void SSKlient::setSenden( SSKlient *klient )
+{
+	senden = klient->getKlient();
+	Text *key = ss->zDB()->getKlientKey( klientNummer );
+	if( !key )
+	{
+		senden->sendeEncrypted( "\0", 1 );
+		errorZuKlientSende( "Es konnte kein Key ermittelt werden." );
+	}
+	else
+	{
+		senden->sendeEncrypted( "\1", 1 );
+		senden->setEmpfangKey( *key, key->getLength() );
+		senden->setSendeKey( *key, key->getLength() );
+		key->release();
+	}
+	verbunden = 1;
+	if( !ss->verteileKlient( this ) )
+		ss->unregisterKlient( this );
+	klient->nichtTrennen();
+	klient->release();
+	ss->addEmpfangen( senden->getDownloadBytes( 1 ) );
+	ss->addGesendet( senden->getUploadBytes( 1 ) );
+}
+
+void SSKlient::thread()
+{
+	int unbekannt = 0;
+	bool del = 0;
+	while( 1 )
+	{
+		bool br = 0;
+		char message = 0;
+		if( empfangen->getNachrichtEncrypted( &message, 1 ) )
+		{
+			switch( message )
+			{
+			case 1: // Klient Identifikation
+				empfangen->getNachrichtEncrypted( (char*)&klientNummer, 4 );
+				if( !klientNummer )
+					errorZuKlientEmpfang( "Du besitzt noch keine Klient Nummer." );
+				else
+				{
+					accountId = ss->zDB()->getAccountId( klientNummer );
+					termThread = 0;
+					if( ss->registerKlient( this ) )
+						return;
+					termThread = 1; 
+					Text *key = ss->zDB()->getKlientKey( klientNummer );
+					if( !key )
+						errorZuKlientEmpfang( "Es konnte kein Key ermittelt werden." );
+					else
+					{
+						empfangen->sendeEncrypted( "\1", 1 );
+						empfangen->setEmpfangKey( *key, key->getLength() );
+						empfangen->setSendeKey( *key, key->getLength() );
+						key->release();
+					}
+				}
+				break;
+			case 2: // Main / Erhaltung Server message
+				if( 1 )
+				{
+					char befehl = 0;
+					empfangen->getNachrichtEncrypted( &befehl, 1 );
+					switch( befehl )
+					{
+					case 2: // klient absturtz
+						if( 1 )
+						{
+							int klientId = 0;
+							empfangen->getNachrichtEncrypted( (char*)&klientId, 4 );
+							if( klientId && ss->absturzKlient( klientId ) )
+								empfangen->sendeEncrypted( "\1", 1 );
+							else
+								empfangen->sendeEncrypted( "\0", 1 );
+						}
+						break;
+					default:
+						errorZuKlientEmpfang( "Befehl nicht bekannt!" );
+						break;
+					}
+				}
+				break;
+			case 3: // Verbindungsende
+				trenne();
+				empfangen->sendeEncrypted( "\1", 1 );
+				br = 1;
+				break;
+			case 4: // SpielErstellt annehmen
+				if( zErstellt )
+				{
+					if( zErstellt->klientNimmtAn( accountId ) )
+						empfangen->sendeEncrypted( "\1", 1 );
+					else
+					{
+						empfangen->sendeEncrypted( "\0", 1 );
+						errorZuKlientSende( "Es ist ein unbekannter Fehler aufgetreten." );
+					}
+				}
+				else
+				{
+					empfangen->sendeEncrypted( "\0", 1 );
+					errorZuKlientSende( "Dir wurde kein erstelltes Spiel zugeteilt." );
+				}
+				break;
+			case 5: // SpielErstellt ablehnen
+				if( zErstellt )
+				{
+					if( zErstellt->klientLehntAb( accountId ) )
+						empfangen->sendeEncrypted( "\1", 1 );
+					else
+					{
+						empfangen->sendeEncrypted( "\0", 1 );
+						errorZuKlientSende( "Es ist ein unbekannter Fehler aufgetreten." );
+					}
+				}
+				else
+				{
+					empfangen->sendeEncrypted( "\0", 1 );
+					errorZuKlientSende( "Dir wurde kein erstelltes Spiel zugeteilt." );
+				}
+				break;
+			case 6: // SpielErstellt team wechseln
+				if( zSpiel )
+				{
+					empfangen->sendeEncrypted( "\1", 1 );
+					int team = 0;
+					empfangen->getNachrichtEncrypted( (char*)&team, 4 );
+					if( zSpiel->klientWechseltTeam( accountId, team ) )
+						empfangen->sendeEncrypted( "\1", 1 );
+					else
+					{
+						empfangen->sendeEncrypted( "\0", 1 );
+						errorZuKlientSende( "Das Team Ist bereits voll." );
+					}
+				}
+				else
+				{
+					empfangen->sendeEncrypted( "\0", 1 );
+					errorZuKlientSende( "Dir wurde kein erstelltes Spiel zugeteilt." );
+				}
+				break;
+			case 7: // SpielErstellt chat Nachricht
+				if( zSpiel )
+				{
+					empfangen->sendeEncrypted( "\1", 1 );
+					char len = 0;
+					empfangen->getNachrichtEncrypted( &len, 1 );
+					char *nachricht = new char[ len + 1 ];
+					nachricht[ (int)len ] = 0;
+					if( len )
+						empfangen->getNachrichtEncrypted( nachricht, len );
+					Text *msg = ss->zDB()->getAccountRufName( accountId );
+					msg->append( ": " );
+					msg->append( nachricht );
+					delete[] nachricht;
+					if( zSpiel->chatNachricht( msg->getText() ) )
+						empfangen->sendeEncrypted( "\1", 1 );
+					else
+					{
+						empfangen->sendeEncrypted( "\0", 1 );
+						errorZuKlientSende( "Es ist ein unbekannter Fehler aufgetreten." );
+					}
+					msg->release();
+				}
+				else
+				{
+					empfangen->sendeEncrypted( "\0", 1 );
+					errorZuKlientSende( "Dir wurde kein erstelltes Spiel zugeteilt." );
+				}
+				break;
+			case 8: // Server Message
+				if( 1 )
+				{
+					char befehl = 0;
+					empfangen->getNachrichtEncrypted( &befehl, 1 );
+					switch( befehl )
+					{
+					case 0: // Verbindung Trennen
+						empfangen->sendeEncrypted( "\1", 1 );
+						br = 1;
+						del = 1;
+						break;
+					case 1: // Spiel Erstellen Abbrechen
+						if( 1 )
+						{
+							empfangen->sendeEncrypted( "\1", 1 );
+							int spielErstelltId = 0;
+							empfangen->getNachrichtEncrypted( (char*)&spielErstelltId, 4 );
+							ss->SpielErstelltAbbruch( spielErstelltId );
+							empfangen->sendeEncrypted( "\1", 1 );
+						}
+						break;
+					default:
+						empfangen->sendeEncrypted( "\0", 1 );
+						break;
+					}
+				}
+				break;
+			case 9: // Bereit zum Laden
+				if( zSpiel && zSpiel->klientBereitZumLaden( accountId ) )
+					empfangen->sendeEncrypted( "\1", 1 );
+				else
+				{
+					empfangen->sendeEncrypted( "\0", 1 );
+					errorZuKlientSende( "Es ist ein unbekannter Fehler aufgetreten." );
+				}
+				break;
+			case 0xA: // Bereit zum Spiel
+				if( zSpiel && zSpiel->klientBereitZumSpiel( accountId ) )
+					empfangen->sendeEncrypted( "\1", 1 );
+				else
+				{
+					empfangen->sendeEncrypted( "\0", 1 );
+					errorZuKlientSende( "Es ist ein unbekannter Fehler aufgetreten." );
+				}
+				break;
+			case 0xB: // Spiel Nachricht
+				if( 1 )
+				{
+					short len = 0;
+					empfangen->getNachricht( (char*)&len, 2 );
+					char *bytes = new char[ len ];
+					empfangen->getNachricht( bytes, len );
+					if( !zSpiel || !zSpiel->spielNachricht( accountId, len, bytes ) )
+						errorZuKlientSende( "Es ist ein unbekannter Fehler aufgetreten." );
+					delete[] bytes;
+				}
+				break;
+			case 0xC: // Spiel Laden Prozent
+				if( 1 )
+				{
+					empfangen->sendeEncrypted( "\1", 1 );
+					int prozent = 0;
+					empfangen->getNachrichtEncrypted( (char*)&prozent, 4 );
+					if( zSpiel && zSpiel->klientSpielLadenProzent( accountId, prozent ) )
+						empfangen->sendeEncrypted( "\1", 1 );
+					else
+					{
+						empfangen->sendeEncrypted( "\0", 1 );
+						errorZuKlientSende( "Es ist ein unbekannter Fehler aufgetreten." );
+					}
+				}
+				break;
+			case 0xD: // Statistik Nachricht
+				if( 1 )
+				{
+					empfangen->sendeEncrypted( "\1", 1 );
+					short len = 0;
+					empfangen->getNachrichtEncrypted( (char*)&len, 2 );
+					char *bytes = new char[ len ];
+					empfangen->getNachrichtEncrypted( bytes, len );
+					if( zSpiel && zSpiel->statistikNachricht( accountId, len, bytes ) )
+						empfangen->sendeEncrypted( "\1", 1 );
+					else
+					{
+						empfangen->sendeEncrypted( "\0", 1 );
+						errorZuKlientSende( "Es ist ein unbekannter Fehler aufgetreten." );
+					}
+					delete[] bytes;
+				}
+				break;
+			case 0xE: // Team wählen Fertig
+				if( 1 )
+				{
+					if( zSpiel && zSpiel->klientTeamAuswahlFertig( accountId ) )
+						empfangen->sendeEncrypted( "\1", 1 );
+					else
+					{
+						empfangen->sendeEncrypted( "\0", 1 );
+						errorZuKlientSende( "Es ist ein unbekannter Fehler aufgetreten." );
+					}
+				}
+				break;
+			case 0xF: // ping
+				if( 1 )
+				{
+					empfangen->sendeEncrypted( "\1", 1 );
+					keepAlive();
+				}
+				break;
+			default:
+				empfangen->sendeEncrypted( "\0", 1 );
+				errorZuKlientSende( "Unbekannte Nachricht." );
+				unbekannt += 2;
+				if( unbekannt > 10 )
+				{
+					trenne();
+					br = 1;
+				}
+				break;
+			}
+			unbekannt--;
+			if( unbekannt < 0 )
+				unbekannt = 0;
+		}
+		else
+		{
+			trenne();
+			br = 1;
+		}
+		if( br )
+			break;
+		ss->addEmpfangen( empfangen->getDownloadBytes( 1 ) );
+		ss->addGesendet( empfangen->getUploadBytes( 1 ) );
+	}
+	ss->addEmpfangen( empfangen->getDownloadBytes( 1 ) );
+	ss->addGesendet( empfangen->getUploadBytes( 1 ) );
+	if( del || !accountId )
+	{
+		termThread = 0;
+		delete this;
+	}
+	else
+	{
+		termThread = 0;
+		ss->unregisterKlient( this );
+	}
+}
+
+void SSKlient::errorZuKlientEmpfang( const char *nachricht ) // sendet eine Fehlernachricht zum Klient
+{
+	char len = (char)textLength( nachricht );
+	if( !len )
+		return;
+	if( empfangen )
+	{
+		empfangen->sendeEncrypted( "\3", 1 );
+		empfangen->sendeEncrypted( &len, 1 );
+		empfangen->sendeEncrypted( nachricht, len );
+	}
+	ss->addEmpfangen( empfangen->getDownloadBytes( 1 ) );
+	ss->addGesendet( empfangen->getUploadBytes( 1 ) );
+}
+
+void SSKlient::errorZuKlientSende( const char *nachricht )
+{
+	char len = (char)textLength( nachricht );
+	if( !len )
+		return;
+	if( senden )
+	{
+		lock();
+		senden->sendeEncrypted( "\3", 1 );
+		senden->sendeEncrypted( &len, 1 );
+		senden->sendeEncrypted( nachricht, len );
+		unlock();
+		ss->addEmpfangen( senden->getDownloadBytes( 1 ) );
+		ss->addGesendet( senden->getUploadBytes( 1 ) );
+	}
+}
+
+// const
+int SSKlient::getAccountId() const
+{
+	return accountId;
+}
+
+int SSKlient::getKlientNummer() const
+{
+	return klientNummer;
+}
+
+SKlient *SSKlient::getKlient() const
+{
+	return empfangen->getThis();
+}
+
+// Reference Counting
+SSKlientV *SSKlient::getThis()
+{
+	ref++;
+	return this;
+}
+
+SSKlientV *SSKlient::release()
+{
+	ref--;
+	if( !ref )
+		delete this;
+	return 0;
+}

+ 180 - 0
SpielServer/SpielServer.h

@@ -0,0 +1,180 @@
+#ifndef SpielServer_H
+#define SpielServer_H
+
+#include <Server.h>
+#include <Thread.h>
+#include <Datei.h>
+#include <Text.h>
+#include "SSKlientV.h"
+#include <InitDatei.h>
+#ifdef WIN32
+#include "SpielErstellt/SpielErstellt.h"
+#include "Spiel/Spiel.h"
+#include "../Datenbank/Datenbank.h"
+#include "Historie/HistorieSender.h"
+#else
+#include "SpielErstellt.h"
+#include "Spiel.h"
+#include "Datenbank.h"
+#include "HistorieSender.h"
+#endif
+
+using namespace Framework;
+using namespace Network;
+
+class SSKlient;
+
+class SpielServer : public Thread
+{
+private:
+	HistorieSender *historieS;
+	Server *server;
+	Server *aServer;
+	InitDatei *ini;
+	SSDatenbank *db;
+	CRITICAL_SECTION cs;
+	SpielFinden *startSpielThread;
+	RCArray< SpielErstellt > *erstellt;
+	int spielErstelltAnzahl;
+	RCArray< Spiel > *spiele;
+	int spielAnzahl;
+	RCArray< SSKlient > *klients;
+	Array< int > *spielHistorieId;
+	Text *fehler;
+	int klientAnzahl;
+	int klientAnzahl2;
+	int id;
+	bool nichtPausiert;
+	int empfangen;
+	int gesendet;
+	bool end;
+	int ref;
+
+public:
+	// Konstruktor 
+	SpielServer( InitDatei *zIni );
+	// Destruktor 
+	virtual ~SpielServer();
+	// nicht constant
+	void lock();
+	void unlock();
+	void runn();
+	virtual void thread();
+	void close();
+	bool serverStarten();
+	bool serverPause();
+	bool serverFortsetzen();
+	bool serverBeenden();
+	bool setMaxSpiele( int ms );
+	void addSpielErstellt( SpielErstellt *erstellt );
+	void SpielErstelltAbbruch( int spielErstelltId );
+	void removeSpielErstellt( int id );
+	bool registerKlient( SSKlient *klient );
+	bool absturzKlient( int klientId );
+	bool verteileKlient( SSKlient *klient );
+	void unregisterKlient( SSKlient *zKlient );
+	void klientsMM( SSKlient *k );
+	void addSpiel( Spiel *spiel );
+	void removeSpiel( int spielId );
+	void addGesendet( int bytes );
+	void addEmpfangen( int bytes );
+	void addSpielHistorieId( int id );
+	bool hatSpielHistorieId( int id );
+	void removeSpielHistorieId( int id );
+	// conatant 
+	bool istAn() const;
+	Server *zServer() const;
+	SSDatenbank *zDB() const;
+    InitDatei *zInit() const;
+	bool hatClients() const;
+	int getId() const;
+	char *getLetzterFehler() const;
+	char *getIp() const;
+	int getPort() const;
+	// Reference Counting
+	SpielServer *getThis();
+	SpielServer *release();
+};
+
+class SSAKlient : public Thread
+{
+private:
+	SKlient *klient;
+	Text *name;
+	Text *passwort;
+	int adminId;
+	SpielServer *ss;
+	int version;
+
+public:
+	// Konstruktor 
+	SSAKlient( SKlient *klient, SpielServer *ss );
+	// Destruktor 
+	virtual ~SSAKlient();
+	// nicht constant
+	void thread();
+	void sendeVerzeichnisAnKlient( char *pfad, int );
+	void errorZuKlient( const char *nachricht ) const; // sendet eine Fehlernachricht zum AKlient
+};
+
+class SSKlient : public SSKlientV
+{
+private:
+	SKlient     *empfangen;
+	SKlient     *senden;
+	unsigned int klientNummer;
+	SpielServer *ss;
+	int accountId;
+	bool termThread;
+	bool verbunden;
+	SpielErstellt *zErstellt;
+	Spiel *zSpiel;
+	CRITICAL_SECTION cs;
+	int ref;
+
+public:
+	// Konstruktor 
+	SSKlient( SKlient *klient, SpielServer *ss );
+	// Destruktor 
+	virtual ~SSKlient();
+	// nicht constant 
+	void lock();
+	void unlock();
+	void absturz();
+	void setSpielErstellt( SpielErstellt *zErstellt );
+	void setSpiel( Spiel *zSpiel );
+	virtual void nichtTrennen();
+	void spielGefunden( int karteId );
+	void zeitVerbleibend( char sekunden );
+	void erstellungAbgebrochen( char *grund );
+	void backInWarteschlange( char st, char min, char sec );
+	void erstellungFortsetzen();
+	void erstellungInitialisierung( SpielerTeamStruktur *sts );
+	void erstellungAddSpieler( int accountId );
+	void erstellungRemoveSpieler( int accountId );
+	void erstellungSpielerTeam( int accountId, int spielerNummer );
+	void erstellungChatNachricht( char *nachricht );
+	void spielLadenBeginn();
+	void spielLadenSpielerAdd( int accId, int spielerNumer );
+	void spielLadenSetSpielerProzent( int accId, int prozent );
+	void spielLadenSetSpielerPing( int accId, int ping );
+	virtual double ping();
+	void spielLadenFertig();
+	virtual void spielNachricht( short len, char *bytes );
+	virtual void statistikNachricht( short len, char *bytes );
+	bool keepAlive();
+	virtual void trenne();
+	void setSenden( SSKlient *klient );
+	virtual void thread();
+	virtual void errorZuKlientEmpfang( const char *nachricht ); // sendet eine Fehlernachricht zum Klient
+	virtual void errorZuKlientSende( const char *nachricht );
+	// const
+	virtual int getAccountId() const;
+	int getKlientNummer() const;
+	SKlient *getKlient() const;
+	// Reference Counting
+	virtual SSKlientV *getThis();
+	virtual SSKlientV *release();
+};
+
+#endif

+ 118 - 0
SpielServer/SpielServer.vcxproj

@@ -0,0 +1,118 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup Label="ProjectConfigurations">
+    <ProjectConfiguration Include="Debug|ARM">
+      <Configuration>Debug</Configuration>
+      <Platform>ARM</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|ARM">
+      <Configuration>Release</Configuration>
+      <Platform>ARM</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Debug|x86">
+      <Configuration>Debug</Configuration>
+      <Platform>x86</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|x86">
+      <Configuration>Release</Configuration>
+      <Platform>x86</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Debug|x64">
+      <Configuration>Debug</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|x64">
+      <Configuration>Release</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+  </ItemGroup>
+  <PropertyGroup Label="Globals">
+    <ProjectGuid>{fee06987-1a98-4953-8a84-f7d1cecf18f4}</ProjectGuid>
+    <Keyword>Linux</Keyword>
+    <RootNamespace>SpielServer</RootNamespace>
+    <MinimumVisualStudioVersion>15.0</MinimumVisualStudioVersion>
+    <ApplicationType>Linux</ApplicationType>
+    <ApplicationTypeRevision>1.0</ApplicationTypeRevision>
+    <TargetLinuxPlatform>Generic</TargetLinuxPlatform>
+    <LinuxProjectType>{D51BCBC9-82E9-4017-911E-C93873C4EA2B}</LinuxProjectType>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'" Label="Configuration">
+    <UseDebugLibraries>true</UseDebugLibraries>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'" Label="Configuration">
+    <UseDebugLibraries>false</UseDebugLibraries>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x86'" Label="Configuration">
+    <UseDebugLibraries>true</UseDebugLibraries>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x86'" Label="Configuration">
+    <UseDebugLibraries>false</UseDebugLibraries>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <RemoteRootDir>/home/kolja/projects</RemoteRootDir>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <RemoteRootDir>/home/kolja/projects</RemoteRootDir>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <ImportGroup Label="ExtensionSettings" />
+  <ImportGroup Label="Shared" />
+  <ImportGroup Label="PropertySheets" />
+  <PropertyGroup Label="UserMacros" />
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <TargetExt />
+    <RemoteProjectDir>$(RemoteRootDir)/Server/$(ProjectName)/debug</RemoteProjectDir>
+    <IncludePath>..\..\..\..\Allgemein\Framework;../../../Framework/debug;..\..\..\..\Allgemein\Network\Network;../../../Network/debug;..\..\..\..\Allgemein\sql\sql;../../../sql/debug;$(IncludePath)</IncludePath>
+    <OutDir>$(ProjectDir)bin\$(Platform)\debug\</OutDir>
+    <IntDir>$(ProjectDir)obj\$(Platform)\debug\</IntDir>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <TargetExt />
+    <RemoteProjectDir>$(RemoteRootDir)/Server/$(ProjectName)/release</RemoteProjectDir>
+    <IncludePath>..\..\..\..\Allgemein\Framework;../../../Framework/release;..\..\..\..\Allgemein\Network\Network;../../../Network/release;..\..\..\..\Allgemein\sql\sql;../../../sql/release;$(IncludePath)</IncludePath>
+    <OutDir>$(ProjectDir)bin\$(Platform)\release\</OutDir>
+    <IntDir>$(ProjectDir)obj\$(Platform)\release\</IntDir>
+  </PropertyGroup>
+  <ItemGroup>
+    <ClCompile Include="Datenbank.cpp" />
+    <ClCompile Include="HistorieSender.cpp" />
+    <ClCompile Include="KartenLeser.cpp" />
+    <ClCompile Include="Spiel.cpp" />
+    <ClCompile Include="SpielErstellt.cpp" />
+    <ClCompile Include="SpielServer.cpp" />
+    <ClCompile Include="start.cpp" />
+    <ClCompile Include="Strukturen.cpp" />
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include="Datenbank.h" />
+    <ClInclude Include="HistorieSender.h" />
+    <ClInclude Include="KartenLeser.h" />
+    <ClInclude Include="Spiel.h" />
+    <ClInclude Include="SpielErstellt.h" />
+    <ClInclude Include="SpielKlasse.h" />
+    <ClInclude Include="SpielServer.h" />
+    <ClInclude Include="SSDatenbankV.h" />
+    <ClInclude Include="SSKlientV.h" />
+    <ClInclude Include="Statistik.h" />
+    <ClInclude Include="Strukturen.h" />
+  </ItemGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <Link>
+      <AdditionalLibraryDirectories>$(RemoteRootDir)/sql/debug/bin/x64/debug;$(RemoteRootDir)/Network/debug/bin/x64/debug;$(RemoteRootDir)/Framework/debug/bin/x64/debug;/usr/lib/;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <LibraryDependencies>dbgFramework;dbgNetwork;dbgSQL;pq;pthread;dl</LibraryDependencies>
+      <AdditionalOptions>-Wl,-rpath,../lib %(AdditionalOptions)</AdditionalOptions>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <Link>
+      <AdditionalLibraryDirectories>$(RemoteRootDir)/sql/release/bin/x64/release;$(RemoteRootDir)/Network/release/bin/x64/release;$(RemoteRootDir)/Framework/release/bin/x64/release;/usr/lib/;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <LibraryDependencies>Framework;Network;SQL;pq;pthread;dl</LibraryDependencies>
+      <AdditionalOptions>-Wl,-rpath,../lib %(AdditionalOptions)</AdditionalOptions>
+    </Link>
+  </ItemDefinitionGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+  <ImportGroup Label="ExtensionTargets" />
+</Project>

+ 75 - 0
SpielServer/SpielServer.vcxproj.filters

@@ -0,0 +1,75 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup>
+    <Filter Include="Headerdateien">
+      <UniqueIdentifier>{da165dc0-1ad2-43eb-9f03-7b00d79a7073}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="Quelldateien">
+      <UniqueIdentifier>{df7cb339-1d18-49b4-968f-e3201b4613a8}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="Include">
+      <UniqueIdentifier>{5daf8666-eec2-4e9a-a4cd-78a523f2223e}</UniqueIdentifier>
+    </Filter>
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include="Datenbank.h">
+      <Filter>Headerdateien</Filter>
+    </ClInclude>
+    <ClInclude Include="HistorieSender.h">
+      <Filter>Headerdateien</Filter>
+    </ClInclude>
+    <ClInclude Include="KartenLeser.h">
+      <Filter>Headerdateien</Filter>
+    </ClInclude>
+    <ClInclude Include="Spiel.h">
+      <Filter>Headerdateien</Filter>
+    </ClInclude>
+    <ClInclude Include="SpielErstellt.h">
+      <Filter>Headerdateien</Filter>
+    </ClInclude>
+    <ClInclude Include="SpielKlasse.h">
+      <Filter>Headerdateien</Filter>
+    </ClInclude>
+    <ClInclude Include="SpielServer.h">
+      <Filter>Headerdateien</Filter>
+    </ClInclude>
+    <ClInclude Include="Statistik.h">
+      <Filter>Headerdateien</Filter>
+    </ClInclude>
+    <ClInclude Include="Strukturen.h">
+      <Filter>Headerdateien</Filter>
+    </ClInclude>
+    <ClInclude Include="SSKlientV.h">
+      <Filter>Include</Filter>
+    </ClInclude>
+    <ClInclude Include="SSDatenbankV.h">
+      <Filter>Include</Filter>
+    </ClInclude>
+  </ItemGroup>
+  <ItemGroup>
+    <ClCompile Include="Datenbank.cpp">
+      <Filter>Quelldateien</Filter>
+    </ClCompile>
+    <ClCompile Include="HistorieSender.cpp">
+      <Filter>Quelldateien</Filter>
+    </ClCompile>
+    <ClCompile Include="KartenLeser.cpp">
+      <Filter>Quelldateien</Filter>
+    </ClCompile>
+    <ClCompile Include="Spiel.cpp">
+      <Filter>Quelldateien</Filter>
+    </ClCompile>
+    <ClCompile Include="SpielErstellt.cpp">
+      <Filter>Quelldateien</Filter>
+    </ClCompile>
+    <ClCompile Include="SpielServer.cpp">
+      <Filter>Quelldateien</Filter>
+    </ClCompile>
+    <ClCompile Include="start.cpp">
+      <Filter>Quelldateien</Filter>
+    </ClCompile>
+    <ClCompile Include="Strukturen.cpp">
+      <Filter>Quelldateien</Filter>
+    </ClCompile>
+  </ItemGroup>
+</Project>

+ 23 - 0
SpielServer/Statistik.h

@@ -0,0 +1,23 @@
+#ifndef Statistik_H
+#define Statistik_H
+
+class StatistikV
+{
+private:
+
+public:
+	virtual ~StatistikV()
+	{
+	}
+	// nicht constant
+	virtual void klientOffline( int accountId ) = 0;
+	virtual void statistikAnfrage( int accountId, short len, char *bytes ) = 0;
+	virtual void run() = 0;
+	// constant
+
+	// Reference Counting
+	virtual StatistikV *getThis() = 0;
+	virtual StatistikV *release() = 0;
+};
+
+#endif

+ 35 - 0
SpielServer/Strukturen.cpp

@@ -0,0 +1,35 @@
+#include "Strukturen.h"
+
+// Inhalt der SpielerTeamStruktur Struktur aus Strukturen.h
+SpielerTeamStruktur::SpielerTeamStruktur()
+{
+	spielerAnzahl = 0;
+	teamAnzahl = 0;
+	spielerFarbe = new Array< int >();
+	teamFarbe = new Array< int >();
+	teamName = new RCArray< Text >();
+	teamSize = new Array< int >();
+	ref = 1;
+}
+
+SpielerTeamStruktur::~SpielerTeamStruktur()
+{
+	spielerFarbe->release();
+	teamFarbe->release();
+	teamName->release();
+	teamSize->release();
+}
+
+SpielerTeamStruktur *SpielerTeamStruktur::getThis()
+{
+	ref++;
+	return this;
+}
+
+SpielerTeamStruktur *SpielerTeamStruktur::release()
+{
+	ref--;
+	if( !ref )
+		delete this;
+	return 0;
+}

+ 25 - 0
SpielServer/Strukturen.h

@@ -0,0 +1,25 @@
+#ifndef Strukturen_H
+#define Strukturen_H
+
+#include <Server.h>
+#include <Array.h>
+#include <Text.h>
+
+using namespace Framework;
+
+struct SpielerTeamStruktur
+{
+	SpielerTeamStruktur();
+	~SpielerTeamStruktur();
+	int spielerAnzahl;
+	int teamAnzahl;
+	Array< int > *spielerFarbe;
+	Array< int > *teamFarbe;
+	RCArray< Text > *teamName;
+	Array< int > *teamSize;
+	int ref;
+	SpielerTeamStruktur *getThis();
+	SpielerTeamStruktur *release();
+};
+
+#endif

BIN
SpielServer/readme/images/ArchOptions.gif


BIN
SpielServer/readme/images/ChangeRemote.gif


BIN
SpielServer/readme/images/ManageConnections.gif


BIN
SpielServer/readme/images/OutputTypes.gif


BIN
SpielServer/readme/images/debuggerexport.png


BIN
SpielServer/readme/images/firstconnection.png


BIN
SpielServer/readme/images/linker.png


BIN
SpielServer/readme/images/postbuild.png


+ 85 - 0
SpielServer/readme/readme.html

@@ -0,0 +1,85 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <meta charset='utf-8'>
+
+    <link rel="stylesheet" type="text/css" href="stylesheet.css" media="screen">
+
+    <title>Getting Started</title>
+  </head>
+
+<body>
+
+    <div class="container">
+        <div id="header">
+            <h1>Getting Started</h1>
+            <h2>Visual C++ for Linux Development extension</h2>
+        </div>
+    
+    <table>
+    <tr>    
+    <div id="main_content">
+        
+        <td>
+        <div id="lpanel">
+            <h1>Setting up your project for Linux Development</h1>
+
+            <p>With this extension you can author C++ code for Linux servers, desktops and devices. You can manage your connections to these machines from within VS. VS will automatically copy and remote build your sources and can launch your application with the debugger. Our project system supports targeting specific architectures, including ARM.</p>
+            <img src="images\ArchOptions.gif"/>
+            
+            <h1>Connecting to Linux</h1>
+            <h2>Prerequisites</h2>
+            <p>Today we only support building remotely on the Linux target machine. We are not limited by specific Linux distros but we do have dependencies on the presence of some tools. Specifically, we need openssh-server, g++, gdb and gdbserver. Use your favorite package manager to install them, e.g. on Debian based systems: sudo apt-get install openssh-server g++ gdb gdbserver</p>
+            
+            <h2>First connection</h2>
+            <p>The first time you target a Linux machine you will be prompted for connection information.  This is triggered by building the project.</p>
+            <img src="images\firstconnection.png"/>
+                
+            <h2>Adding and removing connections</h2>
+            <p>To add a new connection, go to Tools > Options and search for Linux. From here you can add and remove connections.</p>
+            <img src="images\ManageConnections.gif"/>
+            
+            <p>To change which connection a project is using go to the project properties remote settings and update the target machine.</p>
+            <img src="images\ChangeRemote.gif"/>
+            
+            <h1>Project Properties</h1>
+            <p>All of the options necessary to control C++ compilation are exposed on the project properies pages. We'll cover a few specific to how things work for Linux. First under remote settings, you will see the remote root is set to ~/projects/ by default and that we are setting the remote project directory to match our project name in that location. </p>
+            <img src="images\OutputTypes.gif"/>
+            
+            <p>Looking at the General settings for the project, you can see how our output and intermediate directories were configured. Additionally, you’ll see that this project was configured as an application – thus our executable is under bin/x64/Debug/ as ConsoleApplication1.out. Notice that for configuration types we also support static and dynamic libraries.</p>
+            
+            <p>Add additional library dependencies on the Linker > Input property page.</p>
+            <img src="images\linker.png"/>
+            
+            <p>You can pass additional pre launch commands to the debugger to do things like launch graphical apps on the remote linux machine.</p>
+            <img src="images\debuggerexport.png"/>
+            
+            <p>You can also send post build events to control remote behavior, as in this example that exports a gpio pin for use without requiring the executable run as super user.</p>
+            <img src="images\postbuild.png"/>
+            
+        </div>
+        </td>
+        <td>
+        <div id="rpanel">
+
+            <h1>Resources</h1>
+
+            <p>Check out the <a href="http://aka.ms/vslinuxext">VS Gallery VC++ for Linux Development page</a> where we will keep updates posted. You can also check out our <a href="https://blogs.msdn.microsoft.com/vcblog/2016/03/30/visual-c-for-linux-development">announcment blog post</a> for more in depth details on configuring the project properties.</p>
+            
+            <p>Here are other utilities you will find useful in connection with this extension.</p>
+            <ul>
+                <li>Learn more about <a href="http://aka.ms/vsiot">IoT Development</a></li>
+                <li><a href="http://aka.ms/vsiotext">VC++ for IoT Development Tools</a></li>
+                <li><a href="https://github.com/Azure/azure-iot-sdks">Azure IoT SDK</a>, includes a C API for connecting small devices to the Azure IoT Hub</li>
+            </ul>
+
+            <h1>Give us feedback</h1>
+            <p><a href="http://aka.ms/vslinux-feedback">UserVoice</a></p>
+        </div>
+        </td>   
+    </div>
+    </tr>
+    </table>
+    </div>
+</body>
+</html>

+ 119 - 0
SpielServer/readme/stylesheet.css

@@ -0,0 +1,119 @@
+body {
+  margin: 0;
+  padding: 0;
+  border: 0;
+  color: #1E1E1E;
+  font-size: 13px;
+  font-family: "Segoe UI", Helvetica, Arial, sans-serif;
+  line-height: 1.45;
+  word-wrap: break-word;
+}
+
+/* General & 'Reset' Stuff */
+
+
+.container {
+  width: 1100px;
+  margin: 0 auto;
+}
+
+section {
+  display: block;
+  margin: 0;
+}
+
+h1, h2, h3, h4, h5, h6 {
+  margin: 0;
+}
+
+table, tr {
+    width: 1100px;
+    padding: 0px;
+    vertical-align: top;
+  }
+
+/* Header, <header>
+   header   - container
+   h1       - project name
+   h2       - project description
+*/
+
+#header {
+  color: #FFF;
+  background: #68217a;
+  position:relative;
+}
+h1, h2 {
+  font-family: "Segoe UI Light", "Segoe UI", Helvetica, Arial, sans-serif;
+  line-height: 1;
+  margin: 0 18px;;
+  padding: 0;
+}
+#header h1 {
+  font-size: 3.4em;
+  padding-top: 18px;
+  font-weight: normal;
+  margin-left: 15px;
+}
+
+#header h2 {
+  font-size: 1.5em;
+  margin-top: 10px;
+  padding-bottom: 18px;
+  font-weight: normal;
+}
+
+#main_content {
+  width: 100%;
+  display: flex;
+  flex-direction: row;
+}
+
+
+h1, h2, h3, h4, h5, h6 {
+  font-weight: bolder;
+}
+
+#main_content h1 {
+  font-size: 1.8em;
+  margin-top: 34px;
+}
+
+    #main_content h1:first-child {
+        margin-top: 30px;
+    }
+
+#main_content h2 {
+  font-size: 1.8em;
+}
+p, ul {
+    margin: 11px 18px;
+}
+
+#main_content a {
+    color: #06C;
+    text-decoration: none;
+}
+ul {
+        margin-top: 13px;
+    margin-left: 18px;
+    padding-left: 0;
+}
+    ul li {
+        margin-left: 18px;
+        padding-left: 0;
+    }
+#lpanel {
+    width: 870px;
+    float: left;
+}
+#rpanel ul {
+    list-style-type: none;
+}
+    #rpanel ul li {
+        line-height: 1.8em;
+    }
+#rpanel {
+    background: #e7e7e7;
+    width: 230px;
+}

+ 60 - 0
SpielServer/start.cpp

@@ -0,0 +1,60 @@
+#include "SpielServer.h"
+#include <Zeit.h>
+#include <iostream>
+#include <fstream>
+#include <Globals.h>
+#include <sys/resource.h>
+
+int main()
+{
+	struct rlimit core_limits;
+	core_limits.rlim_cur = core_limits.rlim_max = RLIM_INFINITY;
+	setrlimit(RLIMIT_CORE, &core_limits);
+    //chdir( "/ksg/Server/spiel" );
+    Framework::initFramework();
+	Zeit *z = getZeit();
+	Text *pfad = new Text( "../log/spiel/" );
+	pfad->append( z->getZeit( "y-m-d h-i-s.log" ) );
+	z->release();
+	DateiPfadErstellen( pfad->getThis() );
+	std::ofstream file;
+	file.open( pfad->getText() );
+	std::streambuf* sbuf = std::cout.rdbuf();
+	std::cout.rdbuf( file.rdbuf() );
+	pfad->release();
+
+	std::cout << "SS: Startet...\n";
+	std::cout << "SS: Lese init Datei ../data/ssInit.ini ...\n";
+	InitDatei *dat = new InitDatei( "../data/ssInit.ini" );
+	if( !dat->laden() )
+	{
+		std::cout << "SS: 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", "SpielePfad", "TempMapPfad" };
+    for( const char *w : wichtig )
+    {
+        if( !dat->wertExistiert( w ) )
+        {
+            std::cout << "SS: error: Der Wert '" << w << "' wurde nicht gefunden. Das Programm wird geschlossen.\n";
+            dat->release();
+            exit( 1 );
+        }
+    }
+
+	SpielServer *sServer = new SpielServer( dat );
+
+	std::cout << "SS: Der Admin Server läuft. Startforgang beendet.\n";
+	sServer->runn();
+
+	sServer->ende();
+	sServer->release();
+    DateiRemove( dat->zWert( "TempMapPfad" )->getText() );
+	dat->release();
+	std::cout << "SS: Der Server ist heruntergefahren.\n";
+	file.close();
+	std::cout.rdbuf( sbuf );
+    Framework::releaseFramework();
+	return 0;
+}

+ 2 - 0
build.bat

@@ -0,0 +1,2 @@
+"D:\Visual Studio 2017\MSBuild\15.0\Bin\MSBuild.exe" "Spiel Server.sln" /t:rebuild /p:configuration=debug /p:platform=x64
+"D:\Visual Studio 2017\MSBuild\15.0\Bin\MSBuild.exe" "Spiel Server.sln" /t:rebuild /p:configuration=release /p:platform=x64

BIN
spiele/Asteroids/maps/Test/data.map


BIN
spiele/Asteroids/maps/Test/sts.ltgd


BIN
spiele/Asteroids/models/ship.m2


BIN
spiele/Linie/maps/Normal/sts.ltgd