#include "../KSGKlient.h" #include "../KSGServer.h" #include "../../Global/Variablen.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; InitializeCriticalSection( &cs ); } // Destruktor SpielKlient::~SpielKlient() { LOCK( &cs ); if( senden ) { char serverReturn = 0; if( verbunden ) { senden->sendeVerschlüsselt( "\3", 1 ); senden->getNachrichtVerschlüsselt( &serverReturn, 1 ); senden->trenne(); } senden = senden->release(); verbunden = 0; if( empfangen ) { warteAufThread( 5000 ); ende(); empfangen->trenne(); empfangen = empfangen->release(); } } fehler = fehler->release(); UNLOCK( &cs ); DeleteCriticalSection( &cs ); } // nicht constant bool SpielKlient::verbinde( unsigned short port, char *ip ) // verbindet ich mit dem Spiel Server { LOCK( &cs ); if( verbunden ) { UNLOCK( &cs ); return 1; } if( !senden ) senden = new Klient(); unsigned char schlüssel[ 20 ] = { 253, 234, 211, 132, 121, 230, 95, 145, 201, 13, 43, 77, 153, 223, 253, 69, 234, 43, 52, 99 }; senden->setSendeSchlüssel( (char*)schlüssel, 20 ); senden->setEmpfangSchlüssel( (char*)schlüssel, 20 ); if( senden->verbinde( port, ip ) ) { if( senden->sendeVerschlüsselt( "\1", 1 ) ) { char serverReturn = 0; senden->sendeVerschlüsselt( (char*)&klientId, 4 ); char ret = 0; senden->getNachrichtVerschlüsselt( &ret, 1 ); if( ret != 1 ) { if( ret == 3 ) { char byte = 0; senden->getNachrichtVerschlüsselt( &byte, 1 ); char *f = new char[ byte + 1 ]; f[ byte ] = 0; senden->getNachrichtVerschlüsselt( f, byte ); fehler->setText( f ); delete[]f; } senden->sendeVerschlüsselt( "\3", 1 ); senden->getNachrichtVerschlüsselt( &serverReturn, 1 ); senden->trenne(); WMessageBox( 0, new Text( "Fehler" ), new Text( "Server akzeptiert den Klient nicht" ), MB_ICONERROR ); UNLOCK( &cs ); return 0; } char *sl = 0; char slLän = getSchlüssel( &sl ); senden->setSendeSchlüssel( sl, slLän ); senden->setEmpfangSchlüssel( sl, slLän ); delete[] sl; if( !empfangen ) empfangen = new Klient(); unsigned char schlüssel[ 20 ] = { 253, 234, 211, 132, 121, 230, 95, 145, 201, 13, 43, 77, 153, 223, 253, 69, 234, 43, 52, 99 }; empfangen->setSendeSchlüssel( (char*)schlüssel, 20 ); empfangen->setEmpfangSchlüssel( (char*)schlüssel, 20 ); if( empfangen->verbinde( senden->getServerPort(), senden->getServerIp() ) ) { start(); verbunden = 1; UNLOCK( &cs ); return 1; } else { fehler->setText( "Der dir zugewiesene Spiel Server kann dir keine Nachrichten senden." ); UNLOCK( &cs ); 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(); } UNLOCK( &cs ); return 0; } bool SpielKlient::spielErstelltAnnehmen() // klient ist bereit dem erstellten Spiel beizutreten { if( !senden ) return 0; char ret = 0; LOCK( &cs ); senden->sendeVerschlüsselt( "\4", 1 ); senden->getNachrichtVerschlüsselt( &ret, 1 ); UNLOCK( &cs ); return ret == 1; } bool SpielKlient::spielErstelltAblehnen() // klient ist nicht bereit dem erstellten Spiel beizutreten { if( !senden ) return 0; char ret = 0; LOCK( &cs ); senden->sendeVerschlüsselt( "\5", 1 ); senden->getNachrichtVerschlüsselt( &ret, 1 ); UNLOCK( &cs ); return ret == 1; } bool SpielKlient::spielErstelltTeamWechseln( int team ) // wechselt das Team { if( !senden ) return 0; char ret = 0; LOCK( &cs ); senden->sendeVerschlüsselt( "\6", 1 ); senden->getNachrichtVerschlüsselt( &ret, 1 ); if( !ret ) { UNLOCK( &cs ); return 0; } senden->sendeVerschlüsselt( (char*)&team, 4 ); senden->getNachrichtVerschlüsselt( &ret, 1 ); UNLOCK( &cs ); return ret == 1; } bool SpielKlient::spielErstelltTeamFertig() // bestetigt die Team Auswahl { if( !senden ) return 0; char ret = 0; LOCK( &cs ); senden->sendeVerschlüsselt( "\xE", 1 ); senden->getNachrichtVerschlüsselt( &ret, 1 ); UNLOCK( &cs ); return ret == 1; } bool SpielKlient::spielErstelltChatNachricht( char *nachricht ) // sendet eine Chat Nachricht an die mitglieder des erstellten Spiels { char län = textLänge( nachricht ); if( !län ) return 1; if( !senden ) return 0; char ret = 0; LOCK( &cs ); senden->sendeVerschlüsselt( "\7", 1 ); senden->getNachrichtVerschlüsselt( &ret, 1 ); if( !ret ) { UNLOCK( &cs ); return 0; } senden->sendeVerschlüsselt( &län, 1 ); senden->sendeVerschlüsselt( nachricht, län ); senden->getNachrichtVerschlüsselt( &ret, 1 ); UNLOCK( &cs ); return ret == 1; } bool SpielKlient::bereitZumLaden() // Klient ist bereit zum Laden { if( !senden ) return 0; char ret = 0; LOCK( &cs ); senden->sendeVerschlüsselt( "\x9", 1 ); senden->getNachrichtVerschlüsselt( &ret, 1 ); UNLOCK( &cs ); return ret == 1; } bool SpielKlient::setLadenProzent( int prozent ) // Setzt den Fortschritt des Klients { if( !senden ) return 0; char ret = 0; LOCK( &cs ); senden->sendeVerschlüsselt( "\xC", 1 ); senden->getNachrichtVerschlüsselt( &ret, 1 ); if( ret ) { senden->sendeVerschlüsselt( (char*)&prozent, 4 ); senden->getNachrichtVerschlüsselt( &ret, 1 ); } UNLOCK( &cs ); return ret == 1; } bool SpielKlient::bereitZumSpiel() // Klient ist bereit zum Spiel { if( !senden ) return 0; char ret = 0; LOCK( &cs ); senden->sendeVerschlüsselt( "\xA", 1 ); senden->getNachrichtVerschlüsselt( &ret, 1 ); UNLOCK( &cs ); return ret == 1; } bool SpielKlient::spielNachricht( short län, char *bytes ) // Nachricht während des Spiels { if( !senden ) return 0; LOCK( &cs ); senden->sendeVerschlüsselt( "\xB", 1 ); senden->sende( (char*)&län, 2 ); senden->sende( bytes, län ); UNLOCK( &cs ); return 1; } bool SpielKlient::statistikNachricht( short län, char *bytes ) // Nachricht während der Statistik { if( !senden ) return 0; char ret = 0; LOCK( &cs ); senden->sendeVerschlüsselt( "\xD", 1 ); senden->getNachrichtVerschlüsselt( &ret, 1 ); if( ret ) { senden->sendeVerschlüsselt( (char*)&län, 2 ); senden->sendeVerschlüsselt( bytes, län ); senden->getNachrichtVerschlüsselt( &ret, 1 ); } UNLOCK( &cs ); return ret == 1; } bool SpielKlient::keepAlive() // Erhält die Verbindung aufrecht { if( !verbunden ) return 0; char res = 0; if( !TryEnterCriticalSection( &cs ) ) return 1; senden->sendeVerschlüsselt( "\xF", 1 ); senden->getNachrichtVerschlüsselt( &res, 1 ); UNLOCK( &cs ); if( res != 1 ) trenne(); return res == 1; } bool SpielKlient::trenne() // trennt sich von dem Chat Server { if( !verbunden ) return 1; verbunden = 0; LOCK( &cs ); senden->sendeVerschlüsselt( "\3", 1 ); char serverReturn = 0; senden->getNachrichtVerschlüsselt( &serverReturn, 1 ); senden->trenne(); warteAufThread( 2000 ); empfangen->trenne(); UNLOCK( &cs ); run = 0; ende(); return 1; } void SpielKlient::thread() // empfangen von Nachrichten { if( !verbunden || !empfangen || !senden ) return; empfangen->sendeVerschlüsselt( "\1", 1 ); empfangen->sendeVerschlüsselt( (char*)&klientId, 4 ); char res = 0; empfangen->getNachrichtVerschlüsselt( &res, 1 ); if( res == 3 ) { char län = 0; empfangen->getNachrichtVerschlüsselt( &län, 1 ); char *nachricht = new char[ län + 1 ]; nachricht[ län ] = 0; empfangen->getNachrichtVerschlüsselt( nachricht, län ); fehler->setText( nachricht ); delete[]nachricht; } if( res == 1 ) { char *sl = 0; char slLän = getSchlüssel( &sl ); empfangen->setSendeSchlüssel( sl, slLän ); empfangen->setEmpfangSchlüssel( 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->getNachrichtVerschlüsselt( &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->getNachrichtVerschlüsselt( &sekunden, 1 ); if( nachLogin && nachLogin->zSpielenFenster() ) nachLogin->zSpielenFenster()->spielGefundenZeitVerbleibend( sekunden ); } break; case 2: // SpielErstellt abbruch if( 1 ) { char län = 0; empfangen->getNachrichtVerschlüsselt( &län, 1 ); char *grund = new char[ län + 1 ]; grund[ län ] = 0; empfangen->getNachrichtVerschlüsselt( 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->getNachrichtVerschlüsselt( &länge, 1 ); char *txt = new char[ länge + 1 ]; txt[ länge ] = 0; empfangen->getNachrichtVerschlüsselt( 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->getNachrichtVerschlüsselt( &stunden, 1 ); empfangen->getNachrichtVerschlüsselt( &minuten, 1 ); empfangen->getNachrichtVerschlüsselt( &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->getNachrichtVerschlüsselt( (char*)&sts->spielerAnzahl, 4 ); empfangen->getNachrichtVerschlüsselt( (char*)&sts->teamAnzahl, 4 ); for( int i = 0; i < sts->spielerAnzahl; i++ ) { int farbe = 0; empfangen->getNachrichtVerschlüsselt( (char*)&farbe, 4 ); sts->spielerFarbe->set( farbe, i ); } for( int i = 0; i < sts->teamAnzahl; i++ ) { int farbe = 0; empfangen->getNachrichtVerschlüsselt( (char*)&farbe, 4 ); sts->teamFarbe->set( farbe, i ); } for( int i = 0; i < sts->teamAnzahl; i++ ) { char län = 0; empfangen->getNachrichtVerschlüsselt( &län, 1 ); char *name = new char[ län + 1 ]; name[ län ] = 0; if( län ) empfangen->getNachrichtVerschlüsselt( 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->getNachrichtVerschlüsselt( (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->getNachrichtVerschlüsselt( (char*)&accountId, 4 ); if( nachLogin && nachLogin->zSpielenFenster() ) nachLogin->zSpielenFenster()->teamAuswahlAddSpieler( accountId ); } break; case 8: // SpielErstellt Spieler entfernt if( 1 ) { int accountId = 0; empfangen->getNachrichtVerschlüsselt( (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->getNachrichtVerschlüsselt( (char*)&accountId, 4 ); empfangen->getNachrichtVerschlüsselt( (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->getNachrichtVerschlüsselt( &län, 1 ); char *nachricht = new char[ län + 1 ]; nachricht[ län ] = 0; if( län ) empfangen->getNachrichtVerschlüsselt( nachricht, län ); if( nachLogin && nachLogin->zSpielenFenster() ) nachLogin->zSpielenFenster()->teamAuswahlChatNachricht( nachricht ); delete[] nachricht; } break; case 0xB: // Spiel gefunden if( 1 ) { int karteId = 0; empfangen->getNachrichtVerschlüsselt( (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->getNachrichtVerschlüsselt( (char*)&accId, 4 ); empfangen->getNachrichtVerschlüsselt( (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->getNachrichtVerschlüsselt( (char*)&accId, 4 ); empfangen->getNachrichtVerschlüsselt( (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->getNachrichtVerschlüsselt( (char*)&accId, 4 ); empfangen->getNachrichtVerschlüsselt( (char*)&ping, 4 ); if( nachLogin->zImSpiel() && nachLogin->zImSpiel()->istSichtbar() ) nachLogin->zImSpiel()->lBSetSpielerPing( accId, ping ); } break; case 0x10: // ping empfangen->sendeVerschlüsselt( "\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->getNachrichtVerschlüsselt( (char*)&län, 2 ); char *n = new char[ län ]; empfangen->getNachrichtVerschlüsselt( n, län ); if( nachLogin && nachLogin->zSpielenFenster() ) nachLogin->zSpielenFenster()->statistikNachricht( län, n ); delete[] n; } break; case 0x14: // ping empfangen->sendeVerschlüsselt( "\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; }