#include "MinigameClient.h" #include #include "Keys.h" #include using namespace KSGClient; // Inhalt der MinigameClient Klasse // Konstruktor MinigameClient::MinigameClient(int klientId, unsigned short port, const char* ip, const char* key, unsigned char keyLen) : ReferenceCounter() { 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 = (Network::Klient*)k->release(); cs.unlock(); return 0; } } else { err = "network error while connecting to Minigame Server"; k = (Network::Klient*)k->release(); cs.unlock(); return 0; } cs.unlock(); return 1; } // Gibt die Id des aktuell spielenden Accounts zurück int MinigameClient::getAccountId() { cs.lock(); if (!k) { if (!verbinde()) { err = "Der Client ist nicht verbunden."; cs.unlock(); return 0; } } k->sendeEncrypted("\xB", 1); char ret = 0; k->getNachrichtEncrypted(&ret, 1); if (ret == 1) { int acc = 0; k->getNachrichtEncrypted((char*)&acc, 4); cs.unlock(); return acc; } 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 Anzeigenamen eines bestimmten Accounts zurück // id: Die id des Accounts Text* MinigameClient::getAccountName(int id) { cs.lock(); if (!k) { if (!verbinde()) { err = "Der Client ist nicht verbunden."; cs.unlock(); return 0; } } k->sendeEncrypted("\xC", 1); char ret = 0; k->getNachrichtEncrypted(&ret, 1); if (ret == 1) { k->sendeEncrypted((char*)&id, 4); k->getNachrichtEncrypted(&ret, 1); if (ret == 1) { char l; k->getNachrichtEncrypted(&l, 1); char* buff = new char[l + 1]; buff[l] = 0; k->getNachrichtEncrypted(buff, l); cs.unlock(); Text* ret = new Text(buff); delete[] buff; return ret; } } 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 eine geheime zeichenkette die nur der client kennt zurück (ist bei spielstart) Text* MinigameClient::getSecret() { cs.lock(); if (!k) { if (!verbinde()) { err = "Der Client ist nicht verbunden."; cs.unlock(); return 0; } } k->sendeEncrypted("\xD", 1); char ret = 0; k->getNachrichtEncrypted(&ret, 1); if (ret == 1) { unsigned char l = 0; k->getNachrichtEncrypted((char*)&l, 1); char* buff = new char[l + 1]; buff[l] = 0; k->getNachrichtEncrypted(buff, l); cs.unlock(); Text* ret = new Text(buff); delete[] buff; return ret; } 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 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(const char* mName, Framework::RCArray< Framework::Text >* zOptionList) { cs.lock(); if (!k) { if (!verbinde()) { 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(const char* mName, Framework::Array< int >* zScore, Framework::RCArray< Framework::Text >* zPlayerList, Framework::RCArray< Framework::Text >* zOptionList) { cs.lock(); if (!k) { if (!verbinde()) { 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(const char* mName, const char* oName, Framework::Text* zPlayer) { cs.lock(); if (!k) { if (!verbinde()) { 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(const char* mName, const char* oName, int score, Framework::Datei* zCapture) { cs.lock(); if (!k) { if (!verbinde()) { 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(const char* mName, const char* oName) { cs.lock(); if (!k) { if (!verbinde()) { 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 = (Network::Klient*)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 const char* MinigameClient::getLetzterFehler() const { return err; }