Quellcode durchsuchen

Spiel Server hinzugefügt

Kolja Strohm vor 6 Jahren
Ursprung
Commit
f6c55f512e

+ 13 - 38
Include/KSGNetwork.h

@@ -2,6 +2,7 @@
 
 #include <Array.h>
 #include <Thread.h>
+#include "../../Include/StrukturenV.h"
 
 namespace Framework
 {
@@ -153,39 +154,15 @@ namespace KSGClient
         Framework::Array< int > ids; // Liste mit Account Ids
     };
 
-    // Enthält alle Daten zur Team - Spieler Konstalation einer Karte
-    class SpielerTeamStruktur
-    {
-    protected:
-        int ref; // Reference Counter
-
-    public:
-        int spielerAnzahl; // Die Anzahl der Spieler
-        int teamAnzahl; // Die Anzahl der Teams
-        Framework::Array< int > *spielerFarbe; // Eine Liste mit den Farben für jeden Spieler
-        Framework::Array< int > *teamFarbe; // Eine Liste mit Farben für jedes Team
-        Framework::RCArray< Framework::Text > *teamName; // Eine Liste mit namen für jedes Team
-        Framework::Array< int > *teamGröße; // Eine Liste Mit Spieleranzahlen für jedes Team
-        // Erhöht den Reference Counter um 1 un gibt this zurück
-        virtual SpielerTeamStruktur *getThis() = 0;
-        // Verringert den Reference Counter um 1 und gibt 0 zurück.
-        //  Falls der Reference Counter nach dem Aufruf auf 0 ist löscht sich das Objekt selbst 
-        virtual SpielerTeamStruktur *release() = 0;
-    };
-
     // Enthält eine Nachricht von dem Spiel Server
-    class SpielServerNachricht
+    struct SpielServerNachricht
     {
-    protected:
-        int ref; // Reference Counter
-
-    public:
         char type; // Typ der Nachricht
         char sekunden; // Mit der Nachricht zusammenhängende Sekunden
         char minuten; // Mit der Nachricht zusammenhängende Minuten
         char stunden; // Mit der Nachricht zusammenhängende Stunden
-        Framework::Text *message; // Text der Nachricht
-        SpielerTeamStruktur *sts; // Die Spieler Team Struktur eines Spiels
+        Framework::Text message; // Text der Nachricht
+        SpielerTeamStrukturV *sts; // Die Spieler Team Struktur eines Spiels
         int accountId; // Id des Accounts
         int spielerNummer; // Die Spielernummer des Accounts
         int karteId; // Die Id der Karte
@@ -193,11 +170,6 @@ namespace KSGClient
         int ping; // Der Ping des Accounts (1000 = 1 Sekunde)
         short län; // Länge der gesendeten Daten
         char *data; // Die gesendeten Daten
-        // Erhöht den Reference Counter um 1 un gibt this zurück
-        virtual SpielServerNachricht *getThis() = 0;
-        // Verringert den Reference Counter um 1 und gibt 0 zurück.
-        //  Falls der Reference Counter nach dem Aufruf auf 0 ist löscht sich das Objekt selbst 
-        virtual SpielServerNachricht *release() = 0;
     };
 
     // Wird benutzt, um die Verbindung mit den Servern aufrecht zu erhalten. Bei einem Verbindungsabbruch wird der Client automatisch abgemeldet
@@ -726,7 +698,8 @@ namespace KSGClient
         //  Gibt 1 zurück, falls der Vorgang erfolgreich ist, 0 sonnst
         //  Sollte erst nach einem erfolgreichen Aufruf von verbinde aufgerufen werden
         virtual bool trenne( bool abmelden ) = 0;
-        // Wartet auf eine Nachricht vom Chatserver und gibt diese zurück.
+        // Wartet auf eine Nachricht vom Chatserver.
+        //  Gibt bei Erfolg 1 zurück, 0 sonnst
         //  nachricht: Eine Referenz auf die Struktur, in der die Nachricht gespeichert werden soll
         virtual bool getNextMessage( ChatServerNachricht &nachricht) = 0;
         // Gibt 1 zurück, falls der Client verbunden ist, 0 sonst
@@ -1006,8 +979,10 @@ namespace KSGClient
         //  bytes: Ein Zeiger auf die Nachricht
         //  Gibt 1 zurück, falls der Vorgang erfolgreich ist, 0 sonnst
         virtual bool statistikNachricht( short län, char *bytes ) = 0;
