123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592 |
- #include "SpielClient.h"
- #include <Klient.h>
- #include "Keys.h"
- using namespace KSGClient;
- // Inhalt der SpielClient Klasse
- // Konstruktor
- SpielClient::SpielClient(int klientId, unsigned short port, const char* ip, const char* key, unsigned char keyLen)
- : ReferenceCounter()
- {
- this->ip = ip;
- this->port = port;
- cId = klientId;
- senden = 0;
- empfangen = 0;
- this->key = new char[keyLen];
- memcpy(this->key, key, keyLen);
- this->keyLen = keyLen;
- }
- // Destruktor
- SpielClient::~SpielClient()
- {
- trenne();
- delete[] key;
- }
- // verbindet sich mit dem zugewiesenen Karten Server
- // Gibt 1 zurück, falls der Vorgang erfolgreich ist, 0 sonnst
- bool SpielClient::verbinde()
- {
- cs.lock();
- if (senden)
- {
- cs.unlock();
- return 1;
- }
- if (!senden)
- senden = new Network::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*)&cId, 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);
- err = f;
- delete[]f;
- }
- senden->sendeEncrypted("\3", 1);
- senden->getNachrichtEncrypted(&serverReturn, 1);
- senden->trenne();
- senden = (Network::Klient*)senden->release();
- err = "Server akzeptiert den Klient nicht.";
- cs.unlock();
- return 0;
- }
- senden->setSendeKey(this->key, this->keyLen);
- senden->setEmpfangKey(this->key, this->keyLen);
- if (!empfangen)
- empfangen = new Network::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()))
- {
- empfangen->sendeEncrypted("\1", 1);
- empfangen->sendeEncrypted((char*)&cId, 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);
- err = nachricht;
- delete[] nachricht;
- }
- if (res == 1)
- {
- empfangen->setSendeKey(this->key, this->keyLen);
- empfangen->setEmpfangKey(this->key, this->keyLen);
- }
- else if (res != 0)
- {
- err = "Fehler beim Verbinden mit dem Spiel Server.";
- senden->sendeEncrypted("\3", 1);
- char serverReturn = 0;
- senden->getNachrichtEncrypted(&serverReturn, 1);
- senden->trenne();
- senden = (Network::Klient*)senden->release();
- empfangen->trenne();
- empfangen = (Network::Klient*)empfangen->release();
- return 0;
- }
- cs.unlock();
- return 1;
- }
- else
- {
- empfangen = (Network::Klient*)empfangen->release();
- senden->sendeEncrypted("\3", 1);
- char serverReturn = 0;
- senden->getNachrichtEncrypted(&serverReturn, 1);
- senden->trenne();
- senden = (Network::Klient*)senden->release();
- err = "Der dir zugewiesene Spiel Server kann dir keine Nachrichten senden.";
- cs.unlock();
- return 0;
- }
- }
- else
- {
- senden->trenne();
- senden = (Network::Klient*)senden->release();
- err = "Der dir zugewiesene Spiel Server hat die Verbindung abgebrochen. Bitte versuche es Später erneut.";
- cs.unlock();
- return 0;
- }
- }
- else
- {
- err = "Der dir zugewiesene Spiel Server antwortet nicht. Bitte versuche es Später erneut.";
- senden = (Network::Klient*)senden->release();
- cs.unlock();
- return 0;
- }
- err = "Unbekannter Fehler";
- cs.unlock();
- return 0;
- }
- // Betritt das Vorgeschlagene Spiel
- // Gibt 1 zurück, falls der Vorgang erfolgreich ist, 0 sonnst
- bool SpielClient::spielErstelltAnnehmen()
- {
- cs.lock();
- if (!senden)
- {
- err = "Der Client ist nicht verbunden.";
- cs.unlock();
- return 0;
- }
- char ret = 0;
- senden->sendeEncrypted("\4", 1);
- senden->getNachrichtEncrypted(&ret, 1);
- if (ret != 1)
- err = "Fehler beim annehmen des Spiels.";
- cs.unlock();
- return ret == 1;
- }
- // Lehnt das Vorgeschlagene Spiel ab
- // Gibt 1 zurück, falls der Vorgang erfolgreich ist, 0 sonnst
- bool SpielClient::spielErstelltAblehnen()
- {
- cs.lock();
- if (!senden)
- {
- err = "Der Client ist nicht verbunden.";
- cs.unlock();
- return 0;
- }
- char ret = 0;
- senden->sendeEncrypted("\5", 1);
- senden->getNachrichtEncrypted(&ret, 1);
- if (ret != 1)
- err = "Fehler beim ablehnen des Spiels.";
- cs.unlock();
- return ret == 1;
- }
- // Wechselt zu einem bestimmten Team
- // team: Die Id des teams
- // Gibt 1 zurück, falls der Vorgang erfolgreich ist, 0 sonnst
- bool SpielClient::spielErstelltTeamWechseln(int team)
- {
- cs.lock();
- if (!senden)
- {
- err = "Der Client ist nicht verbunden.";
- cs.unlock();
- return 0;
- }
- char ret = 0;
- senden->sendeEncrypted("\6", 1);
- senden->getNachrichtEncrypted(&ret, 1);
- if (!ret)
- {
- err = "Fehler beim wechseln des Teams.";
- cs.unlock();
- return 0;
- }
- senden->sendeEncrypted((char*)&team, 4);
- senden->getNachrichtEncrypted(&ret, 1);
- if (ret != 1)
- err = "Fehler beim wechseln des Teams.";
- cs.unlock();
- return ret == 1;
- }
- // Bestätigt die Teamauswahl so dass das Spiel früher beginnen kann
- // Gibt 1 zurück, falls der Vorgang erfolgreich ist, 0 sonnst
- bool SpielClient::spielErstelltTeamFertig()
- {
- cs.lock();
- if (!senden)
- {
- err = "Der Client ist nicht verbunden.";
- cs.unlock();
- return 0;
- }
- char ret = 0;
- senden->sendeEncrypted("\xE", 1);
- senden->getNachrichtEncrypted(&ret, 1);
- if (ret != 1)
- err = "Fehler beim setzen der Bereitschaft.";
- cs.unlock();
- return ret == 1;
- }
- // sendet eine Chat Nachricht an die mitglieder des erstellten Spiels
- // nachricht: Die Nachricht
- // Gibt 1 zurück, falls der Vorgang erfolgreich ist, 0 sonnst
- bool SpielClient::spielErstelltChatNachricht(const char* nachricht)
- {
- char län = textLength(nachricht);
- if (!län)
- return 1;
- cs.lock();
- if (!senden)
- {
- err = "Der Client ist nicht verbunden.";
- cs.unlock();
- return 0;
- }
- char ret = 0;
- senden->sendeEncrypted("\7", 1);
- senden->getNachrichtEncrypted(&ret, 1);
- if (!ret)
- {
- err = "Fehler beim senden der Chat Nachricht.";
- cs.unlock();
- return 0;
- }
- senden->sendeEncrypted(&län, 1);
- senden->sendeEncrypted(nachricht, län);
- senden->getNachrichtEncrypted(&ret, 1);
- if (ret != 1)
- err = "Fehler beim senden der Chat Nachricht.";
- cs.unlock();
- return ret == 1;
- }
- // Teilt dem Server mit, dass der Client bereit ist das Spiel zu laden
- // Gibt 1 zurück, falls der Vorgang erfolgreich ist, 0 sonnst
- bool SpielClient::bereitZumLaden()
- {
- cs.lock();
- if (!senden)
- {
- err = "Der Client ist nicht verbunden.";
- cs.unlock();
- return 0;
- }
- char ret = 0;
- senden->sendeEncrypted("\x9", 1);
- senden->getNachrichtEncrypted(&ret, 1);
- if (ret != 1)
- err = "Fehler beim setzen der Bereitschaft.";
- cs.unlock();
- return ret == 1;
- }
- // Teilt dem Server mit, zu wie viel Prozent der Client das Spiel geladen hat
- // Gibt 1 zurück, falls der Vorgang erfolgreich ist, 0 sonnst
- bool SpielClient::setLadenProzent(int prozent)
- {
- cs.lock();
- if (!senden)
- {
- err = "Der Client ist nicht verbunden.";
- cs.unlock();
- return 0;
- }
- char ret = 0;
- senden->sendeEncrypted("\xC", 1);
- senden->getNachrichtEncrypted(&ret, 1);
- if (ret)
- {
- senden->sendeEncrypted((char*)&prozent, 4);
- senden->getNachrichtEncrypted(&ret, 1);
- }
- if (ret != 1)
- err = "Fehler beim setzen des Fortschritts.";
- cs.unlock();
- return ret == 1;
- }
- // Teilt dem Server mit, dass das Spiel fertig geladen wurde
- // Gibt 1 zurück, falls der Vorgang erfolgreich ist, 0 sonnst
- bool SpielClient::bereitZumSpiel()
- {
- cs.lock();
- if (!senden)
- {
- err = "Der Client ist nicht verbunden.";
- cs.unlock();
- return 0;
- }
- char ret = 0;
- senden->sendeEncrypted("\xA", 1);
- senden->getNachrichtEncrypted(&ret, 1);
- if (ret != 1)
- err = "Fehler beim setzen der Bereitschaft.";
- cs.unlock();
- return ret == 1;
- }
- // Sendet während des Spiels eine Nachricht an den Server
- // län: Die Länge der Nachricht
- // bytes: Ein Zeiger auf die Nachricht
- // Gibt 1 zurück, falls der Vorgang erfolgreich ist, 0 sonnst
- bool SpielClient::spielNachricht(short län, const char* bytes)
- {
- cs.lock();
- if (!senden)
- {
- err = "Der Client ist nicht verbunden.";
- cs.unlock();
- return 0;
- }
- senden->sendeEncrypted("\xB", 1);
- senden->sende((char*)&län, 2);
- senden->sende(bytes, län);
- cs.unlock();
- return 1;
- }
- // Sendet während der Statistik eine Nachricht an den Server
- // län: Die Länge der Nachricht
- // bytes: Ein Zeiger auf die Nachricht
- // Gibt 1 zurück, falls der Vorgang erfolgreich ist, 0 sonnst
- bool SpielClient::statistikNachricht(short län, const char* bytes)
- {
- cs.lock();
- if (!senden)
- {
- err = "Der Client ist nicht verbunden.";
- cs.unlock();
- return 0;
- }
- char ret = 0;
- 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);
- }
- if (ret != 1)
- err = "Fehler beim setzen der Statistik Nachricht.";
- cs.unlock();
- return ret == 1;
- }
- // Wartet auf eine Nachricht vom Spiel Server.
- // Gibt bei Erfolg 1 zurück, 0 sonnst
- // nachricht: Eine Referenz auf die Struktur, in der die Nachricht gespeichert werden soll
- bool SpielClient::getNextMessage(SpielServerNachricht& nachricht)
- {
- do
- {
- if (!empfangen->getNachrichtEncrypted(&nachricht.type, 1))
- {
- err = "Es ist ein Fehler beim Empfangen aufgetreten";
- return 0;
- }
- switch (nachricht.type)
- {
- case 0: // verbindung getrennt
- trenne();
- break;
- case 1: // verbleibende Zeit
- empfangen->getNachrichtEncrypted(&nachricht.sekunden, 1);
- 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);
- nachricht.message = grund;
- delete[] grund;
- }
- break;
- case 3: // Fehler
- if (1)
- {
- unsigned char länge = 0;
- empfangen->getNachrichtEncrypted((char*)&länge, 1);
- char* txt = new char[länge + 1];
- txt[länge] = 0;
- empfangen->getNachrichtEncrypted(txt, länge);
- nachricht.message = txt;
- delete[]txt;
- }
- break;
- case 4: // zurück in Warteschlange
- empfangen->getNachrichtEncrypted(&nachricht.stunden, 1);
- empfangen->getNachrichtEncrypted(&nachricht.minuten, 1);
- empfangen->getNachrichtEncrypted(&nachricht.sekunden, 1);
- break;
- case 6: // SpielErstellt Initialisierung
- empfangen->getNachrichtEncrypted((char*)&nachricht.sts->spielerAnzahl, 4);
- empfangen->getNachrichtEncrypted((char*)&nachricht.sts->teamAnzahl, 4);
- for (int i = 0; i < nachricht.sts->spielerAnzahl; i++)
- {
- int farbe = 0;
- empfangen->getNachrichtEncrypted((char*)&farbe, 4);
- nachricht.sts->spielerFarbe->set(farbe, i);
- }
- for (int i = 0; i < nachricht.sts->teamAnzahl; i++)
- {
- int farbe = 0;
- empfangen->getNachrichtEncrypted((char*)&farbe, 4);
- nachricht.sts->teamFarbe->set(farbe, i);
- }
- for (int i = 0; i < nachricht.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;
- nachricht.sts->teamName->set(tmp, i);
- }
- for (int i = 0; i < nachricht.sts->teamAnzahl; i++)
- {
- int größe = 0;
- empfangen->getNachrichtEncrypted((char*)&größe, 4);
- nachricht.sts->teamSize->set(größe, i);
- }
- break;
- case 7: // SpielErstellt Spieler hinzugefügt
- empfangen->getNachrichtEncrypted((char*)&nachricht.accountId, 4);
- break;
- case 8: // SpielErstellt Spieler entfernt
- empfangen->getNachrichtEncrypted((char*)&nachricht.accountId, 4);
- break;
- case 9: // SpielErstellt Spieler wechselt Team
- empfangen->getNachrichtEncrypted((char*)&nachricht.accountId, 4);
- empfangen->getNachrichtEncrypted((char*)&nachricht.spielerNummer, 4);
- break;
- case 0xA: // SpielErstellt Chat Nachricht
- if (1)
- {
- char län = 0;
- empfangen->getNachrichtEncrypted(&län, 1);
- char* txt = new char[län + 1];
- txt[län] = 0;
- if (län)
- empfangen->getNachrichtEncrypted(txt, län);
- nachricht.message = txt;
- delete[] txt;
- }
- break;
- case 0xB: // Spiel gefunden
- empfangen->getNachrichtEncrypted((char*)&nachricht.karteId, 4);
- break;
- case 0xD: // Spiel Laden Spieler hinzufügen
- empfangen->getNachrichtEncrypted((char*)&nachricht.accountId, 4);
- empfangen->getNachrichtEncrypted((char*)&nachricht.spielerNummer, 4);
- break;
- case 0xE: // Spiel Laden Spieler Prozent
- empfangen->getNachrichtEncrypted((char*)&nachricht.accountId, 4);
- empfangen->getNachrichtEncrypted((char*)&nachricht.prozent, 4);
- break;
- case 0xF: // Spiel Laden Spieler Ping
- empfangen->getNachrichtEncrypted((char*)&nachricht.accountId, 4);
- empfangen->getNachrichtEncrypted((char*)&nachricht.ping, 4);
- break;
- case 0x10: // ping
- empfangen->sendeEncrypted("\1", 1);
- break;
- case 0x12: // Spiel Nachricht
- empfangen->getNachricht((char*)&nachricht.län, 2);
- nachricht.data = new char[nachricht.län];
- empfangen->getNachricht(nachricht.data, nachricht.län);
- break;
- case 0x13: // Statistik Nachricht
- empfangen->getNachrichtEncrypted((char*)&nachricht.län, 2);
- nachricht.data = new char[nachricht.län];
- empfangen->getNachrichtEncrypted(nachricht.data, nachricht.län);
- break;
- case 0x14: // ping
- empfangen->sendeEncrypted("\1", 1);
- break;
- }
- } while (nachricht.type == 0x10 || nachricht.type == 0x14);
- return 1;
- }
- // 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 SpielClient::keepAlive()
- {
- if (!senden)
- return 0;
- char res = 0;
- if (!cs.tryLock())
- return 1;
- bool ok = senden->sendeEncrypted("\xF", 1);
- ok &= senden->getNachrichtEncrypted(&res, 1);
- cs.unlock();
- if (res != 1 || !ok)
- {
- err = "Die Verbindung zum Spiel Server ist abgebrochen.";
- trenne();
- return 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 SpielClient::trenne()
- {
- cs.lock();
- if (!senden)
- {
- cs.unlock();
- return 1;
- }
- senden->sendeEncrypted("\3", 1);
- char serverReturn = 0;
- senden->getNachrichtEncrypted(&serverReturn, 1);
- senden->trenne();
- senden = (Network::Klient*)senden->release();
- empfangen->trenne();
- empfangen = (Network::Klient*)empfangen->release();
- cs.unlock();
- return 1;
- }
- // Gibt 1 zurück, falls der Client verbunden ist, 0 sonst
- bool SpielClient::istVerbunden() const
- {
- return senden != 0;
- }
- // gibt den Letzten Fehlertext zuück
- // sollte erst aufgerufen werden, nachdem eine andere aufgerufene Methode fehlgeschlagen ist
- const char* SpielClient::getLetzterFehler() const
- {
- return err;
- }
|