#include #include #include #include #include #include #include #include #include "ServerSelection.h" #include "FactoryClient.h" #include "Globals.h" #include "Initialisierung.h" using namespace Framework; ServerStatus::ServerStatus(Framework::Text name, Framework::Text ip, unsigned short sslPort, unsigned short port, Framework::HashMap* secrets) : ZeichnungHintergrund(), name(name), ip(ip), sslPort(sslPort), port(port), playerName(""), ping(-1), status("..."), requestId(0), secrets(secrets), closeAF(new AlphaFeld()), join(initKnopf(0, 0, 55, 20, Knopf::Style::Normal, "join")) { closeAF->setSize(20, 20); closeAF->setFarbe(0x00FF0000); setMausEreignis(_ret1ME); setStyle(Style::Erlaubt | Style::Sichtbar | Style::Rahmen); setRahmenBreite(1); setRahmenFarbe(0xFF3d3d3d); join->setMausEreignis([this](void* p, void* o, MausEreignis me) { if (me.id == ME_RLinks) { FactoryClient* client = new FactoryClient(); if (!client->connect(getIp(), getSSLPort())) { lockZeichnung(); status = "The Server is currently not reachable"; statusId = 404; ping = -1; rend = 1; unlockZeichnung(); client->release(); } else { Text secret = ""; if (this->secrets->has(playerName)) secret = this->secrets->get(playerName); bool isNew = secret.getLength() == 0; int stId = client->join(playerName, secret, getPort()); lockZeichnung(); statusId = stId; if (statusId == 403) status = "The name is already in use"; if (statusId == 500) status = "Unknown Server message received"; if (statusId == 201) status = "Please try again"; unlockZeichnung(); if (statusId == 200 || statusId == 201) { if(statusId == 200) ((ServerSelectionMenu*)(Menu*)menuRegister->get("serverSelection"))->hide(); if (isNew) { this->secrets->put(playerName, secret); ((ServerSelectionMenu*)(Menu*)menuRegister->get("serverSelection"))->saveServers(); } if (statusId == 200) { World::INSTANCE = new World(dynamic_cast(window->zBildschirm()), client); ((ServerSelectionMenu*)(Menu*)menuRegister->get("game"))->show(); } } else client->release(); } } return 1; }); } ServerStatus::~ServerStatus() { secrets->release(); closeAF->release(); join->release(); } void ServerStatus::updatePlayerName(Framework::Text playerName) { lockZeichnung(); status = ""; this->playerName = playerName; ServerStatus* tmp = dynamic_cast(getThis()); int id = ++requestId; unlockZeichnung(); new AsynchronCall([tmp, id]() { FactoryClient* client = new FactoryClient(); if (!client->connect(tmp->getIp(), tmp->getSSLPort())) { tmp->lockZeichnung(); if (tmp->requestId == id) { tmp->status = "The Server is currently not reachable"; tmp->statusId = 404; tmp->ping = -1; tmp->rend = 1; } tmp->unlockZeichnung(); } else { tmp->lockZeichnung(); if (tmp->requestId == id) { Text secret = ""; if (tmp->secrets->has(tmp->playerName)) secret = tmp->secrets->get(tmp->playerName); tmp->unlockZeichnung(); int ping = client->ping(); int statusId = client->status(tmp->playerName, secret); tmp->lockZeichnung(); if (tmp->requestId == id) { tmp->ping = ping; tmp->statusId = statusId; if (tmp->statusId == 200) tmp->status = "The Server is reachable"; if (tmp->statusId == 403) tmp->status = "The name is already in use"; tmp->rend = 1; } } tmp->unlockZeichnung(); } client->release(); tmp->release(); }); } void ServerStatus::doMausEreignis(Framework::MausEreignis& me, bool userRet) { if (me.id == ME_Leaves) { closeAF->setStrength(0); closeAF->setFarbe(0x00FF0000); } else if (me.id == ME_Bewegung) { if (me.mx >= gr.x - 20 && me.mx < gr.x && me.my >= 0 && me.my <= 20) { if (closeAF->getStrength() == 0) { closeAF->setStrength(-5); closeAF->setFarbe(0x30FF0000); } } else { if (closeAF->getStrength() != 0) { closeAF->setStrength(0); closeAF->setFarbe(0x00FF0000); } } } if (me.id == ME_RLinks) { if (me.mx >= gr.x - 20 && me.mx < gr.x && me.my >= 0 && me.my <= 20) { ((ServerSelectionMenu*)(Menu*)menuRegister->get("serverSelection"))->removeServer(name); return; } } if (canConnect()) join->doPublicMausEreignis(me); } bool ServerStatus::tick(double time) { join->setPosition(gr.x - 60, gr.y - 25); closeAF->setPosition(gr.x - 20, 0); return ZeichnungHintergrund::tick(time) || join->tick(time) || closeAF->tick(time); } void ServerStatus::render(Framework::Bild& rObj) { ZeichnungHintergrund::render(rObj); if (rObj.setDrawOptions(pos, gr)) { TextRenderer tr(dynamic_cast(uiFactory.initParam.schrift->getThis())); tr.setSchriftSize(12); tr.renderText(5, 5, name, rObj, 0xFFFFFFFF); tr.renderText(5, 25, ip + ":" + sslPort + " (" + port + ")", rObj, 0xFF808080); if (requestId && requestId != 404) { int tbr = tr.getTextBreite(Text("ping: ") + ping); if (ping >= 0) { tr.renderText(getBreite() - 25 - tbr, 5, Text("ping: ") + ping, rObj, 0xFFFFFFFF); } } if (statusId == 404 || statusId == 500) tr.renderText(5, 45, status, rObj, 0xFFFF0000); if (statusId == 403 || statusId == 201) tr.renderText(5, 45, status, rObj, 0xFFFFA500); if (statusId == 200) tr.renderText(5, 45, status, rObj, 0xFF00FF00); closeAF->render(rObj); rObj.drawLinie(Punkt(gr.x - 20, 0), Punkt(gr.x, 20), 0xFFFF0000); rObj.drawLinie(Punkt(gr.x - 20, 20), Punkt(gr.x, 0), 0xFFFF0000); if (canConnect()) join->render(rObj); rObj.releaseDrawOptions(); } } Framework::Text ServerStatus::getName() const { return name; } Framework::Text ServerStatus::getIp() const { return ip; } unsigned short ServerStatus::getSSLPort() const { return sslPort; } unsigned short ServerStatus::getPort() const { return port; } Framework::HashMap* ServerStatus::zSecrets() const { return secrets; } bool ServerStatus::canConnect() const { return statusId == 200 || statusId == 201; } ServerSelectionMenu::ServerSelectionMenu(Bildschirm* zScreen) : Menu(zScreen) { playerNameLabel = initTextFeld(zScreen->getBackBufferSize().x / 2 - 150, zScreen->getBackBufferSize().y / 2 - 300, 85, 20, TextFeld::Style::Text | TextFeld::Style::VCenter, "Player Name:"); elements.add(playerNameLabel); playerName = initTextFeld(zScreen->getBackBufferSize().x / 2 - 150 + 85, zScreen->getBackBufferSize().y / 2 - 300, 215, 20, TextFeld::Style::TextFeld, ""); playerName->setNTastaturEreignis([this](void* p, void* o, TastaturEreignis te) { // set player names of each server for (int i = 0; i < serverList->getEintragAnzahl(); i++) ((ServerStatus*)serverList->zEintrag(i))->updatePlayerName(playerName->zText()->getText()); saveServers(); return 1; }); elements.add(playerName); serverLabel = initTextFeld(zScreen->getBackBufferSize().x / 2 - 150, zScreen->getBackBufferSize().y / 2 - 275, 100, 20, TextFeld::Style::Text | TextFeld::Style::VCenter, "Server:"); elements.add(serverLabel); refresh = initKnopf(zScreen->getBackBufferSize().x / 2 + 80, zScreen->getBackBufferSize().y / 2 - 275, 70, 20, Knopf::Style::Normal, "Refresh"); refresh->setMausEreignis([this](void* p, void* o, Framework::MausEreignis me) { if (me.id == ME_RLinks) { if (playerName->zText()->getLength() > 0) { for (int i = 0; i < serverList->getEintragAnzahl(); i++) ((ServerStatus*)serverList->zEintrag(i))->updatePlayerName(playerName->zText()->getText()); } } return 1; }); elements.add(refresh); serverList = new ZListe(); serverList->setSize(300, 480); serverList->setRahmenBreite(1); serverList->setRahmenFarbe(0xFF6d6d6d); serverList->setPosition(zScreen->getBackBufferSize().x / 2 - 150, zScreen->getBackBufferSize().y / 2 - 250); serverList->setStyle(ZListe::Style::Normal | ZListe::Style::VScroll); serverList->setMausEreignis(_ret1ME); serverList->setVertikalScrollPos(0); serverList->setEntrySeperatorSize(1); serverList->setEntrySeperatorColor(0xFF6d6d6d); elements.add(serverList); add = initKnopf(zScreen->getBackBufferSize().x / 2 - 50, zScreen->getBackBufferSize().y / 2 + 235, 100, 20, Knopf::Style::Normal, "Add Server"); elements.add(add); add->setMausEreignis([this](void* p, void* o, Framework::MausEreignis me) { if (me.id == ME_RLinks) { hide(); menuRegister->get("addServer")->show(); } return 1; }); // load server json JSON::JSONValue* json = JSON::loadJSONFromFile("data/server.json"); if (json) { // build validator JSON::Validator::JSONValidator* validator = JSON::Validator::JSONValidator::buildForObject() ->withRequiredString("playerName")->withDefault("")->finishString() ->withRequiredAttribute("server", JSON::Validator::JSONValidator::buildForArray() ->withDefault(new JSON::JSONArray()) ->removeInvalidEntries() ->addAcceptedTypeInArray(JSON::Validator::JSONValidator::buildForObject() ->withRequiredString("name")->finishString() ->withRequiredString("ip")->finishString() ->withRequiredNumber("sslPort")->whichIsGreaterOrEqual(0)->whichIsLessOrEqual((double)0xFFFF)->finishNumber() ->withRequiredNumber("port")->whichIsGreaterOrEqual(0)->whichIsLessOrEqual((double)0xFFFF)->finishNumber() ->withRequiredAttribute("secrets", JSON::Validator::JSONValidator::buildForArray() ->addAcceptedObjectInArray() ->withRequiredString("secret")->finishString() ->withRequiredString("playerName")->finishString() ->finishObject()->finishArray()) ->finishObject()) ->finishArray()) ->finishObject(); JSON::JSONValue* validJson = validator->getValidParts(json); json->release(); if (validJson) { JSON::JSONArray* arr = validJson->asObject()->zValue("server")->asArray(); for (int i = 0; i < arr->getLength(); i++) { JSON::JSONObject* obj = arr->zValue(i)->asObject(); Framework::HashMap* secrets = new Framework::HashMap(10, [](Text t) { return t.hashCode(); }); JSON::JSONArray* secretsJson = obj->zValue("secrets")->asArray(); for (int j = 0; j < secretsJson->getLength(); j++) { JSON::JSONObject* obj2 = secretsJson->zValue(j)->asObject(); //decode base64 secret char* secretBuffer = 0; int length; Framework::base64Decode(obj2->zValue("secret")->asString()->getString(), &secretBuffer, &length); secrets->put(obj2->zValue("playerName")->asString()->getString(), Framework::Text(secretBuffer)); delete[] secretBuffer; } ServerStatus* s = new ServerStatus(obj->zValue("name")->asString()->getString(), obj->zValue("ip")->asString()->getString(), (unsigned short)obj->zValue("sslPort")->asNumber()->getNumber(), (unsigned short)obj->zValue("port")->asNumber()->getNumber(), secrets); s->setSize(300, 65); serverList->addEintrag(s); } playerName->setText(validJson->asObject()->zValue("playerName")->asString()->getString()); if (playerName->zText()->getLength() > 0) { for (int i = 0; i < serverList->getEintragAnzahl(); i++) ((ServerStatus*)serverList->zEintrag(i))->updatePlayerName(playerName->zText()->getText()); } serverList->updateVScroll(); validJson->release(); } validator->release(); } } void ServerSelectionMenu::addServer(Framework::Text name, Framework::Text ip, unsigned short sslPort, unsigned short port) { ServerStatus* tmp = new ServerStatus(name, ip, sslPort, port, new HashMap< Framework::Text, Framework::Text>(10, [](Text t) { return t.hashCode(); })); tmp->setSize(300, 65); serverList->addEintrag(tmp); tmp->updatePlayerName(playerName->zText()->getText()); serverList->updateVScroll(); saveServers(); } bool ServerSelectionMenu::hasServer(Framework::Text name) const { for (int i = 0; i < serverList->getEintragAnzahl(); i++) { if (((ServerStatus*)serverList->zEintrag(i))->getName() == name) return 1; } return 0; } void ServerSelectionMenu::removeServer(Framework::Text name) const { for (int i = 0; i < serverList->getEintragAnzahl(); i++) { if (((ServerStatus*)serverList->zEintrag(i))->getName() == name) serverList->removeEintrag(i); } serverList->updateVScroll(); saveServers(); } void ServerSelectionMenu::saveServers() const { Datei file; file.setDatei("data/server.json"); file.open(Datei::Style::schreiben); JSON::JSONObject root; JSON::JSONArray* servers = new JSON::JSONArray(); for (int i = 0; i < serverList->getEintragAnzahl(); i++) { JSON::JSONObject* server = new JSON::JSONObject(); server->addValue("name", new JSON::JSONString(((ServerStatus*)serverList->zEintrag(i))->getName())); server->addValue("ip", new JSON::JSONString(((ServerStatus*)serverList->zEintrag(i))->getIp())); server->addValue("sslPort", new JSON::JSONNumber(((ServerStatus*)serverList->zEintrag(i))->getSSLPort())); server->addValue("port", new JSON::JSONNumber(((ServerStatus*)serverList->zEintrag(i))->getPort())); JSON::JSONArray* secrets = new JSON::JSONArray(); for (auto secretEntry : *((ServerStatus*)serverList->zEintrag(i))->zSecrets()) { JSON::JSONObject* secret = new JSON::JSONObject(); secret->addValue("playerName", new JSON::JSONString(secretEntry.getKey())); // base64 encode secret Framework::Text secretBase64 = Framework::base64Encode(secretEntry.getValue(), secretEntry.getValue().getLength()); secret->addValue("secret", new JSON::JSONString(secretBase64)); secrets->addValue(secret); } server->addValue("secrets", secrets); servers->addValue(server); } root.addValue("server", servers); root.addValue("playerName", new JSON::JSONString(playerName->zText()->getText())); Framework::Text json = root.toString(); file.schreibe(json, json.getLength()); file.close(); }