-        // Wartet auf eine Nachricht vom Spiel Servers und gibt diese zurück.
-        virtual SpielServerNachricht *getNextMessage() = 0;
+        // Wartet auf eine Nachricht vom Spiel Server.
+        //  Gibt bei Erfolg 1 zurück, 0 sonnst
+        //  nachricht: Eine Referenz auf die Struktur, in der die Nachricht gespeichert werden soll
+        virtual bool getNextMessage( SpielServerNachricht &nachricht ) = 0;
         // Erhält die Verbindung aufrecht
         //  Gibt 1 zurück, falls der Vorgang erfolgreich ist, 0 sonnst
         //  Sollte während einer bestehenden Verbindung etwa einmal alle 60 Sekunden aufgerufen werden, da sonst der Router die Verbindung automatisch trennt
@@ -1015,7 +990,7 @@ namespace KSGClient
         // Trennt die Verbindung zum Server
         //  Gibt 1 zurück, falls der Vorgang erfolgreich ist, 0 sonnst
         //  Sollte erst nach einem erfolgreichen Aufruf von verbinde aufgerufen werden
-        virtual bool trenne( bool abmelden ) = 0;
+        virtual bool trenne() = 0;
         // Gibt 1 zurück, falls der Client verbunden ist, 0 sonst
         virtual bool istVerbunden() const = 0;
         // gibt den Letzten Fehlertext zuück
@@ -1250,11 +1225,11 @@ namespace KSGClient
         // lädt die Spieler Team Daten der Karte
         //  sts: Enthält nach erfolgreichem Aufruf die Spieler Team Daten
         //  Gibt 1 zurück, falls der Vorgang erfolgreich ist, 0 sonnst
-        virtual bool ladeTeamDaten( SpielerTeamStruktur *sts ) = 0;
+        virtual bool ladeTeamDaten( SpielerTeamStrukturV *sts ) = 0;
         // speichert die Team Daten
         //  sts: die neuen Spieler Team Daten
         //  Gibt 1 zurück, falls der Vorgang erfolgreich ist, 0 sonnst
-        virtual bool speicherTeamDaten( SpielerTeamStruktur *sts ) = 0;
+        virtual bool speicherTeamDaten( SpielerTeamStrukturV *sts ) = 0;
         // Erstellt neue Datei im Datei Editor
         //  typ: 0=ordner 1=bild 2=modell2d 3=sound
         //  Gibt 1 zurück, falls der Vorgang erfolgreich ist, 0 sonnst

+ 3 - 4
KSGNetwork/ChatClient.cpp

@@ -638,14 +638,14 @@ bool ChatClient::trenne( bool abmelden )
     return 1;
 }
 
