#include "../KSGKlient.h" #include "../KSGServer.h" #include "../../Global/Variablen.h" #include "../Keys.h" // Inhalt der SpielKlient Klasse aus KSGKlient.h // Konstruktor SpielKlient::SpielKlient() : Thread() { verbunden = 0; senden = 0; empfangen = 0; fehler = new Text( "" ); klientId = getKlientId(); ref = 1; } // Destruktor SpielKlient::~SpielKlient() { cs.lock(); if( senden ) { char serverReturn = 0; if( verbunden ) { senden->sendeEncrypted( "\3", 1 ); senden->getNachrichtEncrypted( &serverReturn, 1 ); senden->trenne(); } senden = senden->release(); verbunden = 0; if( empfangen ) { warteAufThread( 5000 ); ende(); empfangen->trenne(); empfangen = empfangen->release(); } } fehler = fehler->release(); cs.unlock(); } // nicht constant bool SpielKlient::verbinde( unsigned short port, char *ip ) // verbindet ich mit dem Spiel Server { cs.lock(); if( verbunden ) { cs.unlock(); return 1; } if( !senden ) senden = new 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*)&klientId, 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 ); fehler->setText( f ); delete[]f; } senden->sendeEncrypted( "\3", 1 ); senden->getNachrichtEncrypted( &serverReturn, 1 ); senden->trenne(); WMessageBox( 0, new Text( "Fehler" ), new Text( "Server akzeptiert den Klient nicht" ), MB_ICONERROR ); cs.unlock(); return 0; } char *sl = 0; char slLän = getSchlüssel( &sl ); senden->setSendeKey( sl, slLän ); senden->setEmpfangKey( sl, slLän ); delete[] sl; if( !empfangen ) empfangen = new 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() ) ) { start(); verbunden = 1; cs.unlock(); return 1; } else { fehler->setText( "Der dir zugewiesene Spiel Server kann dir keine Nachrichten senden." ); cs.unlock(); return 1; } } else { fehler->setText( "Der dir zugewiesene Spiel Server hat die Verbindung abgebrochen. Bitte versuche es Später erneut." ); senden = senden->release(); } } else { fehler->setText( "Der dir zugewiesene Spiel Server antwortet nicht. Bitte versuche es Später erneut." ); senden = senden->release(); } cs.unlock(); return 0; } bool SpielKlient::spielErstelltAnnehmen() // klient ist bereit dem erstellten Spiel beizutreten { if( !senden ) return 0; char ret = 0; cs.lock(); senden->sendeEncrypted( "\4", 1 ); senden->getNachrichtEncrypted( &ret, 1 ); cs.unlock(); return ret == 1; } bool SpielKlient::spielErstelltAblehnen() // klient ist nicht bereit dem erstellten Spiel beizutreten { if( !senden ) return 0; char ret = 0; cs.lock(); senden->sendeEncrypted( "\5", 1 ); senden->getNachrichtEncrypted( &ret, 1 ); cs.unlock(); return ret == 1; } bool SpielKlient::spielErstelltTeamWechseln( int team ) // wechselt das Team { if( !senden ) return 0; char ret = 0; cs.lock(); senden->sendeEncrypted( "\6", 1 ); senden->getNachrichtEncrypted( &ret, 1 ); if( !ret ) { cs.unlock(); return 0; } senden->sendeEncrypted( (char*)&team, 4 ); senden->getNachrichtEncrypted( &ret, 1 ); cs.unlock(); return ret == 1; } bool SpielKlient::spielErstelltTeamFertig() // bestetigt die Team Auswahl { if( !senden ) return 0; char ret = 0; cs.lock(); senden->sendeEncrypted( "\xE", 1 ); senden->getNachrichtEncrypted( &ret, 1 ); cs.unlock(); return ret == 1; } bool SpielKlient::spielErstelltChatNachricht( char *nachricht ) // sendet eine Chat Nachricht an die mitglieder des erstellten Spiels { char län = textLength( nachricht ); if( !län ) return 1; if( !senden ) return 0; char ret = 0; cs.lock(); senden->sendeEncrypted( "\7", 1 ); senden->getNachrichtEncrypted( &ret, 1 ); if( !ret ) { cs.unlock(); return 0; } senden->sendeEncrypted( &län, 1 ); senden->sendeEncrypted( nachricht, län ); senden->getNachrichtEncrypted( &ret, 1 ); cs.unlock(); return ret == 1; } bool SpielKlient::bereitZumLaden() // Klient ist bereit zum Laden { if( !senden ) return 0; char ret = 0; cs.lock(); senden->sendeEncrypted( "\x9", 1 ); senden->getNachrichtEncrypted( &ret, 1 ); cs.unlock(); return ret == 1; } bool SpielKlient::setLadenProzent( int prozent ) // Setzt den Fortschritt des Klients { if( !senden ) return 0; char ret = 0; cs.lock(); senden->sendeEncrypted( "\xC", 1 ); senden->getNachrichtEncrypted( &ret, 1 ); if( ret ) { senden->sendeEncrypted( (char*)&prozent, 4 ); senden->getNachrichtEncrypted( &ret, 1 ); } cs.unlock(); return ret == 1; } bool SpielKlient::bereitZumSpiel() // Klient ist bereit zum Spiel { if( !senden ) return 0; char ret = 0; cs.lock(); senden->sendeEncrypted( "\xA", 1 ); senden->getNachrichtEncrypted( &ret, 1 ); cs.unlock(); return ret == 1; } bool SpielKlient::spielNachricht( short län, char *bytes ) // Nachricht während des Spiels { if( !senden ) return 0; cs.lock(); senden->sendeEncrypted( "\xB", 1 ); senden->sende( (char*)&län, 2 ); senden->sende( bytes, län ); cs.unlock(); return 1; } bool SpielKlient::statistikNachricht( short län, char *bytes ) // Nachricht während der Statistik { if( !senden ) return 0; char ret = 0; cs.lock(); 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 ); } cs.unlock(); return ret == 1; } bool SpielKlient::keepAlive() // Erhält die Verbindung aufrecht { if( !verbunden ) return 0; char res = 0; if( !cs.tryLock() ) return 1; senden->sendeEncrypted( "\xF", 1 ); senden->getNachrichtEncrypted( &res, 1 ); cs.unlock(); if( res != 1 ) trenne(); return res == 1; } bool SpielKlient::trenne() // trennt sich von dem Chat Server { if( !verbunden ) return 1; verbunden = 0; cs.lock(); senden->sendeEncrypted( "\3", 1 ); char serverReturn = 0; senden->getNachrichtEncrypted( &serverReturn, 1 ); senden->trenne(); warteAufThread( 2000 ); empfangen->trenne(); cs.unlock(); run = 0; ende(); return 1; } void SpielKlient::thread() // empfangen von Nachrichten { if( !verbunden || !empfangen || !senden ) return; empfangen->sendeEncrypted( "\1", 1 ); empfangen->sendeEncrypted( (char*)&klientId, 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 ); fehler->setText( nachricht ); delete[]nachricht; } if( res == 1 ) { char *sl = 0; char slLän = getSchlüssel( &sl ); empfangen->setSendeKey( sl, slLän ); empfangen->setEmpfangKey( sl, slLän ); delete[] sl; } else if( res != 0 ) { WMessageBox( 0, new Text( "Fehler" ), new Text( "Server hat keine Verwendung für den Client." ), MB_ICONERROR ); return; } char befehl = 0; while( verbunden ) { if( !empfangen->getNachrichtEncrypted( &befehl, 1 ) ) { run = 0; return; } switch( befehl ) { case 0: // verbindung getrennt trenne(); run = 0; return; case 1: // verbleibende Zeit if( 1 ) { char sekunden = 0; empfangen->getNachrichtEncrypted( &sekunden, 1 ); if( nachLogin && nachLogin->zSpielenFenster() ) nachLogin->zSpielenFenster()->spielGefundenZeitVerbleibend( sekunden ); } 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 ); if( nachLogin && nachLogin->zNachrichtenListe() ) nachLogin->zNachrichtenListe()->addNachricht( new Text( "Spiel Abgebrochen" ), new Text( grund ), new Text( "Ok" ), 0, NachrichtType::nachricht, 0 ); if( nachLogin && nachLogin->zSpielenFenster() ) nachLogin->zSpielenFenster()->spielGefundenAbbruch(); 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 ); hauptScreen->lock(); if( nachLogin && nachLogin->zNachrichtenListe() ) nachLogin->zNachrichtenListe()->addNachricht( new Text( "Fehler" ), new Text( txt ), new Text( "Ok" ), 0, NachrichtType::nachricht, 0 ); hauptScreen->unlock(); delete[]txt; } break; case 4: // zurück in Warteschlange if( 1 ) { char stunden = 0; char minuten = 0; char sekunden = 0; empfangen->getNachrichtEncrypted( &stunden, 1 ); empfangen->getNachrichtEncrypted( &minuten, 1 ); empfangen->getNachrichtEncrypted( &sekunden, 1 ); if( nachLogin && nachLogin->zSpielenFenster() ) nachLogin->zSpielenFenster()->zurückInWarteschlange( stunden, minuten, sekunden ); } break; case 5: // Erstellung fortsetzen if( nachLogin && nachLogin->zSpielenFenster() ) nachLogin->zSpielenFenster()->teamAuswahlBetreten(); break; case 6: // SpielErstellt Initialisierung if( 1 ) { SpielerTeamStruktur *sts = new SpielerTeamStruktur(); empfangen->getNachrichtEncrypted( (char*)&sts->spielerAnzahl, 4 ); empfangen->getNachrichtEncrypted( (char*)&sts->teamAnzahl, 4 ); for( int i = 0; i < sts->spielerAnzahl; i++ ) { int farbe = 0; empfangen->getNachrichtEncrypted( (char*)&farbe, 4 ); sts->spielerFarbe->set( farbe, i ); } for( int i = 0; i < sts->teamAnzahl; i++ ) { int farbe = 0; empfangen->getNachrichtEncrypted( (char*)&farbe, 4 ); sts->teamFarbe->set( farbe, i ); } for( int i = 0; i < 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; sts->teamName->set( tmp, i ); } for( int i = 0; i < sts->teamAnzahl; i++ ) { int größe = 0; empfangen->getNachrichtEncrypted( (char*)&größe, 4 ); sts->teamGröße->set( größe, i ); } if( nachLogin && nachLogin->zSpielenFenster() ) nachLogin->zSpielenFenster()->teamAuswahlInit( sts ); else sts->release(); } break; case 7: // SpielErstellt Spieler hinzugefügt if( 1 ) { int accountId = 0; empfangen->getNachrichtEncrypted( (char*)&accountId, 4 ); if( nachLogin && nachLogin->zSpielenFenster() ) nachLogin->zSpielenFenster()->teamAuswahlAddSpieler( accountId ); } break; case 8: // SpielErstellt Spieler entfernt if( 1 ) { int accountId = 0; empfangen->getNachrichtEncrypted( (char*)&accountId, 4 ); if( nachLogin && nachLogin->zSpielenFenster() ) nachLogin->zSpielenFenster()->teamAuswahlRemoveSpieler( accountId ); } break; case 9: // SpielErstellt Spieler wechselt Team if( 1 ) { int accountId = 0; int spielerNummer = 0; empfangen->getNachrichtEncrypted( (char*)&accountId, 4 ); empfangen->getNachrichtEncrypted( (char*)&spielerNummer, 4 ); if( nachLogin && nachLogin->zSpielenFenster() ) nachLogin->zSpielenFenster()->teamAuswahlSpielerWehseltTeam( accountId, spielerNummer ); } break; case 0xA: // SpielErstellt Chat Nachricht if( 1 ) { char län = 0; empfangen->getNachrichtEncrypted( &län, 1 ); char *nachricht = new char[ län + 1 ]; nachricht[ län ] = 0; if( län ) empfangen->getNachrichtEncrypted( nachricht, län ); if( nachLogin && nachLogin->zSpielenFenster() ) nachLogin->zSpielenFenster()->teamAuswahlChatNachricht( nachricht ); delete[] nachricht; } break; case 0xB: // Spiel gefunden if( 1 ) { int karteId = 0; empfangen->getNachrichtEncrypted( (char*)&karteId, 4 ); if( nachLogin && nachLogin->zSpielenFenster() ) nachLogin->zSpielenFenster()->spielGefunden( karteId ); } break; case 0xC: // Spiel Laden beginnen aktion = 5; break; case 0xD: // Spiel Laden Spieler hinzufügen if( 1 ) { int accId = 0; int spielerNummer = 0; empfangen->getNachrichtEncrypted( (char*)&accId, 4 ); empfangen->getNachrichtEncrypted( (char*)&spielerNummer, 4 ); if( nachLogin->zImSpiel() && nachLogin->zImSpiel()->istSichtbar() ) nachLogin->zImSpiel()->lBAddSpieler( accId, spielerNummer ); } break; case 0xE: // Spiel Laden Spieler Prozent if( 1 ) { int accId = 0; int prozent = 0; empfangen->getNachrichtEncrypted( (char*)&accId, 4 ); empfangen->getNachrichtEncrypted( (char*)&prozent, 4 ); if( nachLogin->zImSpiel() && nachLogin->zImSpiel()->istSichtbar() ) nachLogin->zImSpiel()->lBSetSpielerProzent( accId, prozent ); } break; case 0xF: // Spiel Laden Spieler Ping if( 1 ) { int accId = 0; int ping = 0; empfangen->getNachrichtEncrypted( (char*)&accId, 4 ); empfangen->getNachrichtEncrypted( (char*)&ping, 4 ); if( nachLogin->zImSpiel() && nachLogin->zImSpiel()->istSichtbar() ) nachLogin->zImSpiel()->lBSetSpielerPing( accId, ping ); } break; case 0x10: // ping empfangen->sendeEncrypted( "\1", 1 ); break; case 0x11: // Spiel Laden Fertig if( nachLogin->zImSpiel() && nachLogin->zImSpiel()->istSichtbar() ) nachLogin->zImSpiel()->endLaden(); break; case 0x12: // Spiel Nachricht if( 1 ) { short län = 0; empfangen->getNachricht( (char*)&län, 2 ); char *n = new char[ län ]; empfangen->getNachricht( n, län ); if( nachLogin->zImSpiel() && nachLogin->zImSpiel()->istSichtbar() ) nachLogin->zImSpiel()->spielNachricht( län, n ); delete[] n; } break; case 0x13: // Statistik Nachricht if( 1 ) { short län = 0; empfangen->getNachrichtEncrypted( (char*)&län, 2 ); char *n = new char[ län ]; empfangen->getNachrichtEncrypted( n, län ); if( nachLogin && nachLogin->zSpielenFenster() ) nachLogin->zSpielenFenster()->statistikNachricht( län, n ); delete[] n; } break; case 0x14: // ping empfangen->sendeEncrypted( "\1", 1 ); break; default: // Unbekannte Servernachricht if( nachLogin && nachLogin->zNachrichtenListe() ) { hauptScreen->lock(); nachLogin->zNachrichtenListe()->addNachricht( new Text( "Fehler" ), new Text( "Unbekannte Nachricht vom Server. Eventuel ist der Client nicht mehr Aktuell." ), new Text( "Ok" ), 0, NachrichtType::nachricht, 0 ); hauptScreen->unlock(); } break; } } run = 0; } // constant bool SpielKlient::istVerbunden() const // prüft, ob mit Chat Server verbunden { return verbunden; } char *SpielKlient::getLetzterFehler() const // gibt den Letzten Fehlertext zuück { return fehler->getText(); } // Reference Counting SpielKlientV *SpielKlient::getThis() { ref++; return this; } SpielKlientV *SpielKlient::release() { ref--; if( !ref ) delete this; return 0; }