/* * pawsloginwindow.h - Author: Andrew Craig * * Copyright (C) 2003 Atomic Blue (info@planeshift.it, http://www.atomicblue.org) * * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation (version 2 of the License) * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ #include #include #include #include #include "iclient/netmanager.h" #include "iclient/isoundmngr.h" #include "pawsloginwindow.h" #include "paws/pawsmanager.h" #include "paws/pawstextbox.h" #include "paws/pawsokbox.h" #include "paws/pawslistbox.h" #include "csutil/csmd5.h" #include "util/pscssetup.h" #include "net/serverpinger.h" #include "psmainwidget.h" #include "globals.h" #define LOGIN_WINDOW_QUIT 100 #define LOGIN_WINDOW_LOGIN 101 #define LOGIN_WINDOW_CREDITS 102 #define SERVER_LIST_FILE "/planeshift/data/servers.xml" #define ASTERISKS "********" #define CNF_REMEMBER_SERVER "Planeshift.Connection.RememberServer" #define CNF_REMEMBER_PASS "Planeshift.Connection.RememberPass" #define CNF_USER "Planeshift.Connection.%s.User" #define CNF_PASSWORD "Planeshift.Connection.%s.Password" pawsLoginWindow::pawsLoginWindow() { connecting = false; passwdChanged = false; serverIP.Clear(); LoadServerList(); } bool pawsLoginWindow::PostSetup() { listBox = dynamic_cast (FindWidget("servers")); if (listBox == NULL) return false; if (servers.Length() == 0) { Error1("List of servers is empty. You must add servers to data/servers.xml file first."); return false; } for (size_t x = 0; x < servers.Length(); x++ ) { pawsListBoxRow* row = listBox->NewRow(); pawsTextBox* name = dynamic_cast (row->GetColumn(0)); if (name == NULL) return false; name->SetText( servers[x]->GetName() ); pawsTextBox* ip = dynamic_cast (row->GetColumn(1)); if (ip == NULL) return false; ip->SetText( servers[x]->GetAddress() ); } // Load the stored settings. csRef cfg = CS_QUERY_REGISTRY(PawsManager::GetSingleton().GetObjectRegistry(), iConfigManager); // Get default server int defaultServer = cfg->GetInt(CNF_REMEMBER_SERVER, 0); if (defaultServer >= (int)servers.Length()) defaultServer = 0; listBox->Select( listBox->GetRow(defaultServer), false ); // Update but do not notify self if ((int)servers.Length() > defaultServer) { serverIP = listBox->GetTextCellValue(defaultServer, 1); serverPort = servers[defaultServer]->GetPort(); } login = dynamic_cast (FindWidget("username")); if (login == NULL) return false; passwd = dynamic_cast (FindWidget("password")); if (passwd == NULL) return false; passwd->SetPassword(true); connectingLabel = dynamic_cast (FindWidget("connecting")); if (connectingLabel == NULL) return false; UpdateUserPasswdFromConfig(); remember = cfg->GetBool(CNF_REMEMBER_PASS, true); checkBox = dynamic_cast (FindWidget("option_password")); if (checkBox) checkBox->SetState(remember); // Set the version label pawsTextBox* version = dynamic_cast (FindWidget("version")); if (version == NULL) return false; version->SetText(APPNAME); PawsManager::GetSingleton().SetCurrentFocusedWidget(login); static bool first = true; //psMainWidget* ps = (psMainWidget*)PawsManager::GetSingleton().GetMainWidget(); if(first) { psSystemMessage msg(0,MSG_OK,PawsManager::GetSingleton().Translate("Welcome to PlaneShift!")); msg.FireEvent(); first = false; } else { psSystemMessage msg(0,MSG_RESULT,PawsManager::GetSingleton().Translate("Please re-login")); msg.FireEvent(); } return true; } void pawsLoginWindow::UpdateUserPasswdFromConfig() { csString cfg_name,user; // Load the stored settings. csRef cfg = CS_QUERY_REGISTRY(PawsManager::GetSingleton().GetObjectRegistry(), iConfigManager); cfg_name.Format(CNF_USER,servers[listBox->GetSelectedRowNum()]->GetName().GetData()); user = cfg->GetStr(cfg_name, ""); // For backward compability, if not found check Planeshift.Connection.User if (user.IsEmpty()) { cfg_name = "Planeshift.Connection.User"; user = cfg->GetStr(cfg_name, ""); } login->SetText (user); cfg_name.Format(CNF_PASSWORD,servers[listBox->GetSelectedRowNum()]->GetName().GetData()); storedPasswd = cfg->GetStr(cfg_name, ""); // For backward compability, if not found check Planeshift.Connection.Password if (storedPasswd.IsEmpty()) { cfg_name = "Planeshift.Connection.Password"; storedPasswd = cfg->GetStr(cfg_name, ""); } if (storedPasswd.IsEmpty() == false) passwd->SetText(ASTERISKS); else passwd->SetText(""); } bool pawsLoginWindow::OnChange(pawsWidget * widget) { if (widget==passwd && !passwdChanged) { csString text = passwd->GetText(); for (int i = 0; i < (int)text.Length();i++) { if (text.GetAt(i) != '*') { csString newtext = text.GetAt(i); passwdChanged = true; passwd->SetText(newtext); return true; } } passwdChanged = true; passwd->SetText(""); } return true; } bool pawsLoginWindow::OnButtonPressed( int mouseButton, int keyModifier, pawsWidget* widget ) { switch( widget->GetID() ) { case LOGIN_WINDOW_QUIT: { psengine->QuitClient(); return true; } case LOGIN_WINDOW_LOGIN: { if (connecting) break; if ( strlen(login->GetText()) == 0) { psSystemMessage error(0,MSG_ERROR,"Please enter you account name"); error.FireEvent(); return true; } if ( strlen(passwd->GetText()) == 0) { psSystemMessage error(0,MSG_ERROR,"Please enter you password"); error.FireEvent(); return true; } if (serverIP.Length() == 0) { psSystemMessage error(0,MSG_ERROR,"Missing entry for server!"); error.FireEvent(); return true; } switch (servers[listBox->GetSelectedRowNum()]->GetStatus()){ case psServerPinger::INIT: case psServerPinger::FAILED: { psSystemMessage error(0,MSG_ERROR,"The server isn't available!"); error.FireEvent(); return true; } case psServerPinger::FULL: // GM's should be able to connect, even if server is full. // So in this case the server have to decide if it accept the // connection. ConnectToServer(); return true; case psServerPinger::LOCKED: { psSystemMessage error(0,MSG_ERROR,"The server is locked!"); error.FireEvent(); return true; } case psServerPinger::WAIT: { psSystemMessage error(0,MSG_ERROR,"The server isn't ready!"); error.FireEvent(); return true; } case psServerPinger::READY: ConnectToServer(); return true; } return true; } case LOGIN_WINDOW_CREDITS: { if (connecting) break; pawsWidget* wdg = PawsManager::GetSingleton().FindWidget("CreditsWindow"); if (!wdg) { PawsManager::GetSingleton().LoadWidget("data/gui/creditswindow.xml"); Hide(); return true; } wdg->Show(); Hide(); return true; } } return false; } void pawsLoginWindow::ConnectToServer() { csRef cfg = CS_QUERY_REGISTRY(PawsManager::GetSingleton().GetObjectRegistry(), iConfigManager); // Set the time out to connect to server timeout = csGetTicks() + cfg->GetInt("Planeshift.Client.User.Connecttimeout", 60) * 1000; connectingLabel->SetText("Connecting to server... Please wait"); // to make sure the "Connecting" label is visible: PawsManager::GetSingleton().GetGraphics3D()->BeginDraw (CSDRAW_2DGRAPHICS); PawsManager::GetSingleton().Draw (); PawsManager::GetSingleton().GetGraphics3D()->FinishDraw (); PawsManager::GetSingleton().GetGraphics2D()->Print (0); if ( !psengine->GetNetManager()->Connect( serverIP, serverPort ) ) { psSystemMessage error(0,MSG_ERROR,"Cannot connect to server!"); error.FireEvent(); psengine->GetNetManager()->Disconnect(); ConnectionFailed(); return; } /// Set up the picker window here. if ( PawsManager::GetSingleton().FindWidget("CharPickerWindow") == 0 ) PawsManager::GetSingleton().LoadWidget("data/gui/charpick.xml"); if (passwdChanged) { csString passwordhash = csMD5::Encode(passwd->GetText()).HexString(); psengine->GetNetManager()->Authenticate( login->GetText(), passwordhash.GetData() ); } else { psengine->GetNetManager()->Authenticate( login->GetText(), storedPasswd ); } SaveLoginInformation(); connecting = true; } void pawsLoginWindow::ConnectionFailed() { connecting = false; connectingLabel->SetText("New User? Register at http://laanx.fragnetics.com/register"); } void pawsLoginWindow::SaveLoginInformation() { csRef cfg = CS_QUERY_REGISTRY (PawsManager::GetSingleton().GetObjectRegistry(), iConfigManager); csString cnf_name; cfg->SetInt(CNF_REMEMBER_SERVER, listBox->GetSelectedRowNum()); cnf_name.Format(CNF_USER,servers[listBox->GetSelectedRowNum()]->GetName().GetData()); cfg->SetStr(cnf_name, login->GetText() ); if (checkBox) remember = checkBox->GetState(); cfg->SetBool(CNF_REMEMBER_PASS, remember); if (remember) { if (passwdChanged) { csString passwordhash = csMD5::Encode(passwd->GetText()).HexString(); cnf_name.Format(CNF_PASSWORD,servers[listBox->GetSelectedRowNum()]->GetName().GetData()); cfg->SetStr(cnf_name, passwordhash.GetData() ); } } else { cfg->DeleteKey("Planeshift.Connection.Password"); // TODO: Loop through all servers and delete password key cnf_name.Format(CNF_PASSWORD,servers[listBox->GetSelectedRowNum()]->GetName().GetData()); cfg->DeleteKey(cnf_name); } cfg->Save(); } bool pawsLoginWindow::LoadServerList() { iDocumentSystem* xml = psengine->GetXMLParser (); csRef vfs = CS_QUERY_REGISTRY( PawsManager::GetSingleton().GetObjectRegistry(), iVFS ); csRef buff = vfs->ReadFile( SERVER_LIST_FILE ); if ( !buff || !buff->GetSize() ) { Error2("File %s not found!", SERVER_LIST_FILE); return false; } csRef doc = xml->CreateDocument(); const char* error = doc->Parse( buff ); if ( error ) { Error2("ERROR: %s", error ); return false; } csRef root = doc->GetRoot(); if(!root) { Error1("No XML root"); return false; } csRef topNode = root->GetNode("serverlist"); if (topNode == NULL) { Error1("No tag"); return false; } csRef iter = topNode->GetNodes(); while ( iter->HasNext() ) { csRef node = iter->Next(); if(node->GetType() == CS_NODE_COMMENT) continue; int port; csRef portAttr = node->GetAttribute("port"); if (portAttr != NULL) port = portAttr->GetValueAsInt(); else port = 13331; psServerPinger * server = new psServerPinger(node->GetAttributeValue( "name" ), node->GetAttributeValue( "ip" ), port, PawsManager::GetSingleton().GetObjectRegistry()); server->Connect(); servers.Push( server ); } return true; } void pawsLoginWindow::OnListAction( pawsListBox* selected, int status ) { if (listBox->GetSelectedRowNum() == -1) return; serverIP = listBox->GetTextCellValue(listBox->GetSelectedRowNum(), 1); serverPort = servers[listBox->GetSelectedRowNum()]->GetPort(); UpdateUserPasswdFromConfig(); } void pawsLoginWindow::Show() { // Play some music if(psengine->GetSoundStatus()) { psengine->GetSoundManager()->OverrideBGSong("mainmenu"); } pawsWidget::Show(); } void pawsLoginWindow::Hide() { for (size_t i=0; i < servers.Length(); i++) servers[i]->Disconnect(); pawsWidget::Hide(); } void pawsLoginWindow::Draw() { // Check timeout if(connecting && csGetTicks() >= timeout) { psengine->GetNetManager()->Disconnect(); ConnectionFailed(); PawsManager::GetSingleton().CreateWarningBox("The server is not running or is not reachable. Please check the website or forums for more info."); } csString pingStr; for (size_t i=0; i < servers.Length(); i++) { servers[i]->DoYourWork(); int ping = servers[i]->GetPing(); int loss = (int)(servers[i]->GetLoss()*100.0f); switch (servers[i]->GetStatus()) { case psServerPinger::INIT: pingStr = ""; break; case psServerPinger::FAILED: pingStr = "Failed"; break; case psServerPinger::FULL: pingStr = "Full"; break; case psServerPinger::READY: if (loss == 100) pingStr = "Failed"; else if (loss) pingStr.Format("%d %d%%",ping,loss); else pingStr.Format("%d",ping); break; case psServerPinger::LOCKED: pingStr = "Locked"; break; case psServerPinger::WAIT: pingStr = "Wait"; break; default: pingStr = "Error"; break; } listBox->SetTextCellValue((int)i, 2, pingStr); } pawsWidget::Draw(); }