-// Wartet auf eine Nachricht vom Chatserver und gibt diese zurück.
+// Wartet auf eine Nachricht vom Chatserver.
+//  Gibt bei Erfolg 1 zurück, 0 sonnst
+//  nachricht: Eine Referenz auf die Struktur, in der die Nachricht gespeichert werden soll
 bool ChatClient::getNextMessage( ChatServerNachricht &nachricht )
 {
-    cs.lock();
     if( !empfangen )
     {
         err = "Der Client ist nicht verbunden.";
-        cs.unlock();
         return 0;
     }
     do
@@ -653,7 +653,6 @@ bool ChatClient::getNextMessage( ChatServerNachricht &nachricht )
         if( !empfangen->getNachrichtEncrypted( &nachricht.type, 1 ) )
         {
             err = "Fehler beim Empfangen der Nachricht.";
-            cs.unlock();
             return 0;
         }
         switch( nachricht.type )

+ 3 - 1
KSGNetwork/ChatClient.h

@@ -99,7 +99,9 @@ namespace KSGClient
         //  Gibt 1 zurück, falls der Vorgang erfolgreich ist, 0 sonnst
         //  Sollte erst nach einem erfolgreichen Aufruf von verbinde aufgerufen werden
         bool trenne( bool abmelden ) override;
-        // Wartet auf eine Nachricht vom Chatserver und gibt diese zurück.
+        // Wartet auf eine Nachricht vom Chatserver.
+        //  Gibt bei Erfolg 1 zurück, 0 sonnst
+        //  nachricht: Eine Referenz auf die Struktur, in der die Nachricht gespeichert werden soll
         bool getNextMessage( ChatServerNachricht &nachricht ) override;
         // Gibt 1 zurück, falls der Client verbunden ist, 0 sonst
         bool istVerbunden() const override;

+ 2 - 0
KSGNetwork/KSGNetwork.vcxproj

@@ -161,6 +161,7 @@
     <ClInclude Include="PatchClient.h" />
     <ClInclude Include="RegisterServer.h" />
     <ClInclude Include="ShopClient.h" />
+    <ClInclude Include="SpielClient.h" />
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="AnmeldungClient.cpp" />
@@ -175,6 +176,7 @@
     <ClCompile Include="PatchClient.cpp" />
     <ClCompile Include="RegisterServer.cpp" />
     <ClCompile Include="ShopClient.cpp" />
+    <ClCompile Include="SpielClient.cpp" />
   </ItemGroup>
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
   <ImportGroup Label="ExtensionTargets">

+ 6 - 0
KSGNetwork/KSGNetwork.vcxproj.filters

@@ -57,6 +57,9 @@
     <ClInclude Include="KartenClient.h">
       <Filter>Headerdateien</Filter>
     </ClInclude>
+    <ClInclude Include="SpielClient.h">
+      <Filter>Headerdateien</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="MainClient.cpp">
@@ -95,5 +98,8 @@
     <ClCompile Include="KartenClient.cpp">
       <Filter>Quelldateien</Filter>
     </ClCompile>
+    <ClCompile Include="SpielClient.cpp">
+      <Filter>Quelldateien</Filter>
+    </ClCompile>
   </ItemGroup>
 </Project>

+ 606 - 0
KSGNetwork/SpielClient.cpp

@@ -0,0 +1,606 @@
+#include "SpielClient.h"
+#include <Klient.h>
+#include "Keys.h"
+
+using namespace KSGClient;
+
+// Inhalt der SpielClient Klasse
+
+// Konstruktor
+SpielClient::SpielClient( int klientId, unsigned short port, char *ip, char *key, unsigned char keyLen )
+{
+    ref = 1;
+    this->ip = ip;
+    this->port = port;
+    cId = klientId;
+    senden = 0;
+    empfangen = 0;
+    this->key = new char[ keyLen ];
+    memcpy( this->key, key, keyLen );
+    this->keyLen = keyLen;
+}
+
+// Destruktor
+SpielClient::~SpielClient()
+{
+    trenne();
+    delete[] key;
+}
+
+// verbindet sich mit dem zugewiesenen Karten Server
+//  Gibt 1 zurück, falls der Vorgang erfolgreich ist, 0 sonnst
+bool SpielClient::verbinde()
+{
+    cs.lock();
+    if( senden )
+    {
+        cs.unlock();
+        return 1;
+    }
+    if( !senden )
+        senden = new Network::Klient();
+    int keyLen = 0;
+    char *key = 0;
+    Keys::getServerKey( &key, keyLen, Keys::SPIEL, Keys::SENDEN );
+    senden->setSendeKey( key, keyLen );
+    delete[] key;
+    Keys::getServerKey( &key, keyLen, Keys::SPIEL, Keys::EMPFANGEN );
+    senden->setEmpfangKey( key, keyLen );
+    delete[] key;
+    if( senden->verbinde( port, ip ) )
+    {
+        if( senden->sendeEncrypted( "\1", 1 ) )
+        {
+            char serverReturn = 0;
+            senden->sendeEncrypted( (char*)&cId, 4 );
+            char ret = 0;
+            senden->getNachrichtEncrypted( &ret, 1 );
+            if( ret != 1 )
+            {
+                if( ret == 3 )
+                {
+                    char byte = 0;
+                    senden->getNachrichtEncrypted( &byte, 1 );
+                    char *f = new char[ byte + 1 ];
+                    f[ byte ] = 0;
+                    senden->getNachrichtEncrypted( f, byte );
+                    err = f;
+                    delete[]f;
+                }
+                senden->sendeEncrypted( "\3", 1 );
+                senden->getNachrichtEncrypted( &serverReturn, 1 );
+                senden->trenne();
+                senden = senden->release();
+                err = "Server akzeptiert den Klient nicht.";
+                cs.unlock();
+                return 0;
+            }
+            senden->setSendeKey( this->key, this->keyLen );
+            senden->setEmpfangKey( this->key, this->keyLen );
+            if( !empfangen )
+                empfangen = new Network::Klient();
+            int keyLen = 0;
+            char *key = 0;
+            Keys::getServerKey( &key, keyLen, Keys::SPIEL, Keys::SENDEN );
+            empfangen->setSendeKey( key, keyLen );
+            delete[] key;
+            Keys::getServerKey( &key, keyLen, Keys::SPIEL, Keys::EMPFANGEN );
+            empfangen->setEmpfangKey( key, keyLen );
+            delete[] key;
+            if( empfangen->verbinde( senden->getServerPort(), senden->getServerIp() ) )
+            {
+                empfangen->sendeEncrypted( "\1", 1 );
+                empfangen->sendeEncrypted( (char*)&cId, 4 );
+                char res = 0;
+                empfangen->getNachrichtEncrypted( &res, 1 );
+                if( res == 3 )
+                {
+                    char län = 0;
+                    empfangen->getNachrichtEncrypted( &län, 1 );
+                    char *nachricht = new char[ län + 1 ];
+                    nachricht[ län ] = 0;
+                    empfangen->getNachrichtEncrypted( nachricht, län );
+                    err = nachricht;
+                    delete[] nachricht;
+                }
+                if( res == 1 )
+                {
+                    empfangen->setSendeKey( this->key, this->keyLen );
+                    empfangen->setEmpfangKey( this->key, this->keyLen );
+                }
+                else if( res != 0 )
+                {
+                    err = "Fehler beim Verbinden mit dem Spiel Server.";
+                    senden->sendeEncrypted( "\3", 1 );
+                    char serverReturn = 0;
+                    senden->getNachrichtEncrypted( &serverReturn, 1 );
+                    senden->trenne();
+                    senden = senden->release();
+                    empfangen->trenne();
+                    empfangen = empfangen->release();
+                    return 0;
+                }
+                cs.unlock();
+                return 1;
+            }
+            else
+            {
+                empfangen = empfangen->release();
+                senden->sendeEncrypted( "\3", 1 );
+                char serverReturn = 0;
+                senden->getNachrichtEncrypted( &serverReturn, 1 );
+                senden->trenne();
+                senden = senden->release();
+                err = "Der dir zugewiesene Spiel Server kann dir keine Nachrichten senden.";
+                cs.unlock();
+                return 0;
+            }
+        }
+        else
+        {
+            senden->trenne();
+            senden = senden->release();
+            err = "Der dir zugewiesene Spiel Server hat die Verbindung abgebrochen. Bitte versuche es Später erneut.";
+            cs.unlock();
+            return 0;
+        }
+    }
+    else
+    {
+        err = "Der dir zugewiesene Spiel Server antwortet nicht. Bitte versuche es Später erneut.";
+        senden = senden->release();
+        cs.unlock();
+        return 0;
+    }
+    err = "Unbekannter Fehler";
+    cs.unlock();
+    return 0;
+}
+
+// Betritt das Vorgeschlagene Spiel
+//  Gibt 1 zurück, falls der Vorgang erfolgreich ist, 0 sonnst
+bool SpielClient::spielErstelltAnnehmen()
+{
+    cs.lock();
+    if( !senden )
+    {
+        err = "Der Client ist nicht verbunden.";
+        cs.unlock();
+        return 0;
+    }
+    char ret = 0;
+    senden->sendeEncrypted( "\4", 1 );
+    senden->getNachrichtEncrypted( &ret, 1 );
+    if( ret != 1 )
+        err = "Fehler beim annehmen des Spiels.";
+    cs.unlock();
+    return ret == 1;
+}
+
+// Lehnt das Vorgeschlagene Spiel ab
+//  Gibt 1 zurück, falls der Vorgang erfolgreich ist, 0 sonnst
+bool SpielClient::spielErstelltAblehnen()
+{
+    cs.lock();
+    if( !senden )
+    {
+        err = "Der Client ist nicht verbunden.";
+        cs.unlock();
+        return 0;
+    }
+    char ret = 0;
+    senden->sendeEncrypted( "\5", 1 );
+    senden->getNachrichtEncrypted( &ret, 1 );
+    if( ret != 1 )
+        err = "Fehler beim ablehnen des Spiels.";
+    cs.unlock();
+    return ret == 1;
+}
+
+// Wechselt zu einem bestimmten Team
+//  team: Die Id des teams
+//  Gibt 1 zurück, falls der Vorgang erfolgreich ist, 0 sonnst
+bool SpielClient::spielErstelltTeamWechseln( int team )
+{
+    cs.lock();
+    if( !senden )
+    {
+        err = "Der Client ist nicht verbunden.";
+        cs.unlock();
+        return 0;
+    }
+    char ret = 0;
+    senden->sendeEncrypted( "\6", 1 );
+    senden->getNachrichtEncrypted( &ret, 1 );
+    if( !ret )
+    {
+        err = "Fehler beim wechseln des Teams.";
+        cs.unlock();
+        return 0;
+    }
+    senden->sendeEncrypted( (char*)&team, 4 );
+    senden->getNachrichtEncrypted( &ret, 1 );
+    if( ret != 1 )
+        err = "Fehler beim wechseln des Teams.";
+    cs.unlock();
+    return ret == 1;
+}
+
+// Bestätigt die Teamauswahl so dass das Spiel früher beginnen kann
+//  Gibt 1 zurück, falls der Vorgang erfolgreich ist, 0 sonnst
+bool SpielClient::spielErstelltTeamFertig()
+{
+    cs.lock();
+    if( !senden )
+    {
+        err = "Der Client ist nicht verbunden.";
+        cs.unlock();
+        return 0;
+    }
+    char ret = 0;
+    senden->sendeEncrypted( "\xE", 1 );
+    senden->getNachrichtEncrypted( &ret, 1 );
+    if( ret != 1 )
+        err = "Fehler beim setzen der Bereitschaft.";
+    cs.unlock();
+    return ret == 1;
+}
+
+// sendet eine Chat Nachricht an die mitglieder des erstellten Spiels
+//  nachricht: Die Nachricht
+//  Gibt 1 zurück, falls der Vorgang erfolgreich ist, 0 sonnst
+bool SpielClient::spielErstelltChatNachricht( char *nachricht )
+{
+    char län = textLength( nachricht );
+    if( !län )
+        return 1;
+    cs.lock();
+    if( !senden )
+    {
+        err = "Der Client ist nicht verbunden.";
+        cs.unlock();
+        return 0;
+    }
+    char ret = 0;
+    senden->sendeEncrypted( "\7", 1 );
+    senden->getNachrichtEncrypted( &ret, 1 );
+    if( !ret )
+    {
+        err = "Fehler beim senden der Chat Nachricht.";
+        cs.unlock();
+        return 0;
+    }
+    senden->sendeEncrypted( &län, 1 );
+    senden->sendeEncrypted( nachricht, län );
+    senden->getNachrichtEncrypted( &ret, 1 );
+    if( ret != 1 )
+        err = "Fehler beim senden der Chat Nachricht.";
+    cs.unlock();
+    return ret == 1;
+}
+
+// Teilt dem Server mit, dass der Client bereit ist das Spiel zu laden
+//  Gibt 1 zurück, falls der Vorgang erfolgreich ist, 0 sonnst
+bool SpielClient::bereitZumLaden()
+{
+    cs.lock();
+    if( !senden )
+    {
+        err = "Der Client ist nicht verbunden.";
+        cs.unlock();
+        return 0;
+    }
+    char ret = 0;
+    senden->sendeEncrypted( "\x9", 1 );
+    senden->getNachrichtEncrypted( &ret, 1 );
+    if( ret != 1 )
+        err = "Fehler beim setzen der Bereitschaft.";
+    cs.unlock();
+    return ret == 1;
+}
+
+// Teilt dem Server mit, zu wie viel Prozent der Client das Spiel geladen hat
+//  Gibt 1 zurück, falls der Vorgang erfolgreich ist, 0 sonnst
+bool SpielClient::setLadenProzent( int prozent )
+{
+    cs.lock();
+    if( !senden )
+    {
+        err = "Der Client ist nicht verbunden.";
+        cs.unlock();
+        return 0;
+    }
+    char ret = 0;
+    senden->sendeEncrypted( "\xC", 1 );
+    senden->getNachrichtEncrypted( &ret, 1 );
+    if( ret )
+    {
+        senden->sendeEncrypted( (char*)&prozent, 4 );
+        senden->getNachrichtEncrypted( &ret, 1 );
+    }
+    if( ret != 1 )
+        err = "Fehler beim setzen des Fortschritts.";
+    cs.unlock();
+    return ret == 1;
+}
+
+// Teilt dem Server mit, dass das Spiel fertig geladen wurde
+//  Gibt 1 zurück, falls der Vorgang erfolgreich ist, 0 sonnst
+bool SpielClient::bereitZumSpiel()
+{
+    cs.lock();
+    if( !senden )
+    {
+        err = "Der Client ist nicht verbunden.";
+        cs.unlock();
+        return 0;
+    }
+    char ret = 0;
+    senden->sendeEncrypted( "\xA", 1 );
+    senden->getNachrichtEncrypted( &ret, 1 );
+    if( ret != 1 )
+        err = "Fehler beim setzen der Bereitschaft.";
+    cs.unlock();
+    return ret == 1;
+}
+
+// Sendet während des Spiels eine Nachricht an den Server
+//  län: Die Länge der Nachricht
+//  bytes: Ein Zeiger auf die Nachricht
+//  Gibt 1 zurück, falls der Vorgang erfolgreich ist, 0 sonnst
+bool SpielClient::spielNachricht( short län, char *bytes )
+{
+    cs.lock();
+    if( !senden )
+    {
+        err = "Der Client ist nicht verbunden.";
+        cs.unlock();
+        return 0;
+    }
+    senden->sendeEncrypted( "\xB", 1 );
+    senden->sende( (char*)&län, 2 );
+    senden->sende( bytes, län );
+    cs.unlock();
+    return 1;
+}
+
+// Sendet während der Statistik eine Nachricht an den Server
+//  län: Die Länge der Nachricht
+//  bytes: Ein Zeiger auf die Nachricht
+//  Gibt 1 zurück, falls der Vorgang erfolgreich ist, 0 sonnst
+bool SpielClient::statistikNachricht( short län, char *bytes )
+{
+    cs.lock();
+    if( !senden )
+    {
+        err = "Der Client ist nicht verbunden.";
+        cs.unlock();
+        return 0;
+    }
+    char ret = 0;
+    senden->sendeEncrypted( "\xD", 1 );
+    senden->getNachrichtEncrypted( &ret, 1 );
+    if( ret )
+    {
+        senden->sendeEncrypted( (char*)&län, 2 );
+        senden->sendeEncrypted( bytes, län );
+        senden->getNachrichtEncrypted( &ret, 1 );
+    }
+    if( ret != 1 )
+        err = "Fehler beim setzen der Statistik Nachricht.";
+    cs.unlock();
+    return ret == 1;
+}
+
+// Wartet auf eine Nachricht vom Spiel Server.
+//  Gibt bei Erfolg 1 zurück, 0 sonnst
+//  nachricht: Eine Referenz auf die Struktur, in der die Nachricht gespeichert werden soll
+bool SpielClient::getNextMessage( SpielServerNachricht &nachricht )
+{
+    do
+    {
+        if( !empfangen->getNachrichtEncrypted( &nachricht.type, 1 ) )
+        {
+            return 0;
+        }
+        switch( nachricht.type )
+        {
+        case 0: // verbindung getrennt
+            trenne();
+            break;
+        case 1: // verbleibende Zeit
+            empfangen->getNachrichtEncrypted( &nachricht.sekunden, 1 );
+            break;
+        case 2: // SpielErstellt abbruch
+            if( 1 )
+            {
+                char län = 0;
+                empfangen->getNachrichtEncrypted( &län, 1 );
+                char *grund = new char[ län + 1 ];
+                grund[ län ] = 0;
+                empfangen->getNachrichtEncrypted( grund, län );
+                nachricht.message = grund;
+                delete[] grund;
+            }
+            break;
+        case 3: // Fehler
+            if( 1 )
+            {
+                char länge = 0;
+                empfangen->getNachrichtEncrypted( &länge, 1 );
+                char *txt = new char[ länge + 1 ];
+                txt[ länge ] = 0;
+                empfangen->getNachrichtEncrypted( txt, länge );
+                nachricht.message = txt;
+                delete[]txt;
+            }
+            break;
+        case 4: // zurück in Warteschlange
+            empfangen->getNachrichtEncrypted( &nachricht.stunden, 1 );
+            empfangen->getNachrichtEncrypted( &nachricht.minuten, 1 );
+            empfangen->getNachrichtEncrypted( &nachricht.sekunden, 1 );
+            break;
+        case 6: // SpielErstellt Initialisierung
+            empfangen->getNachrichtEncrypted( (char*)&nachricht.sts->spielerAnzahl, 4 );
+            empfangen->getNachrichtEncrypted( (char*)&nachricht.sts->teamAnzahl, 4 );
+            for( int i = 0; i < nachricht.sts->spielerAnzahl; i++ )
+            {
+                int farbe = 0;
+                empfangen->getNachrichtEncrypted( (char*)&farbe, 4 );
+                nachricht.sts->spielerFarbe->set( farbe, i );
+            }
+            for( int i = 0; i < nachricht.sts->teamAnzahl; i++ )
+            {
+                int farbe = 0;
+                empfangen->getNachrichtEncrypted( (char*)&farbe, 4 );
+                nachricht.sts->teamFarbe->set( farbe, i );
+            }
+            for( int i = 0; i < nachricht.sts->teamAnzahl; i++ )
+            {
+                char län = 0;
+                empfangen->getNachrichtEncrypted( &län, 1 );
+                char *name = new char[ län + 1 ];
+                name[ län ] = 0;
+                if( län )
+                    empfangen->getNachrichtEncrypted( name, län );
+                Text *tmp = new Text( name );
+                delete[] name;
+                nachricht.sts->teamName->set( tmp, i );
+            }
+            for( int i = 0; i < nachricht.sts->teamAnzahl; i++ )
+            {
+                int größe = 0;
+                empfangen->getNachrichtEncrypted( (char*)&größe, 4 );
+                nachricht.sts->teamGröße->set( größe, i );
+            }
+            break;
+        case 7: // SpielErstellt Spieler hinzugefügt
+            empfangen->getNachrichtEncrypted( (char*)&nachricht.accountId, 4 );
+            break;
+        case 8: // SpielErstellt Spieler entfernt
+            empfangen->getNachrichtEncrypted( (char*)&nachricht.accountId, 4 );
+            break;
+        case 9: // SpielErstellt Spieler wechselt Team
+            empfangen->getNachrichtEncrypted( (char*)&nachricht.accountId, 4 );
+            empfangen->getNachrichtEncrypted( (char*)&nachricht.spielerNummer, 4 );
+            break;
+        case 0xA: // SpielErstellt Chat Nachricht
+            if( 1 )
+            {
+                char län = 0;
+                empfangen->getNachrichtEncrypted( &län, 1 );
+                char *txt = new char[ län + 1 ];
+                txt[ län ] = 0;
+                if( län )
+                    empfangen->getNachrichtEncrypted( txt, län );
+                nachricht.message = txt;
+                delete[] txt;
+            }
+            break;
+        case 0xB: // Spiel gefunden
+            empfangen->getNachrichtEncrypted( (char*)&nachricht.karteId, 4 );
+            break;
+        case 0xD: // Spiel Laden Spieler hinzufügen
+            empfangen->getNachrichtEncrypted( (char*)&nachricht.accountId, 4 );
+            empfangen->getNachrichtEncrypted( (char*)&nachricht.spielerNummer, 4 );
+            break;
+        case 0xE: // Spiel Laden Spieler Prozent
+            empfangen->getNachrichtEncrypted( (char*)&nachricht.accountId, 4 );
+            empfangen->getNachrichtEncrypted( (char*)&nachricht.prozent, 4 );
+            break;
+        case 0xF: // Spiel Laden Spieler Ping
+            empfangen->getNachrichtEncrypted( (char*)&nachricht.accountId, 4 );
+            empfangen->getNachrichtEncrypted( (char*)&nachricht.ping, 4 );
+            break;
+        case 0x10: // ping
+            empfangen->sendeEncrypted( "\1", 1 );
+            break;
+        case 0x12: // Spiel Nachricht
+            empfangen->getNachricht( (char*)&nachricht.län, 2 );
+            nachricht.data = new char[ nachricht.län ];
+            empfangen->getNachricht( nachricht.data, nachricht.län );
+            break;
+        case 0x13: // Statistik Nachricht
+            empfangen->getNachrichtEncrypted( (char*)&nachricht.län, 2 );
+            nachricht.data = new char[ nachricht.län ];
+            empfangen->getNachrichtEncrypted( nachricht.data, nachricht.län );
+            break;
+        case 0x14: // ping
+            empfangen->sendeEncrypted( "\1", 1 );
+            break;
+        }
+    } while( nachricht.type == 0x10 || nachricht.type == 0x14 );
+}
+
+// Erhält die Verbindung aufrecht
+//  Gibt 1 zurück, falls der Vorgang erfolgreich ist, 0 sonnst
+//  Sollte während einer bestehenden Verbindung etwa einmal alle 60 Sekunden aufgerufen werden, da sonst der Router die Verbindung automatisch trennt
+bool SpielClient::keepAlive()
+{
+    if( !senden )
+        return 0;
+    char res = 0;
+    if( !cs.tryLock() )
+        return 1;
+    bool ok = senden->sendeEncrypted( "\xF", 1 );
+    ok &= senden->getNachrichtEncrypted( &res, 1 );
+    cs.unlock();
+    if( res != 1 || !ok )
+    {
+        err = "Die Verbindung zum Spiel Server ist abgebrochen.";
+        trenne();
+        return 0;
+    }
+    return res == 1;
+}
+
+// Trennt die Verbindung zum Server
+//  Gibt 1 zurück, falls der Vorgang erfolgreich ist, 0 sonnst
+//  Sollte erst nach einem erfolgreichen Aufruf von verbinde aufgerufen werden
+bool SpielClient::trenne()
+{
+    cs.lock();
+    if( !senden )
+    {
+        cs.unlock();
+        return 1;
+    }
+    senden->sendeEncrypted( "\3", 1 );
+    char serverReturn = 0;
+    senden->getNachrichtEncrypted( &serverReturn, 1 );
+    senden->trenne();
+    senden = senden->release();
+    empfangen->trenne();
+    empfangen = empfangen->release();
+    cs.unlock();
+    return 1;
+}
+
+// Gibt 1 zurück, falls der Client verbunden ist, 0 sonst
+bool SpielClient::istVerbunden() const
+{
+    return senden != 0;
+}
+
+// gibt den Letzten Fehlertext zuück
+//  sollte erst aufgerufen werden, nachdem eine andere aufgerufene Methode fehlgeschlagen ist
+char *SpielClient::getLetzterFehler() const
+{
+    return err;
+}
+
+// Erhöht den Reference Counter um 1 un gibt this zurück
+SpielServerClient *SpielClient::getThis()
+{
+    ref++;
+    return this;
+}
+
+// Verringert den Reference Counter um 1 und gibt 0 zurück.
+//  Falls der Reference Counter nach dem Aufruf auf 0 ist löscht sich das Objekt selbst 
+SpielServerClient *SpielClient::release()
+{
+    if( !--ref )
+        delete this;
+    return 0;
+}

+ 91 - 0
KSGNetwork/SpielClient.h

@@ -0,0 +1,91 @@
+#pragma once
+
+#include "../Include/KSGNetwork.h"
+#include <Critical.h>
+
+namespace KSGClient
+{
+    // Wird zum Online Spielen verwendet
+    //  Kann nur von eingeloggten Clients verwendet werden
+    class SpielClient : public SpielServerClient
+    {
+    private:
+        int ref;
+        Framework::Text ip;
+        unsigned short port;
+        int cId;
+        Network::Klient *senden;
+        Network::Klient *empfangen;
+        char *key;
+        unsigned char keyLen;
+        Framework::Critical cs;
+        Framework::Text err;
+
+    public:
+        // Konstruktor
+        SpielClient( int klientId, unsigned short port, char *ip, char *key, unsigned char keyLen );
+        // Destruktor
+        ~SpielClient();
+        // verbindet sich mit dem zugewiesenen Karten Server
+        //  Gibt 1 zurück, falls der Vorgang erfolgreich ist, 0 sonnst
+        bool verbinde() override;
+        // Betritt das Vorgeschlagene Spiel
+        //  Gibt 1 zurück, falls der Vorgang erfolgreich ist, 0 sonnst
+        bool spielErstelltAnnehmen() override;
+        // Lehnt das Vorgeschlagene Spiel ab
+        //  Gibt 1 zurück, falls der Vorgang erfolgreich ist, 0 sonnst
+        bool spielErstelltAblehnen() override;
+        // Wechselt zu einem bestimmten Team
+        //  team: Die Id des teams
+        //  Gibt 1 zurück, falls der Vorgang erfolgreich ist, 0 sonnst
+        bool spielErstelltTeamWechseln( int team ) override;
+        // Bestätigt die Teamauswahl so dass das Spiel früher beginnen kann
+        //  Gibt 1 zurück, falls der Vorgang erfolgreich ist, 0 sonnst
+        bool spielErstelltTeamFertig() override;
+        // sendet eine Chat Nachricht an die mitglieder des erstellten Spiels
+        //  nachricht: Die Nachricht
+        //  Gibt 1 zurück, falls der Vorgang erfolgreich ist, 0 sonnst
+        bool spielErstelltChatNachricht( char *nachricht ) override;
+        // Teilt dem Server mit, dass der Client bereit ist das Spiel zu laden
+        //  Gibt 1 zurück, falls der Vorgang erfolgreich ist, 0 sonnst
+        bool bereitZumLaden() override;
+        // Teilt dem Server mit, zu wie viel Prozent der Client das Spiel geladen hat
+        //  Gibt 1 zurück, falls der Vorgang erfolgreich ist, 0 sonnst
+        bool setLadenProzent( int prozent ) override;
+        // Teilt dem Server mit, dass das Spiel fertig geladen wurde
+        //  Gibt 1 zurück, falls der Vorgang erfolgreich ist, 0 sonnst
+        bool bereitZumSpiel() override;
+        // Sendet während des Spiels eine Nachricht an den Server
+        //  län: Die Länge der Nachricht
+        //  bytes: Ein Zeiger auf die Nachricht
+        //  Gibt 1 zurück, falls der Vorgang erfolgreich ist, 0 sonnst
+        bool spielNachricht( short län, char *bytes ) override;
+        // Sendet während der Statistik eine Nachricht an den Server
+        //  län: Die Länge der Nachricht
+        //  bytes: Ein Zeiger auf die Nachricht
+        //  Gibt 1 zurück, falls der Vorgang erfolgreich ist, 0 sonnst
+        bool statistikNachricht( short län, char *bytes ) override;
+        // Wartet auf eine Nachricht vom Spiel Server.
+        //  Gibt bei Erfolg 1 zurück, 0 sonnst
+        //  nachricht: Eine Referenz auf die Struktur, in der die Nachricht gespeichert werden soll
+        bool getNextMessage( SpielServerNachricht &nachricht ) override;
+        // Erhält die Verbindung aufrecht
+        //  Gibt 1 zurück, falls der Vorgang erfolgreich ist, 0 sonnst
+        //  Sollte während einer bestehenden Verbindung etwa einmal alle 60 Sekunden aufgerufen werden, da sonst der Router die Verbindung automatisch trennt
+        bool keepAlive() override;
+        // Trennt die Verbindung zum Server
+        //  Gibt 1 zurück, falls der Vorgang erfolgreich ist, 0 sonnst
+        //  Sollte erst nach einem erfolgreichen Aufruf von verbinde aufgerufen werden
+        bool trenne() override;
+        // Gibt 1 zurück, falls der Client verbunden ist, 0 sonst
+        bool istVerbunden() const override;
+        // gibt den Letzten Fehlertext zuück
+        //  sollte erst aufgerufen werden, nachdem eine andere aufgerufene Methode fehlgeschlagen ist
+        char *getLetzterFehler() const override;
+        // Erhöht den Reference Counter um 1 un gibt this zurück
+        SpielServerClient *getThis() override;
+        // Verringert den Reference Counter um 1 und gibt 0 zurück.
+        //  Falls der Reference Counter nach dem Aufruf auf 0 ist löscht sich das Objekt selbst 
+        SpielServerClient *release() override;
+    };
+}