#include "MinigameClient.h" #include #include "Keys.h" #include using namespace KSGClient; // Inhalt der MinigameClient Klasse // Konstruktor MinigameClient::MinigameClient( int klientId, unsigned short port, char *ip, char *key, unsigned char keyLen ) { ref = 1; this->ip = ip; this->port = port; cId = klientId; k = 0; this->key = new char[ keyLen ]; memcpy( this->key, key, keyLen ); this->keyLen = keyLen; } // Destruktor MinigameClient::~MinigameClient() { trenne( 1 ); delete[] key; } // verbindet sich mit dem zugewiesenen Minigame Server // Gibt 1 zurück, falls der Vorgang erfolgreich ist, 0 sonnst bool MinigameClient::verbinde() { cs.lock(); if( k ) { cs.unlock(); return 1; } k = new Network::Klient(); int l = 0; char *key; Keys::getServerKey( &key, l, Keys::MINIGAME, Keys::SENDEN ); k->setSendeKey( key, l ); delete[] key; Keys::getServerKey( &key, l, Keys::MINIGAME, Keys::EMPFANGEN ); k->setEmpfangKey( key, l ); delete[] key; if( k->verbinde( port, ip ) ) { if( k->sendeEncrypted( "\1", 1 ) ) { k->sendeEncrypted( (char*)&cId, 4 ); char serverReturn = 0; k->getNachrichtEncrypted( &serverReturn, 1 ); if( serverReturn == 3 ) { char byte = 0; k->getNachrichtEncrypted( &byte, 1 ); char *f = new char[ byte + 1 ]; f[ byte ] = 0; k->getNachrichtEncrypted( f, byte ); err = "error while identifying client Minigame Server returned: "; err += f; delete[]f; trenne( 0 ); cs.unlock(); return 0; } k->setSendeKey( this->key, this->keyLen ); k->setEmpfangKey( this->key, this->keyLen ); } else { err = "network error while sending to Minigame Server"; k = k->release(); cs.unlock(); return 0; } } else { err = "network error while connecting to Minigame Server"; k = k->release(); cs.unlock(); return 0; } cs.unlock(); return 1; } // Ermittelt die liste mit allen Optionen zu einem Minigame zurück, zu denen es Welt beste Scores gibt // mName: Der Name des Minigames // zOptionList: Enthält nach erfolgreichem Aufruf eine Liste mit Optionen // Gibt die Anzahl der Optionen zurück int MinigameClient::getMinigameOptionList( char *mName, Framework::RCArray< Framework::Text > *zOptionList ) { cs.lock(); if( !k ) { err = "Der Client ist nicht verbunden."; cs.unlock(); return 0; } k->sendeEncrypted( "\x6", 1 ); char ret = 0; k->getNachrichtEncrypted( &ret, 1 ); if( ret == 1 ) { char l = (char)textLength( mName ); k->sendeEncrypted( &l, 1 ); k->sendeEncrypted( mName, l ); int anz = 0; k->getNachrichtEncrypted( (char*)&anz, 4 ); for( int i = 0; i < anz; i++ ) { k->getNachrichtEncrypted( &l, 1 ); char *option = new char[ l + 1 ]; option[ l ] = 0; k->getNachrichtEncrypted( option, l ); zOptionList->add( new Text( option ) ); delete[] option; } cs.unlock(); return anz; } if( ret == 3 ) { char l = 0; k->getNachrichtEncrypted( &l, 1 ); char *fehler = new char[ l + 1 ]; fehler[ l ] = 0; k->getNachrichtEncrypted( fehler, l ); err = fehler; delete[] fehler; cs.unlock(); return 0; } err = "Unbekannter Fehler"; cs.unlock(); return 0; } // Ermittelt eine Liste mit den Weltbesten Scores zurück // mName: Der Name des Minigames // zScore: Enthält nach erfolgreichem Aufruf eine Liste mit Scores // zPlayerList: Enthält nach erfolgreichem Aufruf eine Liste mit angezeigten Account Namen, die die Scores erreicht haben. // zOptionList: Enthält nach erfolgreichem Aufruf eine Liste mit Optionen, die beim erreichen der Scores aktiv waren. // Gibt die Anzahl der Bestscores zurück int MinigameClient::getMinigameBestscoreList( char *mName, Framework::Array< int > *zScore, Framework::RCArray< Framework::Text > *zPlayerList, Framework::RCArray< Framework::Text > *zOptionList ) { cs.lock(); if( !k ) { err = "Der Client ist nicht verbunden."; cs.unlock(); return 0; } k->sendeEncrypted( "\x7", 1 ); char ret = 0; k->getNachrichtEncrypted( &ret, 1 ); if( ret == 1 ) { char l = (char)textLength( mName ); k->sendeEncrypted( &l, 1 ); k->sendeEncrypted( mName, l ); int anz = 0; k->getNachrichtEncrypted( (char*)&anz, 4 ); for( int i = 0; i < anz; i++ ) { int score = 0; k->getNachrichtEncrypted( (char*)&score, 4 ); zScore->add( score ); k->getNachrichtEncrypted( &l, 1 ); char *player = new char[ l + 1 ]; player[ l ] = 0; k->getNachrichtEncrypted( player, l ); zPlayerList->add( new Text( player ) ); delete[] player; k->getNachrichtEncrypted( &l, 1 ); char *option = new char[ l + 1 ]; option[ l ] = 0; k->getNachrichtEncrypted( option, l ); zOptionList->add( new Text( option ) ); delete[] option; } cs.unlock(); return anz; } if( ret == 3 ) { char l = 0; k->getNachrichtEncrypted( &l, 1 ); char *fehler = new char[ l + 1 ]; fehler[ l ] = 0; k->getNachrichtEncrypted( fehler, l ); err = fehler; delete[] fehler; cs.unlock(); return 0; } err = "Unbekannter Fehler"; 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: Enthält nach erfolgreichem Aufruf den Angezeigten Namen des Accounts, der den Score erreicht hat int MinigameClient::getMinigameOptionBestscore( char *mName, char *oName, Framework::Text *zPlayer ) { cs.lock(); if( !k ) { err = "Der Client ist nicht verbunden."; cs.unlock(); return 0; } k->sendeEncrypted( "\x8", 1 ); char ret = 0; k->getNachrichtEncrypted( &ret, 1 ); if( ret == 1 ) { char l = (char)textLength( mName ); k->sendeEncrypted( &l, 1 ); k->sendeEncrypted( mName, l ); l = (char)textLength( oName ); k->sendeEncrypted( &l, 1 ); k->sendeEncrypted( oName, l ); int score = 0; k->getNachrichtEncrypted( (char*)&score, 4 ); k->getNachrichtEncrypted( &l, 1 ); char *player = new char[ l + 1 ]; player[ l ] = 0; k->getNachrichtEncrypted( player, l ); zPlayer->setText( player ); delete[] player; cs.unlock(); return score; } if( ret == 3 ) { char l = 0; k->getNachrichtEncrypted( &l, 1 ); char *fehler = new char[ l + 1 ]; fehler[ l ] = 0; k->getNachrichtEncrypted( fehler, l ); err = fehler; delete[] fehler; cs.unlock(); return 0; } err = "Unbekannter Fehler"; 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 // zCapture: Ein Zeiger auf eine Datei mit der Spielaufzeichnung // Gibt 0 zurück wenn eines Fehler aufgetreten ist, 1 wenn der Forgang erfolgreich war bool MinigameClient::reportEndOfGame( char *mName, char *oName, int score, Framework::Datei *zCapture ) { cs.lock(); if( !k ) { err = "Der Client ist nicht verbunden."; cs.unlock(); return 0; } k->sendeEncrypted( "\x9", 1 ); char ret = 0; k->getNachrichtEncrypted( &ret, 1 ); if( ret == 1 ) { char l = (char)textLength( mName ); k->sendeEncrypted( &l, 1 ); k->sendeEncrypted( mName, l ); l = (char)textLength( oName ); k->sendeEncrypted( &l, 1 ); k->sendeEncrypted( oName, l ); k->sendeEncrypted( (char*)&score, 4 ); k->getNachrichtEncrypted( &ret, 1 ); if( ret == 1 ) { int size = (int)zCapture->getSize(); if( !zCapture->istOffen() ) zCapture->open( Datei::Style::lesen ); k->sendeEncrypted( (char*)&size, 4 ); char *buffer = new char[ 2048 ]; while( size > 0 ) { int l = size > 2048 ? 2048 : size; zCapture->lese( buffer, l ); k->sendeEncrypted( buffer, l ); size -= l; } delete[] buffer; zCapture->close(); cs.unlock(); return 1; } else if( ret == 0 ) { cs.unlock(); return 1; } } if( ret == 3 ) { char l = 0; k->getNachrichtEncrypted( &l, 1 ); char *fehler = new char[ l + 1 ]; fehler[ l ] = 0; k->getNachrichtEncrypted( fehler, l ); err = fehler; delete[] fehler; cs.unlock(); return 0; } err = "Unbekannter Fehler"; cs.unlock(); return 0; } // Lädt ein Game Capture herunter und speichert sie unter data/tmp/minigames/wb.mgc // mName: Der Name des Minigames // oName: Die Optionen // Gibt die Datei mit dem Capture zurück Framework::Datei *MinigameClient::downloadGameCapture( char *mName, char *oName ) { cs.lock(); if( !k ) { err = "Der Client ist nicht verbunden."; cs.unlock(); return 0; } k->sendeEncrypted( "\xA", 1 ); char ret = 0; k->getNachrichtEncrypted( &ret, 1 ); if( ret == 1 ) { char l = (char)textLength( mName ); k->sendeEncrypted( &l, 1 ); k->sendeEncrypted( mName, l ); l = (char)textLength( oName ); k->sendeEncrypted( &l, 1 ); k->sendeEncrypted( oName, l ); k->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; k->getNachrichtEncrypted( (char*)&size, 4 ); char *buffer = new char[ 2048 ]; while( size > 0 ) { int l = size > 2048 ? 2048 : size; k->getNachrichtEncrypted( buffer, l ); capture->schreibe( buffer, l ); size -= l; } delete[] buffer; capture->close(); cs.unlock(); return capture; } err = "Unbekannter Fehler"; cs.unlock(); return 0; } if( ret == 3 ) { char l = 0; k->getNachrichtEncrypted( &l, 1 ); char *fehler = new char[ l + 1 ]; fehler[ l ] = 0; k->getNachrichtEncrypted( fehler, l ); err = fehler; delete[] fehler; cs.unlock(); return 0; } err = "Unbekannter Fehler"; cs.unlock(); return 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 bool MinigameClient::keepAlive() { char res = 0; if( !cs.tryLock() ) return 1; if( !k ) { err = "Der Client ist nicht verbunden."; cs.unlock(); return 0; } bool ok = k->sendeEncrypted( "\x5", 1 ); ok &= k->getNachrichtEncrypted( &res, 1 ); cs.unlock(); if( res != 1 || !ok ) trenne( 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 MinigameClient::trenne( bool abmelden ) { cs.lock(); verbinde(); if( !k ) { cs.unlock(); return 1; } if( abmelden ) { k->sendeEncrypted( "\4", 1 ); char ret = 0; k->getNachrichtEncrypted( &ret, 1 ); if( ret == 3 ) { // error k->getNachrichtEncrypted( &ret, 1 ); char *msg = new char[ ret + 1 ]; msg[ ret ] = 0; if( ret ) k->getNachrichtEncrypted( msg, ret ); err = "error while unregister Client Minigame Server returned: "; err += msg; delete[] msg; } } k->sendeEncrypted( "\3", 1 ); char ret = 0; k->getNachrichtEncrypted( &ret, 1 ); if( ret == 3 ) { // error k->getNachrichtEncrypted( &ret, 1 ); char *msg = new char[ ret + 1 ]; msg[ ret ] = 0; if( ret ) k->getNachrichtEncrypted( msg, ret ); err = "error while trenne Minigame Server returned: "; err += msg; delete[] msg; } k->trenne(); k = k->release(); cs.unlock(); return 1; } // Gibt 1 zurück, falls der Client verbunden ist, 0 sonst bool MinigameClient::istVerbunden() const { return k != 0; } // gibt den Letzten Fehlertext zuück // sollte erst aufgerufen werden, nachdem eine andere aufgerufene Methode fehlgeschlagen ist char *MinigameClient::getLetzterFehler() const { return err; } // Erhöht den Reference Counter um 1 un gibt this zurück MinigameServerClient *MinigameClient::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 MinigameServerClient *MinigameClient::release() { if( !--ref ) delete this; return 0; }