#include "../KSGKlient.h" #include "../KSGServer.h" #include "../Keys.h" #include // Inhalt der MinigameClient Klasse // Konstruktor MinigameClient::MinigameClient() { verbunden = 0; fehler = 0; klient = 0; needCapture = 0; klientId = getKlientId(); ref = 1; } // Destruktor MinigameClient::~MinigameClient() { cs.lock(); if( klient ) { char serverReturn = 0; if( verbunden ) { if( needCapture ) klient->sendeEncrypted( "\0\0\0\0", 4 ); needCapture = 0; klient->sendeEncrypted( "\4", 1 ); klient->getNachrichtEncrypted( &serverReturn, 1 ); if( serverReturn == 3 ) { char län = 0; klient->getNachrichtEncrypted( &län, 1 ); char *nachricht = new char[ län + 1 ]; nachricht[ län ] = 0; klient->getNachrichtEncrypted( nachricht, län ); delete[]nachricht; } klient->sendeEncrypted( "\3", 1 ); klient->getNachrichtEncrypted( &serverReturn, 1 ); klient->trenne(); } else { int keyLen = 0; char *key = 0; Keys::getServerKey( &key, keyLen, Keys::MINIGAME, Keys::SENDEN ); klient->setSendeKey( key, keyLen ); delete[] key; Keys::getServerKey( &key, keyLen, Keys::MINIGAME, Keys::EMPFANGEN ); klient->setEmpfangKey( key, keyLen ); delete[] key; klient->verbinde( klient->getServerPort(), klient->getServerIp() ); klient->sendeEncrypted( "\1", 1 ); klient->sendeEncrypted( (char*)&klientId, 4 ); klient->getNachrichtEncrypted( &serverReturn, 1 ); if( serverReturn == 3 ) { char län = 0; klient->getNachrichtEncrypted( &län, 1 ); char *nachricht = new char[ län + 1 ]; nachricht[ län ] = 0; klient->getNachrichtEncrypted( nachricht, län ); delete[]nachricht; } else { char *sl = 0; char slLän = getSchlüssel( &sl ); klient->setSendeKey( sl, slLän ); klient->setEmpfangKey( sl, slLän ); delete[] sl; klient->sendeEncrypted( "\4", 1 ); klient->getNachrichtEncrypted( &serverReturn, 1 ); if( serverReturn == 3 ) { char län = 0; klient->getNachrichtEncrypted( &län, 1 ); char *nachricht = new char[ län + 1 ]; nachricht[ län ] = 0; klient->getNachrichtEncrypted( nachricht, län ); delete[]nachricht; } } klient->sendeEncrypted( "\3", 1 ); klient->getNachrichtEncrypted( &serverReturn, 1 ); klient->trenne(); } klient = klient->release(); } delete[]fehler; cs.unlock(); } // verbindet ich mit dem Minigame Server bool MinigameClient::verbinde() { cs.lock(); if( verbunden ) { cs.unlock(); return 1; } if( !klient ) { char *msIp = getMainServerIp(); unsigned short msPort = getMainServerPort(); Framework::logLine( "Verbinung mit Main Server wird hergestellt..." ); klient = new Klient(); int keyLen = 0; char *key = 0; Keys::getServerKey( &key, keyLen, Keys::MAIN, Keys::SENDEN ); klient->setSendeKey( key, keyLen ); delete[] key; Keys::getServerKey( &key, keyLen, Keys::MAIN, Keys::EMPFANGEN ); klient->setEmpfangKey( key, keyLen ); delete[] key; if( !klient->verbinde( msPort, msIp ) ) { Framework::logLine( "ERROR: Server nicht erreichbar." ); char *err = "Fehler beim verbinden mit dem Main Server. Bitte versuche es Später erneut."; delete[]fehler; fehler = new char[ textLength( err ) + 1 ]; fehler[ textLength( err ) ] = 0; memcpy( fehler, err, textLength( err ) ); klient = klient->release(); delete[]msIp; cs.unlock(); return 0; } delete[]msIp; klient->sende( "\0", 1 ); // verschlüsselung aktivieren klient->sendeEncrypted( "\1", 1 ); klient->sendeEncrypted( (char*)&klientId, 4 ); char serverReturn = 0; klient->getNachrichtEncrypted( &serverReturn, 1 ); if( serverReturn == 3 ) { char byte = 0; klient->getNachrichtEncrypted( &byte, 1 ); delete[]fehler; fehler = new char[ byte + 1 ]; fehler[ byte ] = 0; klient->getNachrichtEncrypted( fehler, byte ); Framework::logLine( Text( "ERROR: " ) += fehler ); klient->sendeEncrypted( "\3", 1 ); klient->getNachrichtEncrypted( &serverReturn, 1 ); klient->trenne(); klient = klient->release(); cs.unlock(); return 0; } char *sl = 0; char slLän = getSchlüssel( &sl ); klient->setSendeKey( sl, slLän ); klient->setEmpfangKey( sl, slLän ); delete[] sl; klient->sendeEncrypted( "\6\xA", 2 ); char byte = 0; klient->getNachrichtEncrypted( &byte, 1 ); if( byte == 2 ) { unsigned char lsIp[ 4 ]; klient->getNachrichtEncrypted( (char *)lsIp, 4 ); unsigned short lsPort = 0; klient->getNachrichtEncrypted( (char*)&lsPort, 2 ); klient->sendeEncrypted( "\3", 1 ); klient->getNachrichtEncrypted( &serverReturn, 1 ); klient->trenne(); Text *lsIpT = new Text( "" ); lsIpT->append( (int)lsIp[ 0 ] ); lsIpT->append( "." ); lsIpT->append( (int)lsIp[ 1 ] ); lsIpT->append( "." ); lsIpT->append( (int)lsIp[ 2 ] ); lsIpT->append( "." ); lsIpT->append( (int)lsIp[ 3 ] ); Framework::logLine( ( ( Text( "Zugeteilter Minigame Server:" ) += lsIpT->getText() ) += ":" ) += lsPort ); int keyLen = 0; char *key = 0; Keys::getServerKey( &key, keyLen, Keys::MINIGAME, Keys::SENDEN ); klient->setSendeKey( key, keyLen ); delete[] key; Keys::getServerKey( &key, keyLen, Keys::MINIGAME, Keys::EMPFANGEN ); klient->setEmpfangKey( key, keyLen ); delete[] key; klient->verbinde( lsPort, lsIpT->getText() ); lsIpT = lsIpT->release(); klient->sendeEncrypted( "\3", 1 ); klient->getNachrichtEncrypted( &serverReturn, 1 ); klient->trenne(); } if( byte == 3 ) { klient->getNachrichtEncrypted( &byte, 1 ); delete[]fehler; fehler = new char[ byte + 1 ]; fehler[ byte ] = 0; klient->getNachrichtEncrypted( fehler, byte ); Framework::logLine( Text( "ERROR: " ) += fehler ); klient->sendeEncrypted( "\3", 1 ); klient->getNachrichtEncrypted( &serverReturn, 1 ); klient->trenne(); klient = klient->release(); cs.unlock(); return 0; } } Framework::logLine( "Verbinung mit Minigame Server wird hergestellt..." ); int keyLen = 0; char *key = 0; Keys::getServerKey( &key, keyLen, Keys::MINIGAME, Keys::SENDEN ); klient->setSendeKey( key, keyLen ); delete[] key; Keys::getServerKey( &key, keyLen, Keys::MINIGAME, Keys::EMPFANGEN ); klient->setEmpfangKey( key, keyLen ); delete[] key; if( klient->verbinde( klient->getServerPort(), klient->getServerIp() ) ) { if( klient->sendeEncrypted( "\1", 1 ) ) { klient->sendeEncrypted( (char*)&klientId, 4 ); char serverReturn = 0; klient->getNachrichtEncrypted( &serverReturn, 1 ); if( serverReturn == 3 ) { char byte = 0; klient->getNachrichtEncrypted( &byte, 1 ); delete[]fehler; fehler = new char[ byte + 1 ]; fehler[ byte ] = 0; klient->getNachrichtEncrypted( fehler, byte ); Framework::logLine( Text( "ERROR: " ) += fehler ); klient->sendeEncrypted( "\3", 1 ); klient->getNachrichtEncrypted( &serverReturn, 1 ); klient->trenne(); cs.unlock(); return 0; } char *sl = 0; char slLän = getSchlüssel( &sl ); klient->setSendeKey( sl, slLän ); klient->setEmpfangKey( sl, slLän ); delete[] sl; verbunden = 1; cs.unlock(); Framework::logLine( "Erfolgreich mit Minigame Server verbunden." ); return 1; } else { Framework::logLine( "ERROR: Senden zum Server nicht erfolgreich." ); char *err = "Der dir zugewiesene Minigame Server hat die Verbindung abgebrochen. Bitte versuche es Später erneut."; delete[]fehler; fehler = new char[ textLength( err ) + 1 ]; fehler[ textLength( err ) ] = 0; memcpy( fehler, err, textLength( err ) ); klient = klient->release(); } } else { Framework::logLine( "ERROR: Server nicht erreichbar." ); char *err = "Der dir zugewiesene Minigame Server antwortet nicht. Bitte versuche es Später erneut."; delete[]fehler; fehler = new char[ textLength( err ) + 1 ]; fehler[ textLength( err ) ] = 0; memcpy( fehler, err, textLength( err ) ); klient = klient->release(); } cs.unlock(); return 0; } // Gibt die liste mit allen Optionen zu einem Minigame zurück, zu denen es Welt beste Scores gibt // mName: Der Name des Minigames // zOptionList: Ein Zeiger auf ein Array von Texten, in denen die Optionen gespeichert werden // return: Anzahl der Optionen int MinigameClient::getMinigameOptionList( char *mName, RCArray< Text > *zOptionList ) { if( !verbunden ) verbinde(); if( !verbunden ) return 0; if( needCapture ) return 0; cs.lock(); klient->sendeEncrypted( "\x6", 1 ); char ret = 0; klient->getNachrichtEncrypted( &ret, 1 ); if( ret == 1 ) { char l = (char)textLength( mName ); klient->sendeEncrypted( &l, 1 ); klient->sendeEncrypted( mName, l ); int anz = 0; klient->getNachrichtEncrypted( (char*)&anz, 4 ); for( int i = 0; i < anz; i++ ) { klient->getNachrichtEncrypted( &l, 1 ); char *option = new char[ l + 1 ]; option[ l ] = 0; klient->getNachrichtEncrypted( option, l ); zOptionList->add( new Text( option ) ); delete[] option; } cs.unlock(); return anz; } if( ret == 3 ) { char l = 0; klient->getNachrichtEncrypted( &l, 1 ); delete[] fehler; fehler = new char[ l + 1 ]; fehler[ l ] = 0; klient->getNachrichtEncrypted( fehler, l ); } cs.unlock(); return 0; } // Gibt eine Liste mit den Weltbesten Scores zurück // mName: Der Name des Minigames // zScore: (rückgabe) Ein Array von Scores // zPlayerList: (rückgabe) Ein Array von Spielernamen, die die Scores erreicht haben. // zOptionList: (rückgabe) Ein Array von Optionen, die beim erreichen der Scores aktiv waren. // return: Anzahl der Scores int MinigameClient::getMinigameBestscoreList( char *mName, Array< int > *zScore, RCArray< Text > *zPlayerList, RCArray< Text > *zOptionList ) { if( !verbunden ) verbinde(); if( !verbunden ) return 0; if( needCapture ) return 0; cs.lock(); klient->sendeEncrypted( "\x7", 1 ); char ret = 0; klient->getNachrichtEncrypted( &ret, 1 ); if( ret == 1 ) { char l = (char)textLength( mName ); klient->sendeEncrypted( &l, 1 ); klient->sendeEncrypted( mName, l ); int anz = 0; klient->getNachrichtEncrypted( (char*)&anz, 4 ); for( int i = 0; i < anz; i++ ) { int score = 0; klient->getNachrichtEncrypted( (char*)&score, 4 ); zScore->add( score ); klient->getNachrichtEncrypted( &l, 1 ); char *player = new char[ l + 1 ]; player[ l ] = 0; klient->getNachrichtEncrypted( player, l ); zPlayerList->add( new Text( player ) ); delete[] player; klient->getNachrichtEncrypted( &l, 1 ); char *option = new char[ l + 1 ]; option[ l ] = 0; klient->getNachrichtEncrypted( option, l ); zOptionList->add( new Text( option ) ); delete[] option; } cs.unlock(); return anz; } if( ret == 3 ) { char l = 0; klient->getNachrichtEncrypted( &l, 1 ); delete[] fehler; fehler = new char[ l + 1 ]; fehler[ l ] = 0; klient->getNachrichtEncrypted( fehler, l ); } cs.unlock(); return 0; } // Gibt den Welt bestscore zu einem Bestimmten Minigame mit bestimmten Optionen zurück. // mName: Der Name des Minigames // oName: Die Optionen // zPlayer: (rückgabe) Der Spielername, der den Score erreicht hat // return: Der Score der erreicht wurde int MinigameClient::getMinigameOptionBestscore( char *mName, char *oName, Text *zPlayer ) { if( !verbunden ) verbinde(); if( !verbunden ) return 0; if( needCapture ) return 0; cs.lock(); klient->sendeEncrypted( "\x8", 1 ); char ret = 0; klient->getNachrichtEncrypted( &ret, 1 ); if( ret == 1 ) { char l = (char)textLength( mName ); klient->sendeEncrypted( &l, 1 ); klient->sendeEncrypted( mName, l ); l = (char)textLength( oName ); klient->sendeEncrypted( &l, 1 ); klient->sendeEncrypted( oName, l ); int score = 0; klient->getNachrichtEncrypted( (char*)&score, 4 ); klient->getNachrichtEncrypted( &l, 1 ); char *player = new char[ l + 1 ]; player[ l ] = 0; klient->getNachrichtEncrypted( player, l ); zPlayer->setText( player ); delete[] player; cs.unlock(); return score; } if( ret == 3 ) { char l = 0; klient->getNachrichtEncrypted( &l, 1 ); delete[] fehler; fehler = new char[ l + 1 ]; fehler[ l ] = 0; klient->getNachrichtEncrypted( fehler, l ); } cs.unlock(); return 0; } // Meldet die Beendigung eines Minigames // mName: Der Name des Minigames // oName: Die Optionen mit denen gespielt wurde // score: Der Erreichte Score // return: 0: Im Falle eines Fehlers, 1: Im Falle eines Erfolgs, 2: Falls ein Game Capture hochgeladen werden muss int MinigameClient::reportEndOfGame( char *mName, char *oName, int score ) { if( !verbunden ) verbinde(); if( !verbunden ) return 0; if( needCapture ) return 0; cs.lock(); klient->sendeEncrypted( "\x9", 1 ); char ret = 0; klient->getNachrichtEncrypted( &ret, 1 ); if( ret == 1 ) { char l = (char)textLength( mName ); klient->sendeEncrypted( &l, 1 ); klient->sendeEncrypted( mName, l ); l = (char)textLength( oName ); klient->sendeEncrypted( &l, 1 ); klient->sendeEncrypted( oName, l ); klient->sendeEncrypted( (char*)&score, 4 ); klient->getNachrichtEncrypted( &ret, 1 ); if( ret == 1 ) { cs.unlock(); needCapture = 1; return 2; } cs.unlock(); return 1; } if( ret == 3 ) { char l = 0; klient->getNachrichtEncrypted( &l, 1 ); delete[] fehler; fehler = new char[ l + 1 ]; fehler[ l ] = 0; klient->getNachrichtEncrypted( fehler, l ); } cs.unlock(); return 0; } // Lädt ein Game Capture hoch // zCapture: Ein Zeiger auf die Capture Datei // return: 1, falls erfolgreich bool MinigameClient::uploadGameCapture( Datei *zCapture ) { if( !verbunden ) verbinde(); if( !verbunden ) return 0; if( !needCapture ) return 0; cs.lock(); int size = (int)zCapture->getSize(); if( !zCapture->istOffen() ) zCapture->open( Datei::Style::lesen ); klient->sendeEncrypted( (char*)&size, 4 ); char *buffer = new char[ 2048 ]; while( size > 0 ) { int l = size > 2048 ? 2048 : size; zCapture->lese( buffer, l ); klient->sendeEncrypted( buffer, l ); size -= l; } delete[] buffer; zCapture->close(); needCapture = 0; cs.unlock(); return 1; } // Lädt ein Game Capture herunter // mName: Der Name des Minigames // oName: Die Optionen // return: Ein Zeiger auf die Datei mit dem Capture Datei *MinigameClient::downloadGameCapture( char *mName, char *oName ) { if( !verbunden ) verbinde(); if( !verbunden ) return 0; if( needCapture ) return 0; cs.lock(); klient->sendeEncrypted( "\xA", 1 ); char ret = 0; klient->getNachrichtEncrypted( &ret, 1 ); if( ret == 1 ) { char l = (char)textLength( mName ); klient->sendeEncrypted( &l, 1 ); klient->sendeEncrypted( mName, l ); l = (char)textLength( oName ); klient->sendeEncrypted( &l, 1 ); klient->sendeEncrypted( oName, l ); klient->getNachrichtEncrypted( &ret, 1 ); if( ret == 1 ) { Datei *capture = new Datei(); capture->setDatei( "data/tmp/minigames/wb.mgc" ); capture->erstellen(); capture->open( Datei::Style::schreiben ); int size = 0; klient->getNachrichtEncrypted( (char*)&size, 4 ); char *buffer = new char[ 2048 ]; while( size > 0 ) { int l = size > 2048 ? 2048 : size; klient->getNachrichtEncrypted( buffer, l ); capture->schreibe( buffer, l ); size -= l; } delete[] buffer; capture->close(); cs.unlock(); return capture; } cs.unlock(); return 0; } if( ret == 3 ) { char l = 0; klient->getNachrichtEncrypted( &l, 1 ); delete[] fehler; fehler = new char[ l + 1 ]; fehler[ l ] = 0; klient->getNachrichtEncrypted( fehler, l ); } cs.unlock(); return 0; } bool MinigameClient::keepAlive() { if( needCapture ) return 1; if( !verbunden ) return 0; char res = 0; if( !cs.tryLock() ) return 1; Framework::logLine( "Verbindungstest zum Minigame Server..." ); bool ok = klient->sendeEncrypted( "\x5", 1 ); ok &= klient->getNachrichtEncrypted( &res, 1 ); cs.unlock(); if( res != 1 || !ok ) { Framework::logLine( "Verbindungsabbruch." ); trenne(); } else Framework::logLine( "Verbindung besteht." ); return res == 1; } // Erhält die Verbindung aufrecht bool MinigameClient::trenne() { if( verbunden ) { cs.lock(); Framework::logLine( "Verbindung zum Minigame Server wird getrennt..." ); if( needCapture ) klient->sendeEncrypted( "\0\0\0\0", 4 ); needCapture = 0; klient->sendeEncrypted( "\3", 1 ); char serverReturn = 0; klient->getNachrichtEncrypted( &serverReturn, 1 ); klient->trenne(); verbunden = 0; cs.unlock(); } return 1; } // trennt sich von dem Minigame Server bool MinigameClient::istVerbunden() const { return verbunden; } // prüft, ob mit Editor Server verbunden char *MinigameClient::getLetzterFehler() const { return fehler; } // gibt den Letzten Fehlertext zuück // Reference Counting MinigameKlientV *MinigameClient::getThis() { ref++; return this; } MinigameKlientV *MinigameClient::release() { if( !--ref ) delete this; return 0; }