#include "ServerSelection.h" #include #include #include #include #include #include #include #include #include #include #include "FactoryClient.h" #include "Globals.h" #include "Initialization.h" #include "Load.h" using namespace Framework; ServerStatus::ServerStatus(Framework::Text name, Framework::Text ip, unsigned short sslPort, unsigned short port, Framework::HashMap* secrets) : DrawableBackground(), name(name), ip(ip), sslPort(sslPort), port(port), playerName(""), ping(-1), status("..."), statusId(0), requestId(0), secrets(secrets), join(initButton(0, 0, 55, 20, Button::Style::Normal, "join")) { setMouseEvent(_ret1ME); setStyle(Style::Allowed | Style::Visible | Style::Border); setBorderWidth(1); setBorderColor(0xFF3d3d3d); join->setMouseEvent([this](void* p, void* o, MouseEvent me) { if (me.id == ME_RLeft) { FactoryClient* client = new FactoryClient(); if (!client->connect(getIp(), getSSLPort())) { lockDrawable(); status = "The Server is currently not reachable"; statusId = 404; ping = -1; rend = 1; unlockDrawable(); client->release(); } else { Text secret = ""; if (this->secrets->has(playerName)) secret = this->secrets->get(playerName); if (statusId == 203) secret = ""; bool isNew = secret.getLength() == 0; menuRegister->get("serverSelection")->hide(); menuRegister->get("load")->show(); ((LoadMenu*)(Menu*)menuRegister->get("load")) ->load(client, playerName, secret, getPort(), [this, isNew, client](int result, Text secret) { menuRegister->get("load")->hide(); lockDrawable(); statusId = result; 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"; unlockDrawable(); if (statusId == 200 || statusId == 201) { if (isNew) { this->secrets->put(playerName, secret); ((ServerSelectionMenu*)(Menu*)menuRegister ->get("serverSelection")) ->saveServers(); } if (statusId == 200) { World::INSTANCE = new World(dynamic_cast( window->zScreen()), client); menuRegister->get("game")->show(); } else { menuRegister->get("serverSelection") ->show(); client->release(); } } else { menuRegister->get("serverSelection")->show(); client->release(); } }); } } return 1; }); LTDBFile iconsDat; iconsDat.setFile(new Text("data/images/gui_icons.ltdb")); iconsDat.readData(0); removeButton = initButton(0, 0, 20, 20, Framework::Button::Style::BImage | Framework::Button::Style::BAlpha | Framework::Button::Style::Background, ""); removeButton->setBorderColor(0xFF9C0A0A); removeButton->setAlphaFieldColor(0x5F9C0A0A); removeButton->setToolTipText("Remove player from list of ignored players", uiFactory.initParam.bildschirm, uiFactory.initParam.font); removeButton->setBackgroundImageZ( dynamic_cast(iconsDat.load(0, new Text("trash.png")))); removeButton->setMouseEvent([this](void* p, void* o, MouseEvent me) { if (me.id == ME_RLeft) { ((ServerSelectionMenu*)(Menu*)menuRegister->get("serverSelection")) ->removeServer(this->name); } return 1; }); } ServerStatus::~ServerStatus() { secrets->release(); removeButton->release(); join->release(); } void ServerStatus::updatePlayerName(Framework::Text playerName) { lockDrawable(); status = ""; this->playerName = playerName; ServerStatus* tmp = dynamic_cast(getThis()); int id = ++requestId; unlockDrawable(); new AsynchronCall([tmp, id]() { FactoryClient* client = new FactoryClient(); if (!client->connect(tmp->getIp(), tmp->getSSLPort())) { tmp->lockDrawable(); if (tmp->requestId == id) { tmp->status = "The Server is currently not reachable"; tmp->statusId = 404; tmp->ping = -1; tmp->rend = 1; } tmp->unlockDrawable(); } else { tmp->lockDrawable(); if (tmp->requestId == id) { Text secret = ""; if (tmp->secrets->has(tmp->playerName)) secret = tmp->secrets->get(tmp->playerName); tmp->unlockDrawable(); 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.isEqual("") && statusId == 200) { statusId = 203; } tmp->lockDrawable(); 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->unlockDrawable(); } client->release(); tmp->release(); }); } void ServerStatus::doMouseEvent(Framework::MouseEvent& me, bool userRet) { removeButton->doPublicMouseEvent(me); if (canConnect()) join->doPublicMouseEvent(me); } bool ServerStatus::tick(double time) { join->setPosition(gr.x - 60, gr.y - 25); removeButton->setPosition(gr.x - 20, 0); return DrawableBackground::tick(time) || join->tick(time) || removeButton->tick(time); } void ServerStatus::render(Framework::Image& rObj) { DrawableBackground::render(rObj); if (rObj.setDrawOptions(pos, gr)) { TextRenderer tr( dynamic_cast(uiFactory.initParam.font->getThis())); tr.setFontSize(12); tr.renderText(5, 5, name, rObj, 0xFFFFFFFF); tr.renderText( 5, 25, ip + ":" + sslPort + " (" + port + ")", rObj, 0xFF808080); if (requestId && requestId != 404) { int tbr = tr.getTextWidth(Text("ping: ") + ping); if (ping >= 0) { tr.renderText(getWidth() - 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(Screen* zScreen) : Menu(zScreen) { playerNameLabel = initTextField(zScreen->getBackBufferSize().x / 2 - 150, zScreen->getBackBufferSize().y / 2 - 300, 85, 20, TextField::Style::Text | TextField::Style::VCenter, "Player Name:"); elements.add(playerNameLabel); playerName = initTextField(zScreen->getBackBufferSize().x / 2 - 150 + 85, zScreen->getBackBufferSize().y / 2 - 300, 215, 20, TextField::Style::TextField, ""); playerName->setPostKeyboardEvent( [this](void* p, void* o, KeyboardEvent te) { // set player names of each server for (int i = 0; i < serverList->getEntryCount(); i++) ((ServerStatus*)serverList->zEntry(i)) ->updatePlayerName(playerName->zText()->getText()); saveServers(); return 1; }); elements.add(playerName); serverLabel = initTextField(zScreen->getBackBufferSize().x / 2 - 150, zScreen->getBackBufferSize().y / 2 - 275, 100, 20, TextField::Style::Text | TextField::Style::VCenter, "Server:"); elements.add(serverLabel); refresh = initButton(zScreen->getBackBufferSize().x / 2 + 80, zScreen->getBackBufferSize().y / 2 - 275, 70, 20, Button::Style::Normal, "Refresh"); refresh->setMouseEvent([this](void* p, void* o, Framework::MouseEvent me) { if (me.id == ME_RLeft) { if (playerName->zText()->getLength() > 0) { for (int i = 0; i < serverList->getEntryCount(); i++) ((ServerStatus*)serverList->zEntry(i)) ->updatePlayerName(playerName->zText()->getText()); } } return 1; }); elements.add(refresh); serverList = new DrawableList(); serverList->setSize(300, 480); serverList->setBorderWidth(1); serverList->setBorderColor(0xFF6d6d6d); serverList->setPosition(zScreen->getBackBufferSize().x / 2 - 150, zScreen->getBackBufferSize().y / 2 - 250); serverList->setStyle( DrawableList::Style::Normal | DrawableList::Style::VScroll); serverList->setMouseEvent(_ret1ME); serverList->setVerticalScrollPos(0); serverList->setEntrySeperatorSize(1); serverList->setEntrySeperatorColor(0xFF6d6d6d); elements.add(serverList); add = initButton(zScreen->getBackBufferSize().x / 2 - 50, zScreen->getBackBufferSize().y / 2 + 235, 100, 20, Button::Style::Normal, "Add Server"); elements.add(add); add->setMouseEvent([this](void* p, void* o, Framework::MouseEvent me) { if (me.id == ME_RLeft) { hide(); menuRegister->get("addServer")->show(); } return 1; }); exit = initButton(zScreen->getBackBufferSize().x / 2 - 50, zScreen->getBackBufferSize().y / 2 + 285, 100, 20, Button::Style::Normal, "Beenden"); elements.add(exit); exit->setBorderColor(0xFF9C0A0A); exit->setAlphaFieldStrength(10); exit->setAlphaFieldColor(0x5F9C0A0A); exit->setMouseEvent([this](void* p, void* o, Framework::MouseEvent me) { if (me.id == ME_RLeft) { hide(); StopMessageLoop(0); } return 1; }); // load server json JSON::JSONValue* json = JSON::loadJSONFromFile("data/server.json"); if (json) { // build validator Validator::DataValidator* validator = Validator::DataValidator::buildForObject() ->withRequiredString("playerName") ->withDefault("") ->finishString() ->withRequiredAttribute("server", Validator::DataValidator::buildForArray() ->withDefault(new JSON::JSONArray()) ->removeInvalidEntries() ->addAcceptedTypeInArray( Validator::DataValidator::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", Validator::DataValidator::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->addEntry(s); } playerName->setText(validJson->asObject() ->zValue("playerName") ->asString() ->getString()); if (playerName->zText()->getLength() > 0) { for (int i = 0; i < serverList->getEntryCount(); i++) ((ServerStatus*)serverList->zEntry(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->addEntry(tmp); tmp->updatePlayerName(playerName->zText()->getText()); serverList->updateVScroll(); saveServers(); } bool ServerSelectionMenu::hasServer(Framework::Text name) const { for (int i = 0; i < serverList->getEntryCount(); i++) { if (((ServerStatus*)serverList->zEntry(i))->getName() == name) return 1; } return 0; } void ServerSelectionMenu::removeServer(Framework::Text name) const { for (int i = 0; i < serverList->getEntryCount(); i++) { if (((ServerStatus*)serverList->zEntry(i))->getName() == name) serverList->removeEntry(i); } serverList->updateVScroll(); saveServers(); } void ServerSelectionMenu::saveServers() const { File file; file.setFile("data/server.json"); file.open(File::Style::write); JSON::JSONObject root; JSON::JSONArray* servers = new JSON::JSONArray(); for (int i = 0; i < serverList->getEntryCount(); i++) { JSON::JSONObject* server = new JSON::JSONObject(); server->addValue("name", new JSON::JSONString( ((ServerStatus*)serverList->zEntry(i))->getName())); server->addValue("ip", new JSON::JSONString( ((ServerStatus*)serverList->zEntry(i))->getIp())); server->addValue("sslPort", new JSON::JSONNumber( ((ServerStatus*)serverList->zEntry(i))->getSSLPort())); server->addValue("port", new JSON::JSONNumber( ((ServerStatus*)serverList->zEntry(i))->getPort())); JSON::JSONArray* secrets = new JSON::JSONArray(); for (auto secretEntry : *((ServerStatus*)serverList->zEntry(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.write(json, json.getLength()); file.close(); }