Resolve "Toggle Free Look with Hotkey"
[ryzomcore.git] / ryzom / client / src / login.cpp
blob8956df99151c42f0390b70657cf02700c7c12762
1 // Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
2 // Copyright (C) 2010-2019 Winch Gate Property Limited
3 //
4 // This source file has been modified by the following contributors:
5 // Copyright (C) 2013 Laszlo KIS-ADAM (dfighter) <dfighter1985@gmail.com>
6 // Copyright (C) 2014-2020 Jan BOON (Kaetemi) <jan.boon@kaetemi.be>
7 //
8 // This program is free software: you can redistribute it and/or modify
9 // it under the terms of the GNU Affero General Public License as
10 // published by the Free Software Foundation, either version 3 of the
11 // License, or (at your option) any later version.
13 // This program is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 // GNU Affero General Public License for more details.
18 // You should have received a copy of the GNU Affero General Public License
19 // along with this program. If not, see <http://www.gnu.org/licenses/>.
21 //////////////
22 // Includes //
23 //////////////
24 #include "stdpch.h"
26 #include "login.h"
27 #include "login_patch.h"
29 #include "nel/misc/common.h"
30 #include "nel/misc/debug.h"
31 #include "nel/misc/path.h"
32 #include "nel/misc/thread.h"
33 #include "nel/misc/big_file.h"
34 #include "nel/misc/system_utils.h"
35 #include "nel/misc/streamed_package_manager.h"
37 #include "nel/net/tcp_sock.h"
38 #include "nel/3d/u_driver.h"
39 #include "nel/misc/big_file.h"
41 #include "interface_v3/interface_manager.h"
42 #include "interface_v3/input_handler_manager.h"
43 #include "nel/gui/group_editbox.h"
44 #include "interface_v3/group_quick_help.h"
45 #include "nel/gui/view_text.h"
46 #include "nel/gui/ctrl_button.h"
47 #include "nel/gui/ctrl_text_button.h"
48 #include "nel/gui/dbgroup_combo_box.h"
49 #include "sound_manager.h"
50 #include "far_tp.h"
52 #include "actions_client.h"
53 #include "time_client.h"
54 #include "client_cfg.h"
55 #include "global.h"
56 #include "input.h"
57 #include "nel/gui/libwww.h"
58 #include "nel/web/http_client_curl.h"
59 #include "login_progress_post_thread.h"
61 #include "init.h"
62 #include "release.h"
63 #include "bg_downloader_access.h"
65 #include "game_share/crypt.h"
66 #include "game_share/bg_downloader_msg.h"
68 #include "misc.h"
69 #include "user_agent.h"
71 void ConnectToShard();
73 // ***************************************************************************
75 using namespace NLMISC;
76 using namespace NLWEB;
77 using namespace NLNET;
78 using namespace NL3D;
79 using namespace std;
81 #ifdef DEBUG_NEW
82 #define new DEBUG_NEW
83 #endif
85 // ***************************************************************************
87 extern bool SetMousePosFirstTime;
89 vector<CShard> Shards;
91 string LoginLogin, LoginPassword, ClientApp, Salt, LoginCustomParameters;
92 uint32 LoginShardId = 0xFFFFFFFF;
95 // Completed only after that ryzom downloader has run its 'check' task :
96 // It is a bitfield indexed by BGDownloader::TDownloadID that indicate the parts that are available for patch
97 uint32 AvailablePatchs = 0;
98 // next wanted patch for the background downloader
99 BGDownloader::TDownloadID BGDownloaderWantedPatch = BGDownloader::DownloadID_RoS;
103 // R2 mode var ---------------
105 /// domain server version for patch
106 string R2ServerVersion;
107 /// name of the version (used to alias many version under the same name),
108 /// the value is used to get the release not if not empty
109 string VersionName;
110 /// Backup patch server to use in case of failure of all other servers
111 string R2BackupPatchURL;
112 /// a list of patch server to use randomly
113 vector<string> R2PatchURLs;
116 #define CTRL_EDITBOX_LOGIN "ui:login:checkpass:content:eb_login:eb"
117 #define CTRL_EDITBOX_PASSWORD "ui:login:checkpass:content:eb_password:eb"
118 #define GROUP_LIST_SHARD "ui:login:sharddisp:content:shard_list"
119 #define CTRL_BUTTON_CONNECT "ui:login:sharddisp:content:but_con"
120 #define GROUP_LIST_CAT "ui:login:catdisp:content:cat_list"
121 #define CTRL_BUTTON_CLOSE_PATCH "ui:login:patching:content:but_close"
122 #define VIEW_TOTAL_SIZE "ui:login:catdisp:content:global_patch:size"
123 #define VIEW_NON_OPTIONAL_SIZE "ui:login:catdisp:content:nonopt_patch:size"
124 #define VIEW_TOTAL_SIZE_PATCH "ui:login:patching:content:global_patch:size"
125 #define CTRL_BUTTON_BACKTOLOGIN "ui:login:webstart:content:back_to_login"
126 #define CTRL_BUTTON_RELOADTESTPAGE "ui:login:webstart:content:reload_test_page"
127 #define CTRL_EDITBOX_CREATEACCOUNT_LOGIN "ui:login:create_account:content:submit_gr:eb_login:eb"
128 #define CTRL_EDITBOX_CREATEACCOUNT_PASSWORD "ui:login:create_account:content:submit_gr:eb_password:eb"
129 #define CTRL_EDITBOX_CREATEACCOUNT_CONFIRMPASSWORD "ui:login:create_account:content:submit_gr:eb_confirm_password:eb"
130 #define CTRL_EDITBOX_CREATEACCOUNT_EMAIL "ui:login:create_account:content:submit_gr:eb_email:eb"
132 #define UI_VARIABLES_SCREEN_CHECKPASS 0
133 #define UI_VARIABLES_SCREEN_SHARDDISP 1
134 #define UI_VARIABLES_SCREEN_CHECKING 2
135 #define UI_VARIABLES_SCREEN_CATDISP 3
136 #define UI_VARIABLES_SCREEN_PATCHING 4
137 #define UI_VARIABLES_SCREEN_REBOOT 5
138 #define UI_VARIABLES_SCREEN_EULA 6
139 #define UI_VARIABLES_SCREEN_DATASCAN 7
140 #define UI_VARIABLES_SCREEN_CREATE_ACCOUNT 9
143 // ***************************************************************************
144 // ***************************************************************************
145 // ***************************************************************************
146 // INTERFACE
147 // ***************************************************************************
148 // ***************************************************************************
149 // ***************************************************************************
151 bool loginFinished = false;
152 bool loginOK = false;
153 sint32 ShardSelected = -1;
154 CPatchManager::SPatchInfo InfoOnPatch;
155 uint32 TotalPatchSize;
157 CLoginStateMachine LoginSM;
159 // TODO : nico : put this in an external file, this way it isn't included by the background downloader
160 #ifndef RY_BG_DOWNLOADER
162 bool CStartupHttpClient::connectToLogin()
164 bool checkConnect = connect(ClientCfg.ConfigFile.getVar("StartupHost").asString(0));
166 if (ClientCfg.ConfigFile.exists("StartupVerify"))
167 checkConnect = checkConnect && verifyServer(ClientCfg.ConfigFile.getVar("StartupVerify").asBool(0));
169 return checkConnect;
172 CStartupHttpClient HttpClient;
173 #endif // RY_BG_DOWNLOADER
176 // ***************************************************************************
177 #define WIN_COMBO_BOX_SELECT_MENU "ui:interface:combo_box_select_menu"
178 #define WIN_COMBO_BOX_MEASURE_MENU "ui:interface:combo_box_measure_menu"
179 #define WIN_COMBO_BOX_SELECT_MENU_OUTGAME "ui:outgame:combo_box_select_menu"
180 #define WIN_COMBO_BOX_SELECT_MENU_LOGIN "ui:login:combo_box_select_menu"
181 #define WIN_COMBO_BOX_MEASURE_MENU_LOGIN "ui:login:combo_box_measure_menu"
183 bool isLoginFinished()
185 return loginFinished;
188 void setLoginFinished( bool f )
190 loginFinished = f;
191 if( loginFinished )
193 CDBGroupComboBox::measureMenu.assign( WIN_COMBO_BOX_MEASURE_MENU );
194 CDBGroupComboBox::selectMenu.assign( WIN_COMBO_BOX_SELECT_MENU );
196 else
198 CDBGroupComboBox::measureMenu.assign( WIN_COMBO_BOX_MEASURE_MENU_LOGIN );
199 CDBGroupComboBox::selectMenu.assign( WIN_COMBO_BOX_SELECT_MENU_LOGIN );
204 // ***************************************************************************
205 // Pop a fatal error message box, giving the option to 'quit' the client, plus a help button
206 static void fatalMessageBox(const std::string &msg)
208 CInterfaceManager *im = CInterfaceManager::getInstance();
209 im->messageBoxWithHelp(msg, "ui:login", "login_quit");
212 // ***************************************************************************
213 // Pop an error message box, giving the option to go back to main menu, plus a help button
214 static void errorMessageBox(const std::string &msg)
216 CInterfaceManager *im = CInterfaceManager::getInstance();
217 im->messageBoxWithHelp(msg, "ui:login", "on_back_to_login");
220 // ***************************************************************************
221 void createOptionalCatUI()
223 CInterfaceManager *pIM = CInterfaceManager::getInstance();
224 CInterfaceGroup *pList = dynamic_cast<CInterfaceGroup*>(CWidgetManager::getInstance()->getElementFromId(GROUP_LIST_CAT));
225 if (pList == NULL)
227 nlwarning("element " GROUP_LIST_CAT " not found probably bad login_main.xml");
228 return;
231 // Update optional categories
233 CInterfaceGroup *pPrevLine = NULL;
234 for(uint i = 0; i < InfoOnPatch.OptCat.size(); i++)
236 vector< pair < string, string > > params;
237 params.clear();
238 params.push_back(pair<string,string>("id", "c"+toString(i)));
239 if (i>0)
240 params.push_back(pair<string,string>("posref", "BL TL"));
242 CInterfaceGroup *pNewLine = CWidgetManager::getInstance()->getParser()->createGroupInstance("t_cat", GROUP_LIST_CAT, params);
243 if (pNewLine != NULL)
245 CViewText *pVT = dynamic_cast<CViewText*>(pNewLine->getView("name"));
246 if (pVT != NULL) pVT->setText(InfoOnPatch.OptCat[i].Name);
247 pVT = dynamic_cast<CViewText*>(pNewLine->getView("size"));
248 if (pVT != NULL)
250 pVT->setText(BGDownloader::getWrittenSize(InfoOnPatch.OptCat[i].Size));
253 // Add to the list
254 pNewLine->setParent(pList);
255 pNewLine->setParentSize(pList);
256 pNewLine->setParentPos(pPrevLine);
257 pList->addGroup(pNewLine);
259 pPrevLine = pNewLine;
262 pList->invalidateCoords();
265 // ***************************************************************************
266 void initEula()
268 CInterfaceManager *pIM = CInterfaceManager::getInstance();
269 if (!ClientCfg.SkipEULA && CFile::fileExists(getLogDirectory() + "show_eula"))
271 NLGUI::CDBManager::getInstance()->getDbProp("UI:VARIABLES:SCREEN")->setValue32(UI_VARIABLES_SCREEN_EULA);
273 // if we display the eula, it means we make a patch so we clean the cache directory
274 // (clear cache after each patch)
275 nlinfo("Deleting cached files");
276 vector<string> cached;
277 CPath::getPathContent("cache", true, false, true, cached);
278 for(uint i = 0; i < cached.size(); i++)
279 CFile::deleteFile(cached[i]);
281 else
283 CAHManager::getInstance()->runActionHandler("accept_eula", NULL);
287 // ***************************************************************************
288 static void setDataScanLog(const std::string &text)
290 CInterfaceManager *pIM= CInterfaceManager::getInstance();
291 CViewText *pVT = dynamic_cast<CViewText*>(CWidgetManager::getInstance()->getElementFromId("ui:login:datascan:content:log_txt:log"));
292 if (pVT != NULL)
294 pVT->setText(text);
298 // ***************************************************************************
299 static void setDataScanState(const std::string &text, const std::string &progress = string())
301 CInterfaceManager *pIM= CInterfaceManager::getInstance();
302 CViewText *pVT = dynamic_cast<CViewText*>(CWidgetManager::getInstance()->getElementFromId("ui:login:datascan:content:state"));
303 if (pVT != NULL) pVT->setText(text);
305 pVT = dynamic_cast<CViewText*>(CWidgetManager::getInstance()->getElementFromId("ui:login:datascan:content:progress"));
306 if (pVT != NULL) pVT->setText(progress);
309 void initCatDisplay()
311 CInterfaceManager *pIM = CInterfaceManager::getInstance();
312 CPatchManager *pPM = CPatchManager::getInstance();
314 // Check is good now ask the player if he wants to apply the patch
315 pPM->getInfoToDisp(InfoOnPatch);
317 if ((!InfoOnPatch.NonOptCat.empty()) ||
318 (!InfoOnPatch.OptCat.empty()) ||
319 (!InfoOnPatch.ReqCat.empty()))
321 createOptionalCatUI();
322 NLGUI::CDBManager::getInstance()->getDbProp("UI:VARIABLES:SCREEN")->setValue32(UI_VARIABLES_SCREEN_CATDISP);
324 else
326 LoginSM.pushEvent(CLoginStateMachine::ev_run_patch);
327 // CAHManager::getInstance()->runActionHandler("login_patch", NULL);
331 void initReboot()
333 CInterfaceManager *pIM = CInterfaceManager::getInstance();
334 NLGUI::CDBManager::getInstance()->getDbProp("UI:VARIABLES:SCREEN")->setValue32(UI_VARIABLES_SCREEN_REBOOT);
338 // ***************************************************************************
339 static void setPatcherStateText(const std::string &baseUIPath, const std::string &str)
341 CInterfaceManager *pIM = CInterfaceManager::getInstance();
342 CViewText *pVT = dynamic_cast<CViewText*>(CWidgetManager::getInstance()->getElementFromId(baseUIPath + ":content:state"));
343 if (pVT != NULL)
345 pVT->setText(str);
349 // ***************************************************************************
350 static void setPatcherProgressText(const std::string &baseUIPath, const std::string &str)
352 CInterfaceManager *pIM = CInterfaceManager::getInstance();
353 CViewText *pVT = dynamic_cast<CViewText*>(CWidgetManager::getInstance()->getElementFromId(baseUIPath + ":content:progress"));
354 if (pVT != NULL)
356 pVT->setText(str);
360 // ***************************************************************************
361 static void updatePatchingInfoText(const std::string &baseUIPath)
363 CPatchManager *pPM = CPatchManager::getInstance();
364 #ifdef RYZOM_BG_DOWNLOADER
365 CBGDownloaderAccess &bgDownloader = CBGDownloaderAccess::getInstance();
366 if (isBGDownloadEnabled())
368 bgDownloader.update();
369 if (bgDownloader.getDownloadThreadPriority() == BGDownloader::ThreadPriority_Paused)
371 setPatcherStateText(baseUIPath, CI18N::get("uiBGD_Paused"));
372 setPatcherProgressText(baseUIPath, string());
374 else
376 setPatcherStateText(baseUIPath, bgDownloader.getCurrentMessage());
377 if (bgDownloader.getTotalFilesToGet() != 0)
379 setPatcherProgressText(baseUIPath, toString("%d/%d", (int) bgDownloader.getCurrentFilesToGet(), (int) bgDownloader.getTotalFilesToGet()));
381 else
383 setPatcherProgressText(baseUIPath, string());
387 else
388 #endif
390 string state;
391 vector<string> log;
392 if(pPM->getThreadState(state, log))
394 setPatcherStateText(baseUIPath, state);
395 if (pPM->getTotalFilesToGet() != 0)
397 setPatcherProgressText(baseUIPath, toString("%d/%d", pPM->getCurrentFilesToGet(), pPM->getTotalFilesToGet()));
399 else
401 setPatcherProgressText(baseUIPath, string());
407 // ***************************************************************************
408 // Main loop of the login step
409 void loginMainLoop()
411 CDBGroupComboBox::selectMenuOut.assign( WIN_COMBO_BOX_SELECT_MENU_OUTGAME );
412 CInterfaceManager *pIM = CInterfaceManager::getInstance();
413 CPatchManager *pPM = CPatchManager::getInstance();
415 #ifdef RYZOM_BG_DOWNLOADER
416 CBGDownloaderAccess &bgDownloader = CBGDownloaderAccess::getInstance();
417 #endif
419 bool windowBlinkDone = false;
420 bool fatalMessageBoxShown = false;
422 while (LoginSM.getCurrentState() != CLoginStateMachine::st_connect
423 && LoginSM.getCurrentState() != CLoginStateMachine::st_end
424 && LoginSM.getCurrentState() != CLoginStateMachine::st_ingame)
425 // while (loginFinished == false)
427 IngameDbMngr.flushObserverCalls();
428 NLGUI::CDBManager::getInstance()->flushObserverCalls();
430 // Update the DT T0 and T1 global variables
431 updateClientTime();
435 CInputHandlerManager::getInstance()->pumpEvents();
436 Driver->clearBuffers(CRGBA::Black);
437 Driver->setMatrixMode2D11();
439 // Update sound
440 if (SoundMngr != NULL)
441 SoundMngr->update();
443 // Interface handling & displaying
444 pIM->updateFrameEvents();
445 pIM->updateFrameViews(NULL);
446 IngameDbMngr.flushObserverCalls();
447 NLGUI::CDBManager::getInstance()->flushObserverCalls();
451 // if (::GetAsyncKeyState(VK_SPACE))
452 // {
453 // pIM->displayUIViewBBoxs("");
454 // pIM->displayUICtrlBBoxs("");
455 // pIM->displayUIGroupBBoxs("");
456 // }
458 // Force the client to sleep a bit.
459 if(ClientCfg.Sleep >= 0)
461 nlSleep(ClientCfg.Sleep);
463 // Display
464 Driver->swapBuffers();
466 // sint32 screen = NLGUI::CDBManager::getInstance()->getDbProp("UI:VARIABLES:SCREEN")->getValue32();
467 if (LoginSM.getCurrentState() == CLoginStateMachine::st_check_patch)
468 // if (screen == UI_VARIABLES_SCREEN_CHECKING) // If we are in checking mode
470 nlSleep(10); // For the checking thread
471 bool res = false;
472 BGDownloader::TTaskResult taskResult = BGDownloader::TaskResult_Unknown;
473 bool finished = false;
474 #ifdef RYZOM_BG_DOWNLOADER
475 string bgDownloaderError;
476 if (isBGDownloadEnabled())
478 finished = bgDownloader.isTaskEnded(taskResult, bgDownloaderError);
480 else
481 #endif
483 finished = pPM->isCheckThreadEnded(res);
486 if (finished)
488 setPatcherStateText("ui:login:checking", string());
489 setPatcherProgressText("ui:login:checking", string());
491 #ifdef RYZOM_BG_DOWNLOADER
492 if (isBGDownloadEnabled())
494 AvailablePatchs = bgDownloader.getAvailablePatchs();
495 #ifdef NL_OS_WINDOWS
497 // Get the window
498 HWND hWnd = Driver->getDisplay();
499 nlassert (hWnd);
500 // Show the window, unless it has been minimized, in
501 // which case we don't pop it unexpectedly
502 if (!windowBlinkDone)
504 bgDownloader.hideDownloader();
505 ShowWindow (hWnd, SW_RESTORE);
506 windowBlinkDone = true;
510 #endif
511 switch(taskResult)
513 case BGDownloader::TaskResult_Success:
514 if (AvailablePatchs & (1 << BGDownloaderWantedPatch)) // is there a patch for what we want now ?
516 LoginSM.pushEvent(CLoginStateMachine::ev_patch_needed);
518 else
520 LoginSM.pushEvent(CLoginStateMachine::ev_no_patch);
522 break;
523 case BGDownloader::TaskResult_Error:
525 if (!fatalMessageBoxShown)
527 fatalMessageBox(bgDownloaderError);
528 fatalMessageBoxShown = true;
531 break;
532 default:
533 if (!fatalMessageBoxShown)
535 fatalMessageBox(CI18N::get("uiErrChecking"));
536 fatalMessageBoxShown = true;
538 break;
542 else
543 #endif
545 if(res)
547 // Check is good now ask the player if he wants to apply the patch
548 pPM->getInfoToDisp(InfoOnPatch);
550 AvailablePatchs = InfoOnPatch.getAvailablePatchsBitfield();
552 if ((!InfoOnPatch.NonOptCat.empty()) ||
553 (!InfoOnPatch.OptCat.empty()) ||
554 (!InfoOnPatch.ReqCat.empty()))
556 LoginSM.pushEvent(CLoginStateMachine::ev_patch_needed);
557 // createOptionalCatUI();
558 // NLGUI::CDBManager::getInstance()->getDbProp("UI:VARIABLES:SCREEN")->setValue32(UI_VARIABLES_SCREEN_CATDISP);
560 else
562 LoginSM.pushEvent(CLoginStateMachine::ev_no_patch);
563 // CAHManager::getInstance()->runActionHandler("login_patch", NULL);
566 else
568 string errMsg = CI18N::get("uiErrChecking");
569 if (!pPM->getLastErrorMessage().empty())
571 errMsg = pPM->getLastErrorMessage();
573 if (!fatalMessageBoxShown)
575 fatalMessageBox(errMsg);
576 fatalMessageBoxShown = true;
581 else
583 // update interface content
584 updatePatchingInfoText("ui:login:checking");
587 // else if (screen == UI_VARIABLES_SCREEN_DATASCAN) // If we are in ScanData mode
588 else if (LoginSM.getCurrentState() == CLoginStateMachine::st_scan_data)
590 nlSleep(10); // For the checking thread
592 bool res;
593 if (pPM->isScanDataThreadEnded(res))
595 // if interface consider it was running before
596 if(NLGUI::CDBManager::getInstance()->getDbProp("UI:VARIABLES:DATASCAN_RUNNING")->getValue32()!=0)
598 // no more running
599 NLGUI::CDBManager::getInstance()->getDbProp("UI:VARIABLES:DATASCAN_RUNNING")->setValue32(0);
601 if(res)
603 // touch any file with checksum error, and get their number
604 uint numFiles= pPM->applyScanDataResult();
606 // Report result
607 if(numFiles==0)
608 setDataScanState(CI18N::get("uiScanDataSucess"));
609 else
611 string fmt= CI18N::get("uiScanDataErrors");
612 strFindReplace(fmt, "%d", toString(numFiles));
613 setDataScanState(fmt);
616 else
618 string errMsg = CI18N::get("uiErrDataScanning");
619 if (!pPM->getLastErrorMessage().empty())
621 errMsg = pPM->getLastErrorMessage();
623 pIM->messageBoxWithHelp(errMsg, "ui:login");
626 // the log may have changed
627 string dsLog;
628 if(pPM->getDataScanLog(dsLog))
629 setDataScanLog(dsLog);
632 else
634 // update inteface content
635 string state;
636 vector<string> log;
637 // get state
638 if(pPM->getThreadState(state, log))
640 // set state
641 setDataScanState(state, toString("%d/%d", pPM->getCurrentFilesToGet(), pPM->getTotalFilesToGet()));
643 // set special data scan log
644 string dsLog;
645 if(pPM->getDataScanLog(dsLog))
646 setDataScanLog(dsLog);
649 // else if (screen == UI_VARIABLES_SCREEN_PATCHING) // If we are in patching mode
650 else if (LoginSM.getCurrentState() == CLoginStateMachine::st_patch)
652 nlSleep(30); // For the patching thread
654 int currentPatchingSize;
655 int totalPatchSize;
657 #ifdef RYZOM_BG_DOWNLOADER
658 if (isBGDownloadEnabled())
660 currentPatchingSize = bgDownloader.getPatchingSize();
661 totalPatchSize = bgDownloader.getTotalSize();
662 BGDownloader::TTaskResult taskResult;
663 bool finished = false;
664 string bgDownloaderError;
665 finished = bgDownloader.isTaskEnded(taskResult, bgDownloaderError);
666 if (finished)
668 //bgDownloader.hideDownloader();
669 // restore the search paths (all bnp files were removed from CPath to allows
670 // the patcher to overwrite them)
672 // create a file to prompt eula next time
673 CFile::createEmptyFile(getLogDirectory() + "show_eula");
675 if (taskResult == BGDownloader::TaskResult_Error)
677 setPatcherStateText("ui:login:patching", string());
678 setPatcherProgressText("ui:login:patching", string());
680 if (!fatalMessageBoxShown)
682 fatalMessageBox(bgDownloaderError);
683 fatalMessageBoxShown = true;
686 else
688 bgDownloader.getPatchCompletionFlag(true /* clear flag */);
689 LoginSM.pushEvent(CLoginStateMachine::ev_close_patch);
692 else
694 updatePatchingInfoText("ui:login:patching");
697 else
698 #endif
700 totalPatchSize = TotalPatchSize;
701 currentPatchingSize = pPM->getPatchingSize();
702 bool res;
703 if (pPM->isPatchThreadEnded(res))
705 if(res)
707 LoginSM.pushEvent(CLoginStateMachine::ev_close_patch);
709 else
711 string errMsg = CI18N::get("uiErrPatchApply");
712 if (!pPM->getLastErrorMessage().empty())
714 errMsg = pPM->getLastErrorMessage();
716 if (!fatalMessageBoxShown)
718 fatalMessageBox(errMsg);
719 fatalMessageBoxShown = true;
723 else
725 updatePatchingInfoText("ui:login:patching");
729 CViewText *pVT = dynamic_cast<CViewText*>(CWidgetManager::getInstance()->getElementFromId(VIEW_TOTAL_SIZE_PATCH));
730 string sTmp;
731 sTmp = BGDownloader::getWrittenSize(currentPatchingSize);
732 sTmp += " / " + BGDownloader::getWrittenSize(totalPatchSize);
733 if (pVT != NULL) pVT->setText(sTmp);
735 // else if (screen == UI_VARIABLES_SCREEN_CATDISP) // If we are displaying patch info
736 else if (LoginSM.getCurrentState() == CLoginStateMachine::st_display_cat)
738 // Non optional stuff (non opt cat and req cat)
740 // Add req cat size : given the optional cat we determines the required cat
741 uint32 nNonOptSize = 0;
742 TotalPatchSize = 0;
743 vector<sint32> ReqCat;
744 CInterfaceGroup *pList = dynamic_cast<CInterfaceGroup*>(CWidgetManager::getInstance()->getElementFromId(GROUP_LIST_CAT));
745 if (pList != NULL)
747 for(uint i = 0; i < InfoOnPatch.OptCat.size(); i++)
749 CInterfaceGroup *pLine = pList->getGroup("c"+toString(i));
750 if (pLine != NULL)
752 CCtrlButton *pCB = dynamic_cast<CCtrlButton*>(pLine->getCtrl("on_off"));
753 if ((pCB != NULL) && (pCB->getPushed()))
755 TotalPatchSize += InfoOnPatch.OptCat[i].Size;
756 if (InfoOnPatch.OptCat[i].Req != -1)
758 uint32 j;
759 for (j = 0; j < ReqCat.size(); ++j)
760 if (ReqCat[j] == InfoOnPatch.OptCat[i].Req)
761 break;
762 // Add just once the req cat size to the non optional size
763 if (j == ReqCat.size())
765 ReqCat.push_back(InfoOnPatch.OptCat[i].Req);
766 nNonOptSize += InfoOnPatch.ReqCat[InfoOnPatch.OptCat[i].Req].Size;
774 // Add non optional cats
775 for (uint32 i = 0; i < InfoOnPatch.NonOptCat.size(); ++i)
776 nNonOptSize += InfoOnPatch.NonOptCat[i].Size;
778 TotalPatchSize += nNonOptSize;
779 // Total size of the patches is optional cats + required cat (f(optCat)) + non opt cat
781 CViewText *pVT = dynamic_cast<CViewText*>(CWidgetManager::getInstance()->getElementFromId(VIEW_TOTAL_SIZE));
782 if (pVT != NULL) pVT->setText(BGDownloader::getWrittenSize(TotalPatchSize));
784 pVT = dynamic_cast<CViewText*>(CWidgetManager::getInstance()->getElementFromId(VIEW_NON_OPTIONAL_SIZE));
785 if (pVT != NULL) pVT->setText(BGDownloader::getWrittenSize(nNonOptSize));
790 void initLoginScreen()
792 CInterfaceManager *pIM = CInterfaceManager::getInstance();
793 CPatchManager *pPM = CPatchManager::getInstance();
794 NLGUI::CDBManager::getInstance()->getDbProp("UI:VARIABLES:SCREEN")->setValue32(UI_VARIABLES_SCREEN_CHECKPASS);
795 NLGUI::CDBManager::getInstance()->getDbProp("UI:VARIABLES:DISPLAY_ACCOUNT_BUTTONS")->setValue32(ClientCfg.DisplayAccountButtons);
797 // Active inputs
798 Actions.enable(true);
799 EditActions.enable(true);
801 if(ClientCfg.ConfigFile.exists("VerboseLog"))
802 pPM->setVerboseLog(ClientCfg.ConfigFile.getVar("VerboseLog").asInt() == 1);
803 if(pPM->isVerboseLog()) nlinfo("Using verbose log mode");
805 ClientApp = ClientCfg.ConfigFile.getVar("Application").asString(0);
807 // version
808 std::string ext;
809 if (ClientApp.find("ryzom_") != string::npos)
810 ext = " (" + ClientApp.substr(6) + ")";
812 CViewText *pV = dynamic_cast<CViewText*>(CWidgetManager::getInstance()->getElementFromId("ui:login:checkpass:content:ver_value"));
813 if (pV)
814 pV->setHardText(getDisplayVersion() + (ext.empty() ? "" : ext));
816 // give priority to login specified as argument
817 string l = !LoginLogin.empty() ? LoginLogin:ClientCfg.LastLogin;
819 if(!l.empty())
821 CGroupEditBox *pGEB = dynamic_cast<CGroupEditBox*>(CWidgetManager::getInstance()->getElementFromId(CTRL_EDITBOX_LOGIN));
822 if (pGEB != NULL && (pGEB->getInputString().empty()))
824 pGEB->setInputString(l);
826 CAHManager::getInstance()->runActionHandler("set_keyboard_focus", NULL, "target=" CTRL_EDITBOX_PASSWORD "|select_all=false");
828 else
830 CAHManager::getInstance()->runActionHandler("set_keyboard_focus", NULL, "target=" CTRL_EDITBOX_LOGIN "|select_all=false");
834 CCtrlTextButton *pCB = dynamic_cast<CCtrlTextButton*>(CWidgetManager::getInstance()->getElementFromId(CTRL_BUTTON_CONNECT));
835 if (pCB != NULL) pCB->setActive(false);
837 setLoginFinished( false );
838 loginOK = false;
841 void initAutoLogin()
843 CInterfaceManager *pIM = CInterfaceManager::getInstance();
844 CGroupEditBox *pGEBLog = dynamic_cast<CGroupEditBox*>(CWidgetManager::getInstance()->getElementFromId(CTRL_EDITBOX_LOGIN));
845 CGroupEditBox *pGEBPwd = dynamic_cast<CGroupEditBox*>(CWidgetManager::getInstance()->getElementFromId(CTRL_EDITBOX_PASSWORD));
846 pGEBLog->setInputString(LoginLogin);
847 pGEBPwd->setInputString(LoginPassword);
848 CAHManager::getInstance()->runActionHandler("on_login", NULL, "");
850 /* if (ClientCfg.R2Mode)
852 LoginSM.pushEvent(CLoginStateMachine::ev_login_ok);
854 else
856 // Select good shard
857 ShardSelected = -1;
858 for (uint32 i = 0; i < Shards.size(); ++i)
860 if (Shards[i].ShardId == LoginShardId)
862 ShardSelected = i;
863 break;
867 if (ShardSelected == -1)
869 pIM->messageBoxWithHelp(CI18N::get("uiErrServerLost"), "ui:login");
870 LoginSM.pushEvent(CLoginStateMachine::ev_quit);
872 else
875 LoginSM.pushEvent(CLoginStateMachine::ev_login_ok);
876 // CAHManager::getInstance()->runActionHandler("login_connect_2", NULL);
879 * */
882 void initAltLogin()
884 // Check the alt param
885 if (!LoginCustomParameters.empty() && LoginCustomParameters != "&dbg=1")
887 // don't use login and password for alternate login
888 string res = checkLogin("", "", ClientApp, LoginCustomParameters);
889 if (res.empty())
891 if (ClientCfg.R2Mode)
893 LoginSM.pushEvent(CLoginStateMachine::ev_login_ok);
895 else
897 // Select good shard
898 ShardSelected = -1;
899 for (uint32 i = 0; i < Shards.size(); ++i)
901 if (Shards[i].ShardId == LoginShardId)
903 ShardSelected = i;
904 break;
908 if (ShardSelected == -1)
910 CInterfaceManager *pIM = CInterfaceManager::getInstance();
911 pIM->messageBoxWithHelp(CI18N::get("uiErrServerLost"), "ui:login");
912 LoginSM.pushEvent(CLoginStateMachine::ev_quit);
914 else
916 LoginSM.pushEvent(CLoginStateMachine::ev_login_ok);
920 return;
924 // close the socket in case of error
925 HttpClient.disconnect();
927 // ignore error
928 LoginSM.pushEvent(CLoginStateMachine::ev_login_not_alt);
932 // ***************************************************************************
933 // Called from client.cpp
934 bool login()
936 CLoginProgressPostThread::getInstance().step(CLoginStep(LoginStep_LoginScreen, "login_step_login_screen"));
938 CInterfaceManager *pIM = CInterfaceManager::getInstance();
939 CPatchManager *pPM = CPatchManager::getInstance();
941 if (LoginLogin.empty())
942 loginIntro();
944 pIM->initLogin();
945 IngameDbMngr.flushObserverCalls();
946 NLGUI::CDBManager::getInstance()->flushObserverCalls();
948 SetMousePosFirstTime = true;
949 InitMouseWithCursor(false);
950 Driver->showCursor (false);
951 SetMouseFreeLook ();
952 SetMouseCursor (false);
953 SetMouseSpeed (ClientCfg.CursorSpeed);
954 SetMouseAcceleration (ClientCfg.CursorAcceleration);
955 SetMousePosFirstTime = true;
956 InitMouseWithCursor (ClientCfg.HardwareCursor && !StereoDisplayAttached);
958 // if (ClientCfg.TestBrowser)
959 // {
960 // NLGUI::CDBManager::getInstance()->getDbProp("UI:VARIABLES:SCREEN")->setValue32(UI_VARIABLES_SCREEN_WEBSTART);
962 // // hide 'back to login' button
963 // CInterfaceElement *backToLogin = CWidgetManager::getInstance()->getElementFromId(CTRL_BUTTON_BACKTOLOGIN);
964 // if (backToLogin)
965 // backToLogin->setActive(false);
967 // // show 'reload test page' button
968 // CInterfaceElement *reloadTest = CWidgetManager::getInstance()->getElementFromId(CTRL_BUTTON_RELOADTESTPAGE);
969 // if (reloadTest)
970 // reloadTest->setActive(true);
972 // // start the browser
973 // CGroupHTML *pGH = dynamic_cast<CGroupHTML*>(CWidgetManager::getInstance()->getElementFromId(GROUP_BROWSER));
975 // pGH->browse(ClientCfg.TestBrowserUrl.c_str());
977 // }
978 // else
979 // {
980 //// NLGUI::CDBManager::getInstance()->getDbProp("UI:VARIABLES:SCREEN")->setValue32(UI_VARIABLES_SCREEN_CHECKPASS);
981 //// NLGUI::CDBManager::getInstance()->getDbProp("UI:VARIABLES:DISPLAY_ACCOUNT_BUTTONS")->setValue32(ClientCfg.DisplayAccountButtons);
982 // }
984 // Active inputs
985 Actions.enable(true);
986 EditActions.enable(true);
988 if(ClientCfg.ConfigFile.exists("VerboseLog"))
989 pPM->setVerboseLog(ClientCfg.ConfigFile.getVar("VerboseLog").asInt() == 1);
990 if(pPM->isVerboseLog()) nlinfo("Using verbose log mode");
992 ClientApp = ClientCfg.ConfigFile.getVar("Application").asString(0);
994 // string l = getRegKeyValue("Login").c_str();
996 // if(!l.empty())
997 // {
998 // CGroupEditBox *pGEB = dynamic_cast<CGroupEditBox*>(CWidgetManager::getInstance()->getElementFromId(CTRL_EDITBOX_LOGIN));
999 // if (pGEB != NULL)
1000 // pGEB->setInputString(l);
1001 // CAHManager::getInstance()->runActionHandler("set_keyboard_focus", NULL, "target=" CTRL_EDITBOX_PASSWORD "|select_all=false");
1002 // }
1003 // else
1004 // {
1005 // CAHManager::getInstance()->runActionHandler("set_keyboard_focus", NULL, "target=" CTRL_EDITBOX_LOGIN "|select_all=false");
1006 // }
1008 ShardSelected = -1;
1009 // CCtrlTextButton *pCB = dynamic_cast<CCtrlTextButton*>(CWidgetManager::getInstance()->getElementFromId(CTRL_BUTTON_CONNECT));
1010 // if (pCB != NULL) pCB->setActive(false);
1012 // setLoginFinished( false );
1013 // loginFinished = false;
1014 // loginOK = false;
1016 // Comes from a current patch
1017 // if (!LoginLogin.empty())
1018 // {
1019 // CInterfaceManager *pIM = CInterfaceManager::getInstance();
1020 // CGroupEditBox *pGEBLog = dynamic_cast<CGroupEditBox*>(CWidgetManager::getInstance()->getElementFromId(CTRL_EDITBOX_LOGIN));
1021 // CGroupEditBox *pGEBPwd = dynamic_cast<CGroupEditBox*>(CWidgetManager::getInstance()->getElementFromId(CTRL_EDITBOX_PASSWORD));
1022 // pGEBLog->setInputString(LoginLogin);
1023 // pGEBPwd->setInputString(LoginPassword);
1024 // CAHManager::getInstance()->runActionHandler("on_login", NULL, "");
1025 // // Select good shard
1026 // ShardSelected = -1;
1027 // for (uint32 i = 0; i < Shards.size(); ++i)
1028 // {
1029 // if (Shards[i].ShardId == LoginShardId)
1030 // {
1031 // ShardSelected = i;
1032 // break;
1033 // }
1034 // }
1036 // if (ShardSelected == -1)
1037 // pIM->messageBox(CI18N::get("uiErrServerLost"), "ui:login");
1038 // else
1039 // CAHManager::getInstance()->runActionHandler("login_connect_2", NULL);
1040 // }
1042 // start the login state machine
1043 LoginSM.pushEvent(CLoginStateMachine::ev_init_done);
1045 // run the main loop
1046 loginMainLoop();
1048 // Uninit all
1049 pIM->uninitLogin();
1051 // Disable inputs
1052 Actions.enable(false);
1053 EditActions.enable(false);
1055 return loginOK;
1058 // ***************************************************************************
1059 // INTERFACE HELPERS
1060 // ***************************************************************************
1062 // ***************************************************************************
1063 void removeSpace(string &s)
1065 uint i = 0;
1066 while (!s.empty())
1068 if (s[i] == ' ')
1069 s.erase(i, 1);
1070 else
1071 i++;
1072 if (i >= s.size()) break;
1076 // ***************************************************************************
1077 static void getPatchParameters(std::string &url, std::string &ver, std::vector<std::string> &patchURIs)
1079 if (ClientCfg.R2Mode)
1081 url = ClientCfg.PatchUrl;
1082 ver = ClientCfg.PatchVersion;
1084 // if PatchUrl is forced, don't use URLs returned by server
1085 if (url.empty())
1087 patchURIs = R2PatchURLs;
1088 url = R2BackupPatchURL;
1089 ver = R2ServerVersion;
1092 else
1094 nlassert(ShardSelected != -1);
1095 patchURIs = Shards[ShardSelected].PatchURIs;
1096 url = Shards[ShardSelected].EmergencyPatchURL;
1097 ver = Shards[ShardSelected].Version;
1099 if (!ClientCfg.PatchUrl.empty())
1100 url = ClientCfg.PatchUrl;
1102 if (!ClientCfg.PatchVersion.empty())
1103 ver = ClientCfg.PatchVersion;
1107 // ***************************************************************************
1108 std::string getBGDownloaderCommandLine()
1110 #ifdef NL_DEBUG
1111 CConfigFile::CVar *bgdCommandLine = ClientCfg.ConfigFile.getVarPtr("BackgroundDownloaderCommandLine");
1112 if (bgdCommandLine != NULL && !bgdCommandLine->asString().empty())
1114 return bgdCommandLine->asString();
1116 #endif
1117 string url;
1118 string ver;
1119 std::vector<std::string> patchURIs;
1120 getPatchParameters(url, ver, patchURIs);
1121 std::string commandLine = /*R2ServerVersion + " " + VersionName + " " + */ url + " " + ver;
1122 for (uint i = 0; i < patchURIs.size(); ++i)
1124 commandLine += " " + patchURIs[i];
1126 return commandLine;
1129 // ***************************************************************************
1130 void initPatchCheck()
1132 // start the patching system
1133 CInterfaceManager *pIM = CInterfaceManager::getInstance();
1134 CPatchManager *pPM = CPatchManager::getInstance();
1136 string url;
1137 string ver;
1138 std::vector<std::string> patchURIs;
1140 if (!ClientCfg.R2Mode)
1142 // nb Nico : refactored this code.
1143 // In previous code, the following was not set in R2Mode, possible bug ?...let as before anyway ...
1144 // store the selected shard for restarting after patch
1145 LoginShardId = Shards[ShardSelected].ShardId;
1148 #ifdef RYZOM_BG_DOWNLOADER
1149 if (!isBGDownloadEnabled())
1150 #endif
1152 getPatchParameters(url, ver, patchURIs);
1153 pPM->init(patchURIs, url, ver);
1154 pPM->startCheckThread(true /* include background patchs */);
1156 #ifdef RYZOM_BG_DOWNLOADER
1157 else
1159 BGDownloader::CTaskDesc taskDesc(BGDownloader::DLState_CheckPatch);
1160 CBGDownloaderAccess::getInstance().requestDownloadThreadPriority(BGDownloader::ThreadPriority_Normal, false);
1161 CBGDownloaderAccess::getInstance().startTask(taskDesc, getBGDownloaderCommandLine(), true /* showDownloader */);
1163 #endif
1164 NLGUI::CDBManager::getInstance()->getDbProp("UI:VARIABLES:SCREEN")->setValue32(UI_VARIABLES_SCREEN_CHECKING);
1166 setPatcherStateText("ui:login:checking", string());
1167 setPatcherProgressText("ui:login:checking", string());
1170 void initShardDisplay()
1172 CInterfaceManager *pIM = CInterfaceManager::getInstance();
1173 NLGUI::CDBManager::getInstance()->getDbProp("UI:VARIABLES:SCREEN")->setValue32(UI_VARIABLES_SCREEN_SHARDDISP);
1175 CInterfaceGroup *pList = dynamic_cast<CInterfaceGroup*>(CWidgetManager::getInstance()->getElementFromId(GROUP_LIST_SHARD));
1176 if (pList == NULL)
1178 nlwarning("element " GROUP_LIST_SHARD " not found probably bad login_main.xml");
1179 return;
1181 /* // To test more servers
1182 for (uint fff = 0; fff < 20; ++fff)
1184 CShard s ( toString("%05d",fff), fff%3, fff+32, toString("%s%d","pipo",fff),
1185 32*fff%46546, "32.32.32.32", "http://www.ryzom.com" );
1186 Shards.push_back(s);
1189 CInterfaceGroup *pPrevLine = NULL;
1190 for(uint i = 0; i < Shards.size(); i++)
1192 vector< pair < string, string > > params;
1193 params.clear();
1194 params.push_back(pair<string,string>("id", "s"+toString(i)));
1195 if (i>0)
1196 params.push_back(pair<string,string>("posref", "BL TL"));
1198 CInterfaceGroup *pNewLine = CWidgetManager::getInstance()->getParser()->createGroupInstance("t_shard", GROUP_LIST_SHARD, params);
1199 if (pNewLine != NULL)
1201 CViewText *pVT = dynamic_cast<CViewText*>(pNewLine->getView("name"));
1202 if (pVT != NULL) pVT->setText(Shards[i].Name);
1204 pVT = dynamic_cast<CViewText*>(pNewLine->getView("version"));
1205 if (pVT != NULL) pVT->setText(Shards[i].Version);
1207 CViewBase *pVBon = pNewLine->getView("online");
1208 CViewBase *pVBoff = pNewLine->getView("offline");
1209 if ((pVBon != NULL) && (pVBoff != NULL))
1211 pVBon->setActive (Shards[i].Online);
1212 pVBoff->setActive (!Shards[i].Online);
1215 pVT = dynamic_cast<CViewText*>(pNewLine->getView("nbplayer"));
1216 if (pVT != NULL) pVT->setText(toString(Shards[i].NbPlayers));
1219 // Add to the list
1220 pNewLine->setParent(pList);
1221 pNewLine->setParentSize(pList);
1222 pNewLine->setParentPos(pPrevLine);
1223 pList->addGroup(pNewLine);
1225 pPrevLine = pNewLine;
1228 // UI Patch
1229 if (!Shards.empty())
1231 CCtrlButton *pCB = dynamic_cast<CCtrlButton*>(CWidgetManager::getInstance()->getElementFromId(GROUP_LIST_SHARD ":s0:but"));
1232 if (pCB != NULL)
1234 pCB->setPushed(true);
1235 CAHManager::getInstance()->runActionHandler(pCB->getActionOnLeftClick(), pCB, pCB->getParamsOnLeftClick());
1238 pList->invalidateCoords();
1241 // ***************************************************************************
1243 void onlogin(bool vanishScreen = true)
1245 CInterfaceManager *pIM = CInterfaceManager::getInstance();
1247 // Remove space before and after each string login & password
1248 removeSpace(LoginLogin);
1249 removeSpace(LoginPassword);
1251 if(!LoginLogin.empty())
1253 ClientCfg.LastLogin = LoginLogin;
1254 ClientCfg.writeString("LastLogin", ClientCfg.LastLogin, true);
1257 if(vanishScreen)
1258 NLGUI::CDBManager::getInstance()->getDbProp("UI:VARIABLES:SCREEN")->setValue32(-1);
1260 // Check the login/pass
1262 // main menu page for r2mode
1263 string res = checkLogin(LoginLogin, LoginPassword, ClientApp, LoginCustomParameters);
1264 if (res.empty())
1266 LoginSM.pushEvent(CLoginStateMachine::ev_login_ok);
1268 else
1270 // close the socket in case of error
1271 HttpClient.disconnect();
1273 pIM->messageBoxWithHelp("Error : " + res, "ui:login");
1275 LoginSM.pushEvent(CLoginStateMachine::ev_bad_login);
1279 class CAHOnLogin : public IActionHandler
1281 virtual void execute (CCtrlBase * /* pCaller */, const string &/* Params */)
1283 //nlinfo("CAHOnLogin called");
1285 CInterfaceManager *pIM = CInterfaceManager::getInstance();
1287 CGroupEditBox *pGEBLog = dynamic_cast<CGroupEditBox*>(CWidgetManager::getInstance()->getElementFromId(CTRL_EDITBOX_LOGIN));
1288 CGroupEditBox *pGEBPwd = dynamic_cast<CGroupEditBox*>(CWidgetManager::getInstance()->getElementFromId(CTRL_EDITBOX_PASSWORD));
1289 if ((pGEBLog == NULL) || (pGEBPwd == NULL))
1291 nlwarning("element " CTRL_EDITBOX_LOGIN " or " CTRL_EDITBOX_PASSWORD " not found probably bad login_main.xml");
1292 return;
1295 LoginLogin = pGEBLog->getInputString();
1296 LoginPassword = pGEBPwd->getInputString();
1298 onlogin();
1301 REGISTER_ACTION_HANDLER (CAHOnLogin, "on_login");
1304 // ***************************************************************************
1305 class CAHOnGameConfiguration : public IActionHandler
1307 virtual void execute (CCtrlBase * /* pCaller */, const string &/* Params */)
1309 nlinfo("CAHOnGameConfiguration called");
1311 static string Configurator = "ryzom_configuration_rd.exe";
1313 if (CFile::fileExists (Configurator))
1315 // launch the ryzom configurator
1316 launchProgram(Configurator, "");
1317 setLoginFinished( true );
1318 loginOK = false;
1320 LoginSM.pushEvent(CLoginStateMachine::ev_quit);
1322 else
1324 nlwarning("<CAHOnGameConfiguration::execute> can't find ryzom configurator : %s",Configurator.c_str());
1328 REGISTER_ACTION_HANDLER (CAHOnGameConfiguration, "on_game_configuration");
1331 // ***************************************************************************
1332 class CAHLoginQuit : public IActionHandler
1334 virtual void execute (CCtrlBase * /* pCaller */, const string &/* Params */)
1336 nlinfo("CAHLoginQuit called");
1338 setLoginFinished( true );
1339 loginOK = false;
1341 LoginSM.pushEvent(CLoginStateMachine::ev_quit);
1344 REGISTER_ACTION_HANDLER (CAHLoginQuit, "login_quit");
1347 // ***************************************************************************
1348 class CAHLoginTab : public IActionHandler
1350 virtual void execute (CCtrlBase * /* pCaller */, const string &/* Params */)
1352 nlinfo("CAHLoginTab called");
1354 CInterfaceManager *pIM = CInterfaceManager::getInstance();
1356 if (NLGUI::CDBManager::getInstance()->getDbProp("UI:VARIABLES:SCREEN")->getValue32() == UI_VARIABLES_SCREEN_CHECKPASS)
1358 CCtrlBase *pCB = CWidgetManager::getInstance()->getCaptureKeyboard();
1359 if (pCB != NULL)
1361 CCtrlBase *pNewCB;
1362 string sID = pCB->getId();
1363 if (sID == CTRL_EDITBOX_LOGIN)
1364 pNewCB = dynamic_cast<CCtrlBase*>(CWidgetManager::getInstance()->getElementFromId(CTRL_EDITBOX_PASSWORD));
1365 else
1366 pNewCB = dynamic_cast<CCtrlBase*>(CWidgetManager::getInstance()->getElementFromId(CTRL_EDITBOX_LOGIN));
1367 CWidgetManager::getInstance()->setCaptureKeyboard(pNewCB);
1370 else if (NLGUI::CDBManager::getInstance()->getDbProp("UI:VARIABLES:SCREEN")->getValue32() == UI_VARIABLES_SCREEN_CREATE_ACCOUNT)
1372 CCtrlBase *pCB = CWidgetManager::getInstance()->getCaptureKeyboard();
1373 if (pCB != NULL)
1375 CCtrlBase *pNewCB;
1376 string sID = pCB->getId();
1377 if (sID == CTRL_EDITBOX_CREATEACCOUNT_LOGIN)
1378 pNewCB = dynamic_cast<CCtrlBase*>(CWidgetManager::getInstance()->getElementFromId(CTRL_EDITBOX_CREATEACCOUNT_PASSWORD));
1379 else if (sID == CTRL_EDITBOX_CREATEACCOUNT_PASSWORD)
1380 pNewCB = dynamic_cast<CCtrlBase*>(CWidgetManager::getInstance()->getElementFromId(CTRL_EDITBOX_CREATEACCOUNT_CONFIRMPASSWORD));
1381 else if (sID == CTRL_EDITBOX_CREATEACCOUNT_CONFIRMPASSWORD)
1382 pNewCB = dynamic_cast<CCtrlBase*>(CWidgetManager::getInstance()->getElementFromId(CTRL_EDITBOX_CREATEACCOUNT_EMAIL));
1383 else
1384 pNewCB = dynamic_cast<CCtrlBase*>(CWidgetManager::getInstance()->getElementFromId(CTRL_EDITBOX_CREATEACCOUNT_LOGIN));
1385 CWidgetManager::getInstance()->setCaptureKeyboard(pNewCB);
1390 REGISTER_ACTION_HANDLER (CAHLoginTab, "login_tab");
1393 // ***************************************************************************
1394 class CAHShardSelect : public IActionHandler
1396 virtual void execute (CCtrlBase *pCaller, const string &/* Params */)
1398 nlinfo("CAHShardSelect called");
1400 CInterfaceManager *pIM = CInterfaceManager::getInstance();
1402 CCtrlButton *pCB = NULL;
1403 // Unselect
1404 if (ShardSelected != -1)
1406 pCB = dynamic_cast<CCtrlButton*>(CWidgetManager::getInstance()->getElementFromId(GROUP_LIST_SHARD ":s"+toString(ShardSelected)+":but"));
1407 if (pCB != NULL)
1408 pCB->setPushed(false);
1411 pCB = dynamic_cast<CCtrlButton*>(pCaller);
1412 if (pCB != NULL)
1414 string name = pCB->getId();
1415 name = name.substr(0,name.rfind(':'));
1416 name = name.substr(name.rfind(':')+2,name.size());
1417 fromString(name, ShardSelected);
1419 pCB->setPushed(true);
1422 CCtrlTextButton *pCTB = dynamic_cast<CCtrlTextButton*>(CWidgetManager::getInstance()->getElementFromId(CTRL_BUTTON_CONNECT));
1423 if (pCTB != NULL)
1424 pCTB->setActive(true);
1427 REGISTER_ACTION_HANDLER (CAHShardSelect, "shard_select");
1429 // ***************************************************************************
1430 void ConnectToShard()
1432 //nlinfo("ConnectToShard called");
1434 if (ClientCfg.R2Mode)
1436 // r2 mode
1437 setLoginFinished( true );
1438 loginOK = true;
1440 LoginSM.pushEvent(CLoginStateMachine::ev_enter_game);
1442 else
1444 // legacy mode
1445 nlassert(ShardSelected != -1);
1447 string res = selectShard(Shards[ShardSelected].ShardId, Cookie, FSAddr);
1449 if(res.empty())
1451 setLoginFinished( true );
1452 loginOK = true;
1454 LoginSM.pushEvent(CLoginStateMachine::ev_enter_game);
1456 else
1458 CInterfaceManager *pIM = CInterfaceManager::getInstance();
1459 pIM->messageBoxWithHelp("Error :" + res, "ui:login");
1461 LoginSM.pushEvent(CLoginStateMachine::ev_conn_failed);
1468 // ***************************************************************************
1469 class CAHLoginConnect : public IActionHandler
1471 virtual void execute (CCtrlBase * /* pCaller */, const string &/* Params */)
1473 nlinfo("CAHLoginConnect called");
1475 CInterfaceManager *pIM = CInterfaceManager::getInstance();
1477 if (ShardSelected == -1)
1478 return;
1480 if (!Shards[ShardSelected].Online)
1482 pIM->messageBoxWithHelp(CI18N::get("uiErrOffLineShard"), "ui:login");
1483 return;
1486 LoginSM.pushEvent(CLoginStateMachine::ev_shard_selected);
1488 // std::vector<std::string> patchURIs = Shards[ShardSelected].PatchURIs;
1489 // string url = Shards[ShardSelected].EmergencyPatchURL;
1490 // string ver = Shards[ShardSelected].Version;
1492 // if (!ClientCfg.PatchUrl.empty())
1493 // url = ClientCfg.PatchUrl;
1495 // if (!ClientCfg.PatchVersion.empty())
1496 // ver = ClientCfg.PatchVersion;
1498 // pPM->init(patchURIs, url, ver);
1500 // LoginShardId = Shards[ShardSelected].ShardId;
1502 // if (ClientCfg.PatchWanted)
1503 // {
1504 // pPM->startCheckThread();
1505 // NLGUI::CDBManager::getInstance()->getDbProp("UI:VARIABLES:SCREEN")->setValue32(UI_VARIABLES_SCREEN_CHECKING);
1506 // }
1507 // else
1508 // {
1509 // CAHManager::getInstance()->runActionHandler("login_patch",NULL);
1510 // }
1513 REGISTER_ACTION_HANDLER (CAHLoginConnect, "login_connect");
1515 // ***************************************************************************
1516 // Can be called after a patching process (ryzom relaunch and call this AH to
1517 // see if we have to continue patching or directly go ingame)
1518 class CAHLoginConnect2 : public IActionHandler
1520 virtual void execute (CCtrlBase * /* pCaller */, const string &/* Params */)
1522 nlinfo("CAHLoginConnect2 called");
1523 CInterfaceManager *pIM = CInterfaceManager::getInstance();
1525 if (Shards[ShardSelected].PatchURIs.empty() && Shards[ShardSelected].EmergencyPatchURL.empty())
1527 pIM->messageBoxWithHelp(CI18N::get("uiErrCantPatch"), "ui:login");
1528 return;
1531 LoginSM.pushEvent(CLoginStateMachine::ev_shard_selected);
1533 // std::vector<std::string> patchURIs = Shards[ShardSelected].PatchURIs;
1534 // string url = Shards[ShardSelected].EmergencyPatchURL;
1535 // string ver = Shards[ShardSelected].Version;
1537 // if (!ClientCfg.PatchUrl.empty())
1538 // url = ClientCfg.PatchUrl;
1540 // if (!ClientCfg.PatchVersion.empty())
1541 // ver = ClientCfg.PatchVersion;
1543 // pPM->init(patchURIs, url, ver);
1545 // if ((ClientCfg.PatchWanted) &&
1546 // (!Shards[ShardSelected].Version.empty()) &&
1547 // (Shards[ShardSelected].Version != pPM->getClientVersion()))
1548 // {
1549 // pPM->startCheckThread();
1550 // NLGUI::CDBManager::getInstance()->getDbProp("UI:VARIABLES:SCREEN")->setValue32(UI_VARIABLES_SCREEN_CHECKING);
1551 // }
1552 // else
1553 // {
1554 // // Version is good, eula then connect and launch the client
1555 // showEULA();
1556 // }
1559 REGISTER_ACTION_HANDLER (CAHLoginConnect2, "login_connect_2");
1561 void initPatch()
1563 CInterfaceManager *pIM = CInterfaceManager::getInstance();
1564 CPatchManager *pPM = CPatchManager::getInstance();
1566 #ifdef RYZOM_BG_DOWNLOADER
1567 if (!isBGDownloadEnabled())
1568 #endif
1570 // Get the list of optional categories to patch
1571 vector<string> vCategories;
1573 CInterfaceGroup *pList = dynamic_cast<CInterfaceGroup*>(CWidgetManager::getInstance()->getElementFromId(GROUP_LIST_CAT));
1574 if (pList == NULL)
1576 nlwarning("element " GROUP_LIST_CAT " not found probably bad login_main.xml");
1577 return;
1580 for(uint i = 0; i < InfoOnPatch.OptCat.size(); i++)
1582 // Ok for the moment all optional categories must be patched even if the player
1583 // does not want it. Because we cant detect that a continent have to be patched ingame.
1584 vCategories.push_back(InfoOnPatch.OptCat[i].Name);
1587 // Code to check if the player wants an optional category or not
1588 CInterfaceGroup *pLine = pList->getGroup("c"+toString(i));
1589 if (pLine != NULL)
1591 CCtrlButton *pCB = dynamic_cast<CCtrlButton*>(pLine->getCtrl("on_off"));
1592 if (pCB != NULL)
1594 if (pCB->getPushed())
1595 vCategories.push_back(rAllCats[i]);
1601 pPM->startPatchThread(vCategories, true);
1603 #ifdef RYZOM_BG_DOWNLOADER
1604 else
1606 // NB : here we only do a part of the download each time
1607 BGDownloader::CTaskDesc taskDesc(BGDownloader::DLState_GetAndApplyPatch, (1 << BGDownloaderWantedPatch));
1608 CBGDownloaderAccess::getInstance().startTask(taskDesc, string(), true /* showDownloader */); // no command line since bg downloader should already be started
1609 // release lock on bnp, so that they can be written
1610 NLMISC::CBigFile::getInstance().removeAll();
1611 NLMISC::CStreamedPackageManager::getInstance().unloadAll();
1613 #endif
1614 NLGUI::CDBManager::getInstance()->getDbProp("UI:VARIABLES:SCREEN")->setValue32(UI_VARIABLES_SCREEN_PATCHING);
1616 CInterfaceElement *closeBtn = CWidgetManager::getInstance()->getElementFromId(CTRL_BUTTON_CLOSE_PATCH);
1617 if (closeBtn)
1618 closeBtn->setActive(false);
1620 setPatcherStateText("ui:login:patching", string());
1621 setPatcherProgressText("ui:login:patching", string());
1624 // ***************************************************************************
1625 // Called after the check has been done. The page is full of optional categories that must be selected for patching
1626 class CAHLoginPatch : public IActionHandler
1628 virtual void execute (CCtrlBase * /* pCaller */, const string &/* Params */)
1630 nlinfo("CAHLoginPatch called");
1632 LoginSM.pushEvent(CLoginStateMachine::ev_run_patch);
1634 // CInterfaceManager *pIM = CInterfaceManager::getInstance();
1635 // CPatchManager *pPM = CPatchManager::getInstance();
1637 // // Get the list of optional categories to patch
1638 // vector<string> vCategories;
1640 // CInterfaceGroup *pList = dynamic_cast<CInterfaceGroup*>(CWidgetManager::getInstance()->getElementFromId(GROUP_LIST_CAT));
1641 // if (pList == NULL)
1642 // {
1643 // nlwarning("element "GROUP_LIST_CAT" not found probably bad login_main.xml");
1644 // return;
1645 // }
1647 // for(uint i = 0; i < InfoOnPatch.OptCat.size(); i++)
1648 // {
1649 // // Ok for the moment all optional categories must be patched even if the player
1650 // // does not want it. Because we cant detect that a continent have to be patched ingame.
1651 // vCategories.push_back(InfoOnPatch.OptCat[i].Name);
1653 // /*
1654 // // Code to check if the player wants an optional category or not
1655 // CInterfaceGroup *pLine = pList->getGroup("c"+toString(i));
1656 // if (pLine != NULL)
1657 // {
1658 // CCtrlButton *pCB = dynamic_cast<CCtrlButton*>(pLine->getCtrl("on_off"));
1659 // if (pCB != NULL)
1660 // {
1661 // if (pCB->getPushed())
1662 // vCategories.push_back(rAllCats[i]);
1663 // }
1664 // }
1665 // */
1666 // }
1668 // // Start patching
1669 // if (ClientCfg.PatchWanted)
1670 // {
1671 // pPM->startPatchThread(vCategories);
1672 // NLGUI::CDBManager::getInstance()->getDbProp("UI:VARIABLES:SCREEN")->setValue32(UI_VARIABLES_SCREEN_PATCHING);
1673 // }
1674 // else
1675 // {
1676 // ConnectToShard();
1677 // }
1680 REGISTER_ACTION_HANDLER (CAHLoginPatch, "login_patch");
1682 // ***************************************************************************
1683 // Called after the check has been done. The page is full of optional categories that must be selected for patching
1684 class CAHClosePatch : public IActionHandler
1686 virtual void execute (CCtrlBase * /* pCaller */, const string &/* Params */)
1688 nlinfo("CAHClosePatch called");
1690 LoginSM.pushEvent(CLoginStateMachine::ev_close_patch);
1693 REGISTER_ACTION_HANDLER (CAHClosePatch, "close_patch");
1696 // ***************************************************************************
1697 // Called after pushing the read note at the opening of the modal window
1698 class CAHSetReleaseNote : public IActionHandler
1700 virtual void execute (CCtrlBase * /* pCaller */, const string &sParams)
1702 nlinfo("CAHSetReleaseNote called");
1704 CInterfaceManager *pIM = CInterfaceManager::getInstance();
1706 string sShard = getParam(sParams, "shard");
1707 string sGroupHtml = getParam(sParams, "group");
1709 CGroupHTML *pQH = dynamic_cast<CGroupHTML*>(CWidgetManager::getInstance()->getElementFromId(sGroupHtml));
1710 if (pQH == NULL)
1711 return;
1713 string sURL;
1714 if (ClientCfg.R2Mode)
1716 // ring release note
1717 sURL = ClientCfg.RingReleaseNotePath +
1718 "?version=" + (VersionName.empty() ? R2ServerVersion : VersionName)+
1719 "&lang=" + ClientCfg.LanguageCode +
1720 "&ca=" + ClientCfg.ConfigFile.getVar("Application").asString(0);
1721 "&startPage="+RingMainURL;
1723 else
1725 // legacy ryzom release note
1726 uint32 nShardId;
1727 if (sShard == "selected")
1728 nShardId = ShardSelected;
1729 else
1730 fromString(sShard.substr(1), nShardId);
1732 sURL = ClientCfg.ReleaseNotePath +
1733 "?version=" + Shards[nShardId].Version +
1734 "&lang=" + ClientCfg.LanguageCode +
1735 "&id=" + toString(Shards[nShardId].ShardId) +
1736 "&ca=" + ClientCfg.ConfigFile.getVar("Application").asString(0);
1740 pQH->browse(sURL.c_str());
1743 REGISTER_ACTION_HANDLER (CAHSetReleaseNote, "set_release_note");
1745 // ***************************************************************************
1746 // Called after pushing the read note at the opening of the modal window
1747 class CAHReboot : public IActionHandler
1749 virtual void execute (CCtrlBase * /* pCaller */, const string &/* sParams */)
1751 nlinfo("CAHReboot called");
1753 // create a file to prompt eula next time
1754 CFile::createEmptyFile(getLogDirectory() + "show_eula");
1756 CInterfaceManager *im = CInterfaceManager::getInstance();
1759 #ifdef RYZOM_BG_DOWNLOADER
1760 if (isBGDownloadEnabled())
1762 CBGDownloaderAccess::getInstance().reboot();
1764 else
1765 #endif
1767 CPatchManager::getInstance()->reboot();
1769 LoginSM.pushEvent(CLoginStateMachine::ev_reboot);
1771 catch (const NLMISC::EDiskFullError &)
1773 im->messageBoxWithHelp(CI18N::get("uiPatchDiskFull"), "ui:login");
1775 catch (const NLMISC::EWriteError &)
1777 im->messageBoxWithHelp(CI18N::get("uiPatchWriteError"), "ui:login");
1779 catch (const std::exception &e)
1781 im->messageBoxWithHelp(e.what(), "ui:login", "login_quit");
1785 REGISTER_ACTION_HANDLER (CAHReboot, "reboot");
1789 // ***************************************************************************
1790 class CAHAcceptEula : public IActionHandler
1792 virtual void execute (CCtrlBase * /* pCaller */, const string &/* sParams */)
1794 //nlinfo("CAHAcceptEula called");
1795 if(CFile::fileExists(getLogDirectory() + "show_eula"))
1796 CFile::deleteFile(getLogDirectory() + "show_eula");
1797 LoginSM.pushEvent(CLoginStateMachine::ev_accept_eula);
1799 // if (ClientCfg.R2Mode)
1800 // {
1801 // // open web browser
1802 // CInterfaceManager *pIM = CInterfaceManager::getInstance();
1803 // NLGUI::CDBManager::getInstance()->getDbProp("UI:VARIABLES:SCREEN")->setValue32(UI_VARIABLES_SCREEN_WEBSTART);
1805 // // start the browser
1806 // CGroupHTML *pGH = dynamic_cast<CGroupHTML*>(CWidgetManager::getInstance()->getElementFromId(GROUP_BROWSER));
1808 // pGH->browse(RingMainURL.c_str());
1809 // }
1810 // else
1811 // {
1812 // ConnectToShard();
1813 // }
1816 REGISTER_ACTION_HANDLER (CAHAcceptEula, "accept_eula");
1818 // ***************************************************************************
1819 class CAHOpenURL : public IActionHandler
1821 virtual void execute (CCtrlBase * /* pCaller */, const string &sParams)
1823 nlinfo("CAHOpenURL called");
1825 string url;
1827 string installTag;
1829 #ifdef NL_OS_WINDOWS
1831 // Check for special install tag
1832 const char *KeyName = "InstallTag";
1834 installTag = CSystemUtils::getRegKey(KeyName);
1836 if (installTag.length() > 1)
1838 nldebug("Found install tag '%s'", url.c_str());
1840 else
1842 // Process any inserts in lpMsgBuf.
1843 // ...
1844 // Display the string.
1845 nlwarning("RegQueryValue for '%s' : %s", KeyName, NLMISC::formatErrorMessage(0).c_str());
1847 #else
1848 // TODO: for Linux and Mac OS
1849 #endif
1850 if (sParams == "cfg_CreateAccountURL")
1852 url = ClientCfg.CreateAccountURL;
1854 else if (sParams == "cfg_EditAccountURL")
1856 url = ClientCfg.EditAccountURL;
1858 else if (sParams == "cfg_BetaAccountURL")
1860 url = ClientCfg.BetaAccountURL;
1862 else if (sParams == "cfg_ForgetPwdURL")
1864 url = ClientCfg.ForgetPwdURL;
1866 else if (sParams == "cfg_LoginSupportURL")
1868 url= ClientCfg.LoginSupportURL;
1870 else if (sParams == "cfg_FreeTrialURL")
1872 url = ClientCfg.FreeTrialURL;
1874 if (!installTag.empty())
1876 url += string("&from=")+installTag;
1879 else if (sParams == "cfg_ConditionsTermsURL")
1881 url = ClientCfg.ConditionsTermsURL;
1883 else if (sParams == "cfg_NamingPolicyURL")
1885 url = ClientCfg.NamingPolicyURL;
1887 else
1889 nlwarning("no URL found");
1890 return;
1893 if(sParams != "cfg_ConditionsTermsURL" && sParams != "cfg_NamingPolicyURL")
1895 // modify existing languages
1897 // old site
1898 string::size_type pos_lang = url.find("/en/");
1900 // or new forums
1901 if (pos_lang == string::npos)
1902 pos_lang = url.find("=en#");
1904 if (pos_lang != string::npos)
1906 url.replace(pos_lang + 1, 2, ClientCfg.getHtmlLanguageCode());
1908 else
1910 // append language
1911 if (url.find('?') != string::npos)
1912 url += "&";
1913 else
1914 url += "?";
1916 url += "language=" + ClientCfg.LanguageCode;
1918 if (!LoginCustomParameters.empty())
1919 url += LoginCustomParameters;
1923 openURL(url);
1925 nlinfo("openURL %s", url.c_str());
1928 REGISTER_ACTION_HANDLER (CAHOpenURL, "open_url");
1930 static vector<UDriver::CMode> VideoModes;
1931 vector<string> StringModeList;
1932 vector<string> StringPresetList;
1933 vector< pair<string, bool> > CfgPresetList;
1934 sint CurrentMode = -1;
1935 sint CurrentPreset = -1;
1937 // ***************************************************************************
1938 class CAHInitResLod : public IActionHandler
1940 virtual void execute (CCtrlBase * /* pCaller */, const string &/* sParams */)
1942 //nlinfo("CAHInitResLod called");
1943 if (Driver == NULL) return;
1945 VideoModes.clear();
1946 StringModeList.clear();
1948 std::vector<std::string> stringFreqList;
1949 sint currentFreq;
1951 getRyzomModes(VideoModes, StringModeList, stringFreqList, CurrentMode, currentFreq);
1953 // getRyzomModes() expects empty list, so we need to insert 'Windowed' after mode list is filled
1954 StringModeList.insert(StringModeList.begin(), "uiConfigWindowed");
1956 // If the client is in windowed mode, still in windowed mode and do not change anything
1957 if (ClientCfg.Windowed)
1958 CurrentMode = 0;
1959 // If we have not found the mode so it can be an error or machine change, so propose the first available
1960 else if (CurrentMode == -1)
1961 CurrentMode = 1;
1962 // We inserted 'Windowed' as first mode, so index needs to move too
1963 else
1964 ++CurrentMode;
1966 CInterfaceManager *pIM = CInterfaceManager::getInstance();
1967 CViewText *pVT = dynamic_cast<CViewText*>(CWidgetManager::getInstance()->getElementFromId("ui:login:checkpass:content:res_value"));
1968 if (pVT != NULL)
1969 pVT->setHardText(StringModeList[CurrentMode]);
1971 StringPresetList.clear();
1972 StringPresetList.push_back("uiLodValueLow");
1973 StringPresetList.push_back("uiLodValueMedium");
1974 StringPresetList.push_back("uiLodValueNormal");
1975 StringPresetList.push_back("uiLodValueHigh");
1976 StringPresetList.push_back("uiLodValueCustom");
1977 CurrentPreset = 4; // CInterfaceDDX::CustomPreset
1979 // first indicates the preset-able cfg-variable
1980 // second indicates if its a double variable (else it's an int)
1981 CfgPresetList.clear();
1982 CfgPresetList.push_back(pair<string,bool>("LandscapeTileNear", true));
1983 CfgPresetList.push_back(pair<string,bool>("LandscapeThreshold", true));
1984 CfgPresetList.push_back(pair<string,bool>("Vision", true));
1985 CfgPresetList.push_back(pair<string,bool>("MicroVeget", false));
1986 CfgPresetList.push_back(pair<string,bool>("MicroVegetDensity", true));
1987 CfgPresetList.push_back(pair<string,bool>("FxNbMaxPoly", false));
1988 CfgPresetList.push_back(pair<string,bool>("Cloud", false));
1989 CfgPresetList.push_back(pair<string,bool>("CloudQuality", true));
1990 CfgPresetList.push_back(pair<string,bool>("CloudUpdate", false));
1991 CfgPresetList.push_back(pair<string,bool>("Shadows", false));
1992 CfgPresetList.push_back(pair<string,bool>("SkinNbMaxPoly", false));
1993 CfgPresetList.push_back(pair<string,bool>("NbMaxSkeletonNotCLod", false));
1994 CfgPresetList.push_back(pair<string,bool>("CharacterFarClip", true));
1996 CfgPresetList.push_back(pair<string,bool>("FXAA", false));
1997 CfgPresetList.push_back(pair<string,bool>("Bloom", false));
1998 CfgPresetList.push_back(pair<string,bool>("SquareBloom", false));
1999 CfgPresetList.push_back(pair<string,bool>("DensityBloom", true));
2001 // Check if all the preset-able cfg-variable are in a preset mode
2002 sint nPreset = -1;
2003 for (uint32 i = 0; i < CfgPresetList.size(); ++i)
2005 CConfigFile::CVar *cfgVarPtr = ClientCfg.ConfigFile.getVarPtr(CfgPresetList[i].first);
2006 if (cfgVarPtr == NULL) continue;
2007 // Get the preset of the variable i
2008 sint nVarPreset = 0;
2009 for (uint32 j = 0; j < 4; ++j) // CInterfaceDDX::NumPreset
2011 string sPresetName = CfgPresetList[i].first + "_ps" + toString(j);
2012 CConfigFile::CVar *presetVarPtr = ClientCfg.ConfigFile.getVarPtr(sPresetName);
2013 if(presetVarPtr)
2015 if (CfgPresetList[i].second) // Is it a double ?
2017 if (cfgVarPtr->asDouble() == presetVarPtr->asDouble())
2018 nVarPreset |= (1 << j);
2020 else
2022 if (cfgVarPtr->asInt() == presetVarPtr->asInt())
2023 nVarPreset |= (1 << j);
2028 if (nPreset == -1)
2029 nPreset = nVarPreset;
2030 else
2031 nPreset &= nVarPreset;
2033 if (nPreset == 0)
2034 break;
2037 if (nPreset != 0)
2039 if (nPreset&1) CurrentPreset = 0;
2040 else if (nPreset&2) CurrentPreset = 1;
2041 else if (nPreset&4) CurrentPreset = 2;
2042 else if (nPreset&8) CurrentPreset = 3;
2045 pVT = dynamic_cast<CViewText*>(CWidgetManager::getInstance()->getElementFromId("ui:login:checkpass:content:lod_value"));
2046 if (pVT != NULL)
2047 pVT->setHardText(StringPresetList[CurrentPreset]);
2050 REGISTER_ACTION_HANDLER (CAHInitResLod, "init_res_lod");
2052 // ***************************************************************************
2053 class CAHMoreRes : public IActionHandler
2055 virtual void execute (CCtrlBase * /* pCaller */, const string &/* sParams */)
2057 nlinfo("CAHMoreRes called");
2058 if (CurrentMode < ((sint)StringModeList.size()-1))
2059 CurrentMode++;
2060 CInterfaceManager *pIM = CInterfaceManager::getInstance();
2061 CViewText *pVT = dynamic_cast<CViewText*>(CWidgetManager::getInstance()->getElementFromId("ui:login:checkpass:content:res_value"));
2062 if (pVT != NULL)
2063 pVT->setHardText(StringModeList[CurrentMode]);
2066 REGISTER_ACTION_HANDLER (CAHMoreRes, "more_res");
2068 // ***************************************************************************
2069 class CAHLessRes : public IActionHandler
2071 virtual void execute (CCtrlBase * /* pCaller */, const string &/* sParams */)
2073 nlinfo("CAHLessRes called");
2074 if (CurrentMode > 0)
2075 CurrentMode--;
2076 CInterfaceManager *pIM = CInterfaceManager::getInstance();
2077 CViewText *pVT = dynamic_cast<CViewText*>(CWidgetManager::getInstance()->getElementFromId("ui:login:checkpass:content:res_value"));
2078 if (pVT != NULL)
2079 pVT->setHardText(StringModeList[CurrentMode]);
2082 REGISTER_ACTION_HANDLER (CAHLessRes, "less_res");
2084 // ***************************************************************************
2085 class CAHMoreLod : public IActionHandler
2087 virtual void execute (CCtrlBase * /* pCaller */, const string &/* sParams */)
2089 nlinfo("CAHMoreLod called");
2090 if (CurrentPreset < ((sint)StringPresetList.size()-1))
2091 CurrentPreset++;
2092 CInterfaceManager *pIM = CInterfaceManager::getInstance();
2093 CViewText *pVT = dynamic_cast<CViewText*>(CWidgetManager::getInstance()->getElementFromId("ui:login:checkpass:content:lod_value"));
2094 if (pVT != NULL)
2095 pVT->setHardText(StringPresetList[CurrentPreset]);
2098 REGISTER_ACTION_HANDLER (CAHMoreLod, "more_lod");
2100 // ***************************************************************************
2101 class CAHLessLod : public IActionHandler
2103 virtual void execute (CCtrlBase * /* pCaller */, const string &/* sParams */)
2105 nlinfo("CAHMoreLod called");
2106 if (CurrentPreset > 0)
2107 CurrentPreset--;
2108 CInterfaceManager *pIM = CInterfaceManager::getInstance();
2109 CViewText *pVT = dynamic_cast<CViewText*>(CWidgetManager::getInstance()->getElementFromId("ui:login:checkpass:content:lod_value"));
2110 if (pVT != NULL)
2111 pVT->setHardText(StringPresetList[CurrentPreset]);
2114 REGISTER_ACTION_HANDLER (CAHLessLod, "less_lod");
2116 // ***************************************************************************
2117 // TODO: remove resolution change from login screen
2118 class CAHUninitResLod : public IActionHandler
2120 virtual void execute (CCtrlBase * /* pCaller */, const string &/* sParams */)
2122 //nlinfo("CAHUninitResLod called");
2124 // If the mode requested is a windowed mode do nothnig
2125 if (CurrentMode == 0)
2127 ClientCfg.Windowed = true;
2128 ClientCfg.writeBool("FullScreen", false);
2130 else
2132 ClientCfg.Windowed = false;
2133 // Get W, H
2134 uint16 w = 0, h = 0;
2136 string vidModeStr = StringModeList[CurrentMode];
2137 string tmp = vidModeStr.substr(0,vidModeStr.find('x')-1);
2138 fromString(tmp, w);
2139 tmp = vidModeStr.substr(vidModeStr.find('x')+2,vidModeStr.size());
2140 fromString(tmp, h);
2142 ClientCfg.Width = w;
2143 ClientCfg.Height = h;
2145 ClientCfg.writeBool("FullScreen", true);
2146 ClientCfg.writeInt("Width", w);
2147 ClientCfg.writeInt("Height", h);
2150 if (CurrentPreset != 4) // CInterfaceDDX::CustomPreset
2152 for (uint32 i = 0; i < CfgPresetList.size(); ++i)
2154 CConfigFile::CVar *cfgVarPtr = ClientCfg.ConfigFile.getVarPtr(CfgPresetList[i].first);
2155 if (cfgVarPtr == NULL) continue;
2157 string sPresetName = CfgPresetList[i].first + "_ps" + toString(CurrentPreset);
2158 CConfigFile::CVar *presetVarPtr = ClientCfg.ConfigFile.getVarPtr(sPresetName);
2159 if(presetVarPtr)
2161 if (CfgPresetList[i].second) // Is it a double ?
2162 cfgVarPtr->setAsDouble(presetVarPtr->asDouble());
2163 else
2164 cfgVarPtr->setAsInt(presetVarPtr->asInt());
2169 // **** Save the config
2170 if (ClientCfg.SaveConfig)
2171 ClientCfg.ConfigFile.save ();
2172 ClientCfg.IsInvalidated = true;
2175 REGISTER_ACTION_HANDLER (CAHUninitResLod, "uninit_res_lod");
2178 void initDataScan()
2180 CInterfaceManager *pIM = CInterfaceManager::getInstance();
2181 CPatchManager *pPM = CPatchManager::getInstance();
2183 // reset the log
2184 setDataScanLog(string());
2186 // Start Scanning
2187 pPM->startScanDataThread();
2188 NLGUI::CDBManager::getInstance()->getDbProp("UI:VARIABLES:SCREEN")->setValue32(UI_VARIABLES_SCREEN_DATASCAN);
2189 NLGUI::CDBManager::getInstance()->getDbProp("UI:VARIABLES:DATASCAN_RUNNING")->setValue32(1);
2192 // ***************************************************************************
2193 // Called after the check has been done. The page is full of optional categories that must be selected for patching
2194 class CAHOnScanDataStart : public IActionHandler
2196 virtual void execute (CCtrlBase * /* pCaller */, const string &/* Params */)
2198 nlinfo("CAHOnScanDataStart called");
2200 LoginSM.pushEvent(CLoginStateMachine::ev_data_scan);
2204 REGISTER_ACTION_HANDLER (CAHOnScanDataStart, "on_scan_data_start");
2206 // ***************************************************************************
2207 // Called when the user cancel the scan
2208 class CAHOnScanDataClose : public IActionHandler
2210 virtual void execute (CCtrlBase * /* pCaller */, const string &/* Params */)
2212 nlinfo("CAHOnScanDataClose called");
2213 CInterfaceManager *pIM = CInterfaceManager::getInstance();
2214 CPatchManager *pPM = CPatchManager::getInstance();
2216 // if the scan is still running
2217 if(NLGUI::CDBManager::getInstance()->getDbProp("UI:VARIABLES:DATASCAN_RUNNING")->getValue32()!=0)
2219 // request to stop the thread
2220 pPM->askForStopScanDataThread();
2222 // Log.
2223 setDataScanState(CI18N::get("uiCancelingScanData"));
2225 else
2227 LoginSM.pushEvent(CLoginStateMachine::ev_close_data_scan);
2228 // Come Back to Login Screen.
2229 // NLGUI::CDBManager::getInstance()->getDbProp("UI:VARIABLES:SCREEN")->setValue32(UI_VARIABLES_SCREEN_CHECKPASS);
2231 // // Give focus to password if some login entered
2232 // string loginEB;
2233 // CGroupEditBox *pGEB = dynamic_cast<CGroupEditBox*>(CWidgetManager::getInstance()->getElementFromId(CTRL_EDITBOX_LOGIN));
2234 // if(pGEB)
2235 // loginEB= pGEB->getInputStringAsStdString();
2236 // // if none entered
2237 // if (loginEB.empty())
2238 // CAHManager::getInstance()->runActionHandler("set_keyboard_focus", NULL, "target=" CTRL_EDITBOX_LOGIN "|select_all=false");
2239 // else
2240 // CAHManager::getInstance()->runActionHandler("set_keyboard_focus", NULL, "target=" CTRL_EDITBOX_PASSWORD "|select_all=false");
2244 REGISTER_ACTION_HANDLER (CAHOnScanDataClose, "on_scan_data_close");
2246 // ***************************************************************************
2248 inline string parseTooltip(const string & initString, const string & tagName)
2250 string tooltip;
2252 string::size_type tooltipPos = initString.find(tagName);
2253 if(tooltipPos != string::npos)
2255 tooltip = initString.substr(tooltipPos);
2257 // start of tooltip
2258 tooltip = tooltip.substr(tooltip.find(">")+1);
2260 // end of tooltip
2261 tooltip = tooltip.substr(0, tooltip.find("<"));
2264 return tooltip;
2267 inline string parseCommentError(const string & initString, const string & tagName)
2269 string error;
2271 string::size_type errorPos = initString.find(tagName);
2272 if(errorPos != string::npos)
2274 error = initString.substr(errorPos);
2276 // start of comment
2277 error = error.substr(error.find(">")+1);
2279 // end of comment
2280 error = error.substr(0, error.find("<"));
2283 return error;
2286 bool initCreateAccount()
2288 CInterfaceManager *pIM = CInterfaceManager::getInstance();
2290 // reset UI
2291 CInterfaceGroup *createAccountUI = dynamic_cast<CInterfaceGroup*>(CWidgetManager::getInstance()->getElementFromId("ui:login:create_account"));
2292 if(createAccountUI)
2294 // show "submit interface", hide "login interface"
2295 CInterfaceGroup * grSubmit = dynamic_cast<CInterfaceGroup*>(createAccountUI->findFromShortId("submit_gr"));
2296 if(grSubmit)
2297 grSubmit->setActive(true);
2299 CInterfaceGroup * grLogin = dynamic_cast<CInterfaceGroup*>(createAccountUI->findFromShortId("login_gr"));
2300 if(grLogin)
2301 grLogin->setActive(false);
2303 // empty edit boxes
2304 std::vector< std::string > editBoxes(4);
2305 editBoxes[0] = "eb_login";
2306 editBoxes[1] = "eb_password";
2307 editBoxes[2] = "eb_confirm_password";
2308 editBoxes[3] = "eb_email";
2310 for(uint i=0; i<editBoxes.size(); i++)
2312 CGroupEditBox * eb = dynamic_cast<CGroupEditBox*>(createAccountUI->findFromShortId(editBoxes[i] + ":eb"));
2313 if(eb)
2314 eb->setInputString(std::string());
2317 // conditions button
2318 CCtrlBaseButton * but = dynamic_cast<CCtrlBaseButton*>(createAccountUI->findFromShortId("accept_cond"));
2319 if(but)
2320 but->setPushed(true);
2322 // get rules from url
2323 string url = ClientCfg.CreateAccountURL;
2324 CPatchManager *pPM = CPatchManager::getInstance();
2326 if (!CurlHttpClient.connect(url))
2328 nlwarning("Can't connect");
2329 return false;
2332 std::string lang = ClientCfg.LanguageCode;
2333 if(lang=="wk") lang = "uk";
2335 CurlHttpClient.verifyServer(true); // set this to false if you need to connect to the test environment
2337 std::string params = "language=" + lang;
2339 if (!LoginCustomParameters.empty())
2340 params += LoginCustomParameters;
2342 if(!CurlHttpClient.sendGet(url, params, pPM->isVerboseLog()))
2344 string errorMessage("Can't send (error code 60)");
2345 errorMessageBox(errorMessage);
2346 nlwarning(errorMessage.c_str());
2347 return false;
2350 string res;
2351 if(!CurlHttpClient.receive(res, pPM->isVerboseLog()))
2353 string errorMessage("Can't receive (error code 61)");
2354 errorMessageBox(errorMessage);
2355 nlwarning(errorMessage.c_str());
2356 return false;
2359 if(res.empty())
2361 string errorMessage("Empty result (error code 13)");
2362 errorMessageBox(errorMessage);
2363 nlwarning(errorMessage.c_str());
2364 return false;
2367 CurlHttpClient.disconnect();
2369 // initialize rules in interface
2370 std::vector< std::pair< std::string , std::string > > rules(5);
2371 rules[0] = std::pair<std::string , std::string>("rules_login", "id=tooltip-Username");
2372 rules[1] = std::pair<std::string , std::string>("rules_password", "id=tooltip-Password");
2373 rules[2] = std::pair<std::string , std::string>("rules_password_conf", "id=tooltip-ConfirmPass");
2374 rules[3] = std::pair<std::string , std::string>("rules_email", "id=tooltip-Email");
2375 rules[4] = std::pair<std::string , std::string>("rules_conditions", "id=tooltip-TaC");
2377 for(uint i=0; i<rules.size(); i++)
2379 CViewText * text = dynamic_cast<CViewText*>(createAccountUI->findFromShortId(rules[i].first));
2380 if(text)
2382 string tooltip = parseTooltip(res, rules[i].second);
2383 text->setHardText(tooltip);
2384 text->setActive(false);
2388 // welcome text
2389 CViewText * text = dynamic_cast<CViewText*>(createAccountUI->findFromShortId("errors_list"));
2390 if(text)
2392 text->setHardText(toString(CI18N::get("uiCreateAccountWelcome")));
2393 text->setColor(CRGBA(255, 255, 255, 255));
2395 CInterfaceGroup * group = dynamic_cast<CInterfaceGroup*>(createAccountUI->findFromShortId("erros_txt"));
2396 if(group)
2398 group->updateCoords();
2400 CInterfaceGroup * groupScroll = dynamic_cast<CInterfaceGroup*>(createAccountUI->findFromShortId("err_back_scrollbar"));
2401 if(groupScroll) groupScroll->setActive(group->getHReal() > group->getMaxHReal());
2402 CCtrlScroll * scroll = dynamic_cast<CCtrlScroll*>(createAccountUI->findFromShortId("err_scroll_bar"));
2403 if(scroll)
2404 scroll->setTrackPos(scroll->getHReal());
2408 // hide rules
2409 CInterfaceGroup * rulesGr = dynamic_cast<CInterfaceGroup*>(createAccountUI->findFromShortId("rules_gr"));
2410 if(rulesGr)
2411 rulesGr->setActive(false);
2413 // must be done after hide rules
2414 CAHManager::getInstance()->runActionHandler("set_keyboard_focus", NULL, "target=" CTRL_EDITBOX_CREATEACCOUNT_LOGIN "|select_all=false");
2418 NLGUI::CDBManager::getInstance()->getDbProp("UI:VARIABLES:SCREEN")->setValue32(UI_VARIABLES_SCREEN_CREATE_ACCOUNT);
2420 return true;
2423 // ***************************************************************************
2424 // Called when the user focus one of the edit boxes during the account creation
2425 class CAHCreateAccountRules : public IActionHandler
2427 virtual void execute (CCtrlBase * /* pCaller */, const string &Params)
2429 nlinfo("CAHCreateAccountRules called");
2431 CInterfaceManager *pIM = CInterfaceManager::getInstance();
2432 CInterfaceGroup *createAccountUI = dynamic_cast<CInterfaceGroup*>(CWidgetManager::getInstance()->getElementFromId("ui:login:create_account"));
2433 if(createAccountUI)
2435 CInterfaceGroup * rulesGr = dynamic_cast<CInterfaceGroup*>(createAccountUI->findFromShortId("rules_gr"));
2436 if(rulesGr)
2437 rulesGr->setActive(false);
2439 std::vector< std::string > rules(4);
2440 rules[0] = "rules_login";
2441 rules[1] = "rules_password";
2442 rules[2] = "rules_password_conf";
2443 rules[3] = "rules_email";
2445 for(uint i=0; i<rules.size(); i++)
2447 CViewText * text = dynamic_cast<CViewText*>(createAccountUI->findFromShortId(rules[i]));
2448 if(text)
2450 text->setActive(Params==rules[i]);
2451 if(Params==rules[i])
2453 if(rulesGr)
2454 rulesGr->setActive(!text->getText().empty());
2461 REGISTER_ACTION_HANDLER (CAHCreateAccountRules, "create_account_rules");
2463 // ***************************************************************************
2464 // Called when the user choose the account creation
2465 class CAHOnCreateAccount : public IActionHandler
2467 virtual void execute (CCtrlBase * /* pCaller */, const string &/* Params */)
2469 nlinfo("CAHOnCreateAccount called");
2471 LoginSM.pushEvent(CLoginStateMachine::ev_create_account);
2474 REGISTER_ACTION_HANDLER (CAHOnCreateAccount, "on_create_account");
2476 // ***************************************************************************
2477 // Called when the user submit the account creation
2478 class CAHOnCreateAccountSubmit : public IActionHandler
2480 virtual void execute (CCtrlBase * /* pCaller */, const string &/* Params */)
2482 nlinfo("CAHOnCreateAccountSubmit called");
2484 CInterfaceManager *pIM = CInterfaceManager::getInstance();
2486 CInterfaceGroup *createAccountUI = dynamic_cast<CInterfaceGroup*>(CWidgetManager::getInstance()->getElementFromId("ui:login:create_account"));
2487 if(createAccountUI)
2489 // recover data from UI
2490 std::vector< std::string > editBoxes(4);
2491 editBoxes[0] = "eb_login";
2492 editBoxes[1] = "eb_password";
2493 editBoxes[2] = "eb_confirm_password";
2494 editBoxes[3] = "eb_email";
2495 std::vector< std::string > results(4);
2497 for(uint i=0; i<editBoxes.size(); i++)
2499 CGroupEditBox * eb = dynamic_cast<CGroupEditBox*>(createAccountUI->findFromShortId(editBoxes[i] + ":eb"));
2500 if(eb)
2501 results[i] = eb->getInputString();
2504 // text
2505 CViewText * text = dynamic_cast<CViewText*>(createAccountUI->findFromShortId("email_adress"));
2506 if(text)
2507 text->setHardText(results[3]);
2509 // conditions button
2510 bool conditionsPushed = false;
2511 CCtrlBaseButton * but = dynamic_cast<CCtrlBaseButton*>(createAccountUI->findFromShortId("accept_cond"));
2512 if(but)
2513 conditionsPushed = !but->getPushed();
2515 string url = ClientCfg.CreateAccountURL;
2516 CPatchManager *pPM = CPatchManager::getInstance();
2518 if (!CurlHttpClient.connect(url))
2520 string errorMessage("Can't connect");
2521 errorMessageBox(errorMessage);
2522 nlwarning(errorMessage.c_str());
2523 return;
2526 std::string params = "Username=" + results[0] + "&Password=" + results[1]
2527 + "&ConfirmPass=" + results[2] + "&Email=" + results[3];
2529 if(conditionsPushed)
2530 params += "&TaC=1";
2532 if (!LoginCustomParameters.empty())
2533 params += LoginCustomParameters;
2535 std::string md5 = results[0] + results[1] + "" + results[3];
2536 md5 = NLMISC::getMD5((uint8*)md5.data(), (uint32)md5.size()).toString();
2538 params += "&SC=" + md5;
2539 std::string lang = ClientCfg.LanguageCode;
2540 if(lang=="wk") lang = "uk";
2541 params += "&Language=" + lang;
2543 CurlHttpClient.verifyServer(true); // set this to false if you need to connect to the test environment
2545 if(!CurlHttpClient.sendPost(url, params, pPM->isVerboseLog()))
2547 string errorMessage("Can't send (error code 60)");
2548 errorMessageBox(errorMessage);
2549 nlwarning(errorMessage.c_str());
2550 return;
2553 string res;
2554 if(!CurlHttpClient.receive(res, pPM->isVerboseLog()))
2556 string errorMessage("Can't receive (error code 61)");
2557 errorMessageBox(errorMessage);
2558 nlwarning(errorMessage.c_str());
2559 return;
2562 if(res.empty())
2564 string errorMessage("Empty result (error code 13)");
2565 errorMessageBox(errorMessage);
2566 nlwarning(errorMessage.c_str());
2567 return;
2570 CurlHttpClient.disconnect();
2572 // parse html
2573 string::size_type okPos = res.find("email_sent");
2574 if(okPos != string::npos)
2576 // show "submit interface", hide "login interface"
2577 CInterfaceGroup * grSubmit = dynamic_cast<CInterfaceGroup*>(createAccountUI->findFromShortId("submit_gr"));
2578 if(grSubmit)
2579 grSubmit->setActive(false);
2581 CInterfaceGroup * grLogin = dynamic_cast<CInterfaceGroup*>(createAccountUI->findFromShortId("login_gr"));
2582 if(grLogin)
2583 grLogin->setActive(true);
2585 else
2587 // initialize error comments in interface
2588 CViewText * text = dynamic_cast<CViewText*>(createAccountUI->findFromShortId("errors_list"));
2589 if(text)
2591 text->setColor(CRGBA(250, 30, 30, 255));
2593 std::vector< std::string > errors(5);
2594 errors[0] = "id=\"comment-Username\"";
2595 errors[1] = "id=\"comment-Password\"";
2596 errors[2] = "id=\"comment-ConfirmPass\"";
2597 errors[3] = "id=\"comment-Email\"";
2598 errors[4] = "id=\"comment-TaC\"";
2600 string error;
2601 for(uint i=0; i<errors.size(); i++)
2603 string comment = parseCommentError(res, errors[i]);
2604 if(!comment.empty())
2605 error += "- " + comment + "\n";
2608 text->setHardText(error);
2610 CInterfaceGroup * group = dynamic_cast<CInterfaceGroup*>(createAccountUI->findFromShortId("erros_txt"));
2611 if(group)
2613 group->updateCoords();
2615 CInterfaceGroup * groupScroll = dynamic_cast<CInterfaceGroup*>(createAccountUI->findFromShortId("err_back_scrollbar"));
2616 if(groupScroll) groupScroll->setActive(group->getHReal() > group->getMaxHReal());
2617 CCtrlScroll * scroll = dynamic_cast<CCtrlScroll*>(createAccountUI->findFromShortId("err_scroll_bar"));
2618 if(scroll)
2619 scroll->setTrackPos(scroll->getHReal());
2626 REGISTER_ACTION_HANDLER (CAHOnCreateAccountSubmit, "on_create_account_submit");
2628 // ***************************************************************************
2629 // Called when the user cancel the account creation
2630 class CAHOnCreateAccountClose : public IActionHandler
2632 virtual void execute (CCtrlBase * /* pCaller */, const string &/* Params */)
2634 nlinfo("CAHOnCreateAccountClose called");
2636 LoginSM.pushEvent(CLoginStateMachine::ev_close_create_account);
2639 REGISTER_ACTION_HANDLER (CAHOnCreateAccountClose, "on_create_account_close");
2641 // ***************************************************************************
2642 class CAHCreateAccountLogin : public IActionHandler
2644 virtual void execute (CCtrlBase * /* pCaller */, const string &/* Params */)
2646 nlinfo("CAHCreateAccountLogin called");
2648 CInterfaceManager *pIM = CInterfaceManager::getInstance();
2650 CInterfaceGroup *createAccountUI = dynamic_cast<CInterfaceGroup*>(CWidgetManager::getInstance()->getElementFromId("ui:login:create_account"));
2651 if(createAccountUI)
2653 CGroupEditBox * eb = dynamic_cast<CGroupEditBox*>(createAccountUI->findFromShortId("eb_login:eb"));
2654 if(eb)
2655 LoginLogin = eb->getInputString();
2657 eb = dynamic_cast<CGroupEditBox*>(createAccountUI->findFromShortId("eb_password:eb"));
2658 if(eb)
2659 LoginPassword = eb->getInputString();
2661 onlogin(false);
2665 REGISTER_ACTION_HANDLER (CAHCreateAccountLogin, "create_account_login");
2667 // ***************************************************************************
2668 // Called by html embeded lua script
2669 class CAHOnConnectToShard: public IActionHandler
2671 virtual void execute (CCtrlBase * /* pCaller */, const string &Params)
2673 // warning : pCaller is null when event come from lua scrip embeded in HTML
2674 Cookie = getParam(Params, "cookie");
2675 FSAddr = getParam(Params, "fsAddr");
2677 // replace the '_' with '|' in the cookie string
2678 for (uint i=0; i<Cookie.size(); ++i)
2680 if (Cookie[i] == '_')
2681 Cookie[i] = '|';
2684 setLoginFinished( true );
2685 loginOK = true;
2687 LoginSM.pushEvent(CLoginStateMachine::ev_connect);
2690 REGISTER_ACTION_HANDLER (CAHOnConnectToShard, "on_connect_to_shard");
2692 // ***************************************************************************
2693 // Called to return to login screen in case of error
2694 class CAHOnBackToLogin: public IActionHandler
2696 virtual void execute (CCtrlBase * /* pCaller */, const string &/* Params */)
2698 setLoginFinished( false );
2699 loginOK = false;
2700 LoginSM.pushEvent(CLoginStateMachine::ev_relog);
2702 // CInterfaceManager *pIM = CInterfaceManager::getInstance();
2703 // // need to reset password and current screen
2704 // NLGUI::CDBManager::getInstance()->getDbProp("UI:VARIABLES:SCREEN")->setValue32(UI_VARIABLES_SCREEN_CHECKPASS);
2707 REGISTER_ACTION_HANDLER (CAHOnBackToLogin, "on_back_to_login");
2709 // ***************************************************************************
2710 // ***************************************************************************
2711 // ***************************************************************************
2712 // NETWORK CONNECTION
2713 // ***************************************************************************
2714 // ***************************************************************************
2715 // ***************************************************************************
2718 // ***************************************************************************
2719 string checkLogin(const string &login, const string &password, const string &clientApp, const std::string &customParameters)
2721 CPatchManager *pPM = CPatchManager::getInstance();
2722 Shards.clear();
2724 if(ClientCfg.ConfigFile.exists("VerboseLog"))
2725 pPM->setVerboseLog(ClientCfg.ConfigFile.getVar("VerboseLog").asInt() == 1);
2726 if(pPM->isVerboseLog()) nlinfo("Using verbose log mode");
2728 if(!HttpClient.connectToLogin())
2729 return "Can't connect (error code 1)";
2731 if(pPM->isVerboseLog()) nlinfo("Connected");
2733 string res;
2735 std::string url = ClientCfg.ConfigFile.getVar("StartupHost").asString() + ClientCfg.ConfigFile.getVar("StartupPage").asString();
2737 // don't use login with alt method
2738 if (!login.empty())
2740 // ask server for salt
2741 if(!HttpClient.sendGet(url + "?cmd=ask&cp=2&login=" + login + "&lg=" + ClientCfg.LanguageCode, "", pPM->isVerboseLog()))
2742 return std::string("Can't send (error code 60) ") + HttpClient.lastError();
2744 if(pPM->isVerboseLog()) nlinfo("Sent request for password salt");
2746 if(!HttpClient.receive(res, pPM->isVerboseLog()))
2747 return "Can't receive (error code 61)";
2749 if(pPM->isVerboseLog()) nlinfo("Received request login check");
2751 if(res.empty())
2752 return "Empty answer from server (error code 62)";
2754 size_t first = res.find("\n\n");
2755 if (first == std::string::npos)
2757 first = res.find("\r\r");
2758 if (first == std::string::npos)
2760 first = res.find("\r\n\r\n");
2761 if (first != std::string::npos)
2763 res = res.substr(first + 4);
2766 else
2768 res = res.substr(first + 2);
2771 else
2773 res = res.substr(first + 2);
2776 nldebug("res1: %s", res.c_str());
2778 if (res[0] == 'H')
2780 nlwarning("missing response body: %s", res.c_str());
2781 return "missing response body (error code 64)";
2783 else if(res[0] == '0')
2785 // server returns an error
2786 nlwarning("server error: %s", res.substr(2).c_str());
2787 return res.substr(2);
2789 else if(res[0] == '1')
2791 Salt = res.substr(2);
2793 else
2795 // server returns ???
2796 nlwarning("%s", res.c_str());
2797 return res;
2800 // send login + crypted password + client app and cp=2 (as crypted password)
2801 if(!HttpClient.connectToLogin())
2802 return "Can't connect (error code 63)";
2804 if(pPM->isVerboseLog()) nlinfo("Connected");
2807 if (ClientCfg.R2Mode)
2809 // R2 login sequence
2811 if (!login.empty())
2813 std::string cryptedPassword = CCrypt::crypt(password, Salt);
2815 if(!HttpClient.sendGet(url + "?cmd=login&login=" + login + "&password=" + cryptedPassword + "&clientApplication=" + clientApp + "&cp=2" + "&lg=" + ClientCfg.LanguageCode + customParameters))
2816 return std::string("Can't send (error code 2) ") + HttpClient.lastError();
2818 else
2820 // don't send login and password if empty
2821 if(!HttpClient.sendGet(url + "?cmd=login&clientApplication=" + clientApp + "&cp=2" + "&lg=" + ClientCfg.LanguageCode + customParameters))
2822 return std::string("Can't send (error code 2) ") + HttpClient.lastError();
2825 // the response should contains the result code and the cookie value
2826 if(pPM->isVerboseLog()) nlinfo("Sent request login check");
2828 if(!HttpClient.receive(res, pPM->isVerboseLog()))
2829 return "Can't receive (error code 3)";
2831 if(pPM->isVerboseLog()) nlinfo("Received request login check");
2833 if(res.empty())
2834 return "Empty answer from server (error code 4)";
2836 size_t first = res.find("\n\n");
2837 if (first == std::string::npos)
2839 first = res.find("\r\r");
2840 if (first == std::string::npos)
2842 first = res.find("\r\n\r\n");
2843 if (first != std::string::npos)
2845 res = res.substr(first + 4);
2848 else
2850 res = res.substr(first + 2);
2853 else
2855 res = res.substr(first + 2);
2858 nldebug("res2: %s", res.c_str());
2860 if (res[0] == 'H')
2862 nlwarning("missing response body: %s", res.c_str());
2863 return "missing response body (error code 65)";
2865 else if(res[0] == '0')
2867 // server returns an error
2868 nlwarning("server error: %s", res.substr(2).c_str());
2869 return res.substr(2);
2871 else if(res[0] == '1')
2873 //nlwarning(res.c_str());
2874 vector<string> lines;
2875 explode(res, std::string("\n"), lines, false);
2876 if (lines.size() != 2)
2878 return toString("Invalid server return, found %u lines, want 2", lines.size());
2881 vector<string> parts;
2882 explode(lines[0], std::string("#"), parts, false);
2883 if (parts.size() < 5)
2884 return "Invalid server return, missing cookie and/or Ring URLs";
2886 // server returns ok, we have the cookie
2888 // store the cookie value and FS address for next page request
2889 CurrentCookie = parts[1];
2890 Cookie = CurrentCookie;
2891 FSAddr = parts[2];
2893 // store the ring startup page
2894 RingMainURL = parts[3];
2895 FarTP.setURLBase(parts[4]);
2897 if(parts.size() >= 6 && parts[5] == "1")
2899 // we want stats
2900 extern bool startStat;
2901 startStat = true;
2904 // parse the second line (contains the domain info)
2905 parts.clear();
2906 explode(lines[1], std::string("#"), parts, false);
2907 if (parts.size() < 3)
2908 return "Invalid server return, missing patch URLs";
2910 R2ServerVersion = parts[0].c_str();
2911 R2BackupPatchURL = parts[1];
2912 explode(parts[2], std::string(" "), R2PatchURLs, true);
2914 else
2916 // unexpected content
2917 #if !FINAL_VERSION
2918 string ret = toString("DEV : Invalid server return, missing return code in \n%s", res.c_str());
2919 return ret;
2920 #else
2921 return "Invalid server return, missing return code";
2922 #endif
2926 else
2928 // standard ryzom login sequence
2929 std::string cryptedPassword = CCrypt::crypt(password, Salt);
2931 if(!HttpClient.sendGet(url + "?login=" + login + "&password=" + cryptedPassword + "&clientApplication=" + clientApp + "&cp=2"))
2932 return std::string("Can't send (error code 2) ") + HttpClient.lastError();
2934 if(!send(ClientCfg.ConfigFile.getVar("StartupPage").asString()+"?login="+login+"&password="+password+"&clientApplication="+clientApp))
2935 return "Can't send (error code 2)";
2937 if(pPM->isVerboseLog()) nlinfo("Sent request login check");
2939 if(!HttpClient.receive(res, pPM->isVerboseLog()))
2940 return "Can't receive (error code 3)";
2942 if(pPM->isVerboseLog()) nlinfo("Received request login check");
2944 if(res.empty())
2945 return "Empty answer from server (error code 4)";
2947 size_t first = res.find("\n\n");
2948 if (first == std::string::npos)
2950 first = res.find("\r\r");
2951 if (first == std::string::npos)
2953 first = res.find("\r\n\r\n");
2954 if (first != std::string::npos)
2956 res = res.substr(first + 4);
2959 else
2961 res = res.substr(first + 2);
2964 else
2966 res = res.substr(first + 2);
2969 nldebug("res2: %s", res.c_str());
2971 if (res[0] == 'H')
2973 nlwarning("missing response body: %s", res.c_str());
2974 return "missing response body (error code 66)";
2976 else if(res[0] == '0')
2978 // server returns an error
2979 nlwarning("server error: %s", res.substr(2).c_str());
2980 return res.substr(2);
2982 else if(res[0] == '1')
2984 // server returns ok, we have the list of shard
2985 uint nbs;
2986 fromString(res.substr(2), nbs);
2987 vector<string> lines;
2989 explode(res, std::string("\n"), lines, true);
2991 if(pPM->isVerboseLog())
2993 nlinfo ("Exploded, with nl, %u res", (uint)lines.size());
2994 /* for (uint i = 0; i < lines.size(); i++)
2996 nlinfo (" > '%s'", lines[i].c_str());
3000 if(lines.size() != nbs+1)
3002 nlwarning("bad shard lines number %u != %d", (uint)lines.size(), nbs+1);
3003 nlwarning("'%s'", res.c_str());
3004 return "bad lines numbers (error code 5)";
3007 for(uint i = 1; i < lines.size(); i++)
3009 vector<string> res;
3010 explode(lines[i], std::string("|"), res);
3012 if(pPM->isVerboseLog())
3014 nlinfo ("Exploded with '%s', %u res", "|", (uint)res.size());
3015 /* for (uint i = 0; i < res.size(); i++)
3017 nlinfo (" > '%s'", res[i].c_str());
3021 if (res.size() < 7 && res.size() > 8)
3023 nlwarning("bad | numbers %u != %d", (uint)res.size(), 8);
3024 nlwarning("'%s'", lines[i].c_str());
3025 return "bad pipe numbers (error code 6)";
3027 bool online;
3028 fromString(res[1], online);
3029 uint32 shardId;
3030 fromString(res[2], shardId);
3031 uint32 nbPlayers;
3032 fromString(res[4], nbPlayers);
3033 Shards.push_back(CShard(res[0], online, shardId, res[3], nbPlayers, res[5], res[6]));
3034 nlinfo("Shard %u, addr = %s, id = %u, name = %s, PatchURIs = %s", i, res[5].c_str(), shardId, res[3].c_str(), res[6].c_str());
3035 if (res.size() == 8)
3037 explode(res[7], std::string(" "), Shards.back().PatchURIs);
3041 else
3043 // server returns ???
3044 nlwarning("%s", res.c_str());
3045 return res;
3049 return "";
3052 // ***************************************************************************
3053 string selectShard(uint32 shardId, string &cookie, string &addr)
3055 cookie.clear();
3056 addr.clear();
3058 if(!HttpClient.connectToLogin()) return "Can't connect (error code 7)";
3060 if(LoginLogin.empty()) return "Empty Login (error code 8)";
3061 if(LoginPassword.empty()) return "Empty Password (error code 9)";
3062 if(ClientApp.empty()) return "Empty Client Application (error code 10)";
3064 // send login + crypted password + client app and cp=2 (as crypted password)
3065 std::string cryptedPassword = CCrypt::crypt(LoginPassword, Salt);
3067 std::string url = ClientCfg.ConfigFile.getVar("StartupHost").asString() + ClientCfg.ConfigFile.getVar("StartupPage").asString();
3069 if(!HttpClient.sendGet(url + "?cmd=login&shardid=" + toString(shardId) + "&login=" + LoginLogin + "&password=" + cryptedPassword + "&clientApplication=" + ClientApp + "&cp=2"))
3070 return "Can't send (error code 11)";
3072 string res;
3074 CPatchManager *pPM = CPatchManager::getInstance();
3075 if(!HttpClient.receive(res, pPM->isVerboseLog()))
3076 return "Can't receive (error code 12)";
3078 if(res.empty())
3079 return "Empty result (error code 13)";
3081 size_t first = res.find("\n\n");
3082 if (first == std::string::npos)
3084 first = res.find("\r\r");
3085 if (first == std::string::npos)
3087 first = res.find("\r\n\r\n");
3088 if (first != std::string::npos)
3090 res = res.substr(first + 4);
3093 else
3095 res = res.substr(first + 2);
3098 else
3100 res = res.substr(first + 2);
3103 nldebug("res2: %s", res.c_str());
3105 if (res[0] == 'H')
3107 nlwarning("missing response body: %s", res.c_str());
3108 return "missing response body (error code 66)";
3110 else if(res[0] == '0')
3112 // server returns an error
3113 nlwarning("server error: %s", res.substr(2).c_str());
3114 return res.substr(2);
3116 else if(res[0] == '1')
3118 // server returns ok, we have the access
3120 vector<string> line;
3121 explode(res, std::string(" "), line, true);
3123 if (line.size() < 2 || line.size() > 3)
3125 nlwarning("bad launch lines number %d != %d", line.size(), 2);
3126 return "bad launch line number (error code 14)";
3129 cookie = line[0].substr(2);
3130 addr = line[1];
3132 std::vector<std::string> patchURIs;
3134 CShard* shard = NULL;
3135 uint i;
3136 for (i=0; i<Shards.size(); ++i)
3138 if (Shards[i].ShardId == shardId)
3140 shard = &Shards[i];
3141 break;
3145 if (shard != NULL && line.size() >= 3)
3147 explode(line[2], "|", shard->PatchURIs, true);
3149 nlinfo("received %d main patch server URIs:", shard->PatchURIs.size());
3150 uint i;
3151 for (i=0; i<shard->PatchURIs.size(); ++i)
3152 nlinfo("%d: '%s'", i, shard->PatchURIs[i].c_str());
3156 else
3158 // server returns ???
3159 nlwarning("%s", res.c_str());
3160 return res;
3163 return "";
3167 /*void mainLandPatch()
3169 if (!AvailablePatchs) return;
3170 nlassert(AvailablePatchs & (1 << BGDownloader::DownloadID_MainLand)); // only handled case for now
3171 // no-op
3172 BGDownloaderWantedPatch = BGDownloader::DownloadID_MainLand;
3173 CInterfaceManager *im = CInterfaceManager::getInstance();
3174 im->initLogin();
3175 // login machine should be in the 'end' state !!
3176 nlassert(LoginSM.getCurrentState() == CLoginStateMachine::st_end);
3177 LoginSM.pushEvent(CLoginStateMachine::ev_mainland_patch);
3178 loginMainLoop(); // patch is handled in the login mainloop
3179 // there should have been a reboot there, so quit if something went wrong...
3180 release();
3181 exit(0);
3187 // ***************************************************************************
3188 // ***************************************************************************
3189 // INTRO HANDLING
3190 // ***************************************************************************
3191 // ***************************************************************************
3193 #include "init_main_loop.h"
3195 bool loginIntroSkip;
3197 void loginIntro()
3199 // Display of nevrax logo is done at init time (see init.cpp) just before addSearchPath (second one)
3200 for (uint i = 0; i < 1; i++) // previously display nevrax then nvidia
3202 if (i != 0)
3204 beginLoading(IntroNVidia);
3205 string nmsg("");
3206 ProgressBar.newMessage (nmsg);
3209 Driver->AsyncListener.reset();
3210 updateClientTime();
3211 CInputHandlerManager::getInstance()->pumpEventsNoIM();
3212 updateClientTime();
3214 loginIntroSkip = false;
3216 sint64 CurTime = T0;
3218 while (loginIntroSkip == false)
3220 updateClientTime();
3221 if ((T0 - CurTime) > 5000) // 5s before quiting
3222 break;
3223 // Update messages
3224 CInputHandlerManager::getInstance()->pumpEventsNoIM();
3226 // Exit ?
3227 if (Driver->AsyncListener.isKeyPushed (KeyESCAPE) || Driver->AsyncListener.isKeyPushed (KeyRETURN) ||
3228 Driver->AsyncListener.isKeyPushed (KeySPACE))
3229 break;
3231 const string nmsg("");
3232 ProgressBar.newMessage (nmsg);
3233 IngameDbMngr.flushObserverCalls();
3234 NLGUI::CDBManager::getInstance()->flushObserverCalls();
3237 beginLoading(StartBackground);
3238 ProgressBar.finish();