#include "ServerSelection.h" #include #include #include #include #include #include #include #include #include #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("..."), statusId(0), requestId(0), secrets(secrets), join(initKnopf(0, 0, 55, 20, Knopf::Style::Normal, "join")) { 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); if (statusId == 203) secret = ""; 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; }); LTDBDatei iconsDat; iconsDat.setDatei(new Text("data/images/gui_icons.ltdb")); iconsDat.leseDaten(0); removeButton = initKnopf(0, 0, 20, 20, Framework::Knopf::Style::HBild | Framework::Knopf::Style::HAlpha | Framework::Knopf::Style::Hintergrund, ""); removeButton->setRahmenFarbe(0xFF9C0A0A); removeButton->setAlphaFeldFarbe(0x5F9C0A0A); removeButton->setToolTipText("Remove player from list of ignored players", uiFactory.initParam.bildschirm, uiFactory.initParam.schrift); removeButton->setHintergrundBildZ( dynamic_cast(iconsDat.laden(0, new Text("trash.png")))); removeButton->setMausEreignis([this](void* p, void* o, MausEreignis me) { if (me.id == ME_RLinks) { ((ServerSelectionMenu*)(Menu*)menuRegister->get("serverSelection")) ->removeServer(this->name); } return 1; }); } ServerStatus::~ServerStatus() { secrets->release(); removeButton->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); if (statusId == 403) { int secondStatus = client->status(tmp->playerName, ""); if (secondStatus == 200) statusId = 203; } if (secret.istGleich("") && statusId == 200) { statusId = 203; } tmp->lockZeichnung(); if (tmp->requestId == id) { tmp->ping = ping; tmp->statusId = statusId; if (tmp->statusId == 200) tmp->status = "The Server is reachable"; if (statusId == 203) tmp->status = "Create a new player"; 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) { removeButton->doPublicMausEreignis(me); if (canConnect()) join->doPublicMausEreignis(me); } bool ServerStatus::tick(double time) { join->setPosition(gr.x - 60, gr.y - 25); removeButton->setPosition(gr.x - 20, 0); return ZeichnungHintergrund::tick(time) || join->tick(time) || removeButton->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 || statusId == 203) tr.renderText(5, 45, status, rObj, 0xFFFFA500); if (statusId == 200) tr.renderText(5, 45, status, rObj, 0xFF00FF00); removeButton->render(rObj); 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 || statusId == 203; } 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; }); exit = initKnopf(zScreen->getBackBufferSize().x / 2 - 50, zScreen->getBackBufferSize().y / 2 + 285, 100, 20, Knopf::Style::Normal, "Beenden"); elements.add(exit); exit->setRahmenFarbe(0xFF9C0A0A); exit->setAlphaFeldStrength(10); exit->setAlphaFeldFarbe(0x5F9C0A0A); exit->setMausEreignis([this](void* p, void* o, Framework::MausEreignis me) { if (me.id == ME_RLinks) { hide(); StopNachrichtenSchleife(0); } 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(); RCArray removedParts; JSON::JSONValue* validJson = validator->getValidParts(json, &removedParts); 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( 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(); }