Merge branch '138-toggle-free-look-with-hotkey' into main/gingo-test
[ryzomcore.git] / ryzom / client / src / login.cpp
bloba82e76d32adc5c785b6c0e55f17916eff11520dc
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 url = sParams;
1892 if(sParams != "cfg_ConditionsTermsURL" && sParams != "cfg_NamingPolicyURL")
1894 // modify existing languages
1896 // old site
1897 string::size_type pos_lang = url.find("/en/");
1899 // or new forums
1900 if (pos_lang == string::npos)
1901 pos_lang = url.find("=en#");
1903 if (pos_lang != string::npos)
1905 url.replace(pos_lang + 1, 2, ClientCfg.getHtmlLanguageCode());
1907 else
1909 // append language
1910 if (url.find('?') != string::npos)
1911 url += "&";
1912 else
1913 url += "?";
1915 url += "language=" + ClientCfg.LanguageCode;
1917 if (!LoginCustomParameters.empty())
1918 url += LoginCustomParameters;
1922 openURL(url);
1924 nlinfo("openURL %s", url.c_str());
1927 REGISTER_ACTION_HANDLER (CAHOpenURL, "open_url");
1929 static vector<UDriver::CMode> VideoModes;
1930 vector<string> StringModeList;
1931 vector<string> StringPresetList;
1932 vector< pair<string, bool> > CfgPresetList;
1933 sint CurrentMode = -1;
1934 sint CurrentPreset = -1;
1936 // ***************************************************************************
1937 class CAHInitResLod : public IActionHandler
1939 virtual void execute (CCtrlBase * /* pCaller */, const string &/* sParams */)
1941 //nlinfo("CAHInitResLod called");
1942 if (Driver == NULL) return;
1944 VideoModes.clear();
1945 StringModeList.clear();
1947 std::vector<std::string> stringFreqList;
1948 sint currentFreq;
1950 getRyzomModes(VideoModes, StringModeList, stringFreqList, CurrentMode, currentFreq);
1952 // getRyzomModes() expects empty list, so we need to insert 'Windowed' after mode list is filled
1953 StringModeList.insert(StringModeList.begin(), "uiConfigWindowed");
1955 // If the client is in windowed mode, still in windowed mode and do not change anything
1956 if (ClientCfg.Windowed)
1957 CurrentMode = 0;
1958 // If we have not found the mode so it can be an error or machine change, so propose the first available
1959 else if (CurrentMode == -1)
1960 CurrentMode = 1;
1961 // We inserted 'Windowed' as first mode, so index needs to move too
1962 else
1963 ++CurrentMode;
1965 CInterfaceManager *pIM = CInterfaceManager::getInstance();
1966 CViewText *pVT = dynamic_cast<CViewText*>(CWidgetManager::getInstance()->getElementFromId("ui:login:checkpass:content:res_value"));
1967 if (pVT != NULL)
1968 pVT->setHardText(StringModeList[CurrentMode]);
1970 StringPresetList.clear();
1971 StringPresetList.push_back("uiLodValueLow");
1972 StringPresetList.push_back("uiLodValueMedium");
1973 StringPresetList.push_back("uiLodValueNormal");
1974 StringPresetList.push_back("uiLodValueHigh");
1975 StringPresetList.push_back("uiLodValueCustom");
1976 CurrentPreset = 4; // CInterfaceDDX::CustomPreset
1978 // first indicates the preset-able cfg-variable
1979 // second indicates if its a double variable (else it's an int)
1980 CfgPresetList.clear();
1981 CfgPresetList.push_back(pair<string,bool>("LandscapeTileNear", true));
1982 CfgPresetList.push_back(pair<string,bool>("LandscapeThreshold", true));
1983 CfgPresetList.push_back(pair<string,bool>("Vision", true));
1984 CfgPresetList.push_back(pair<string,bool>("MicroVeget", false));
1985 CfgPresetList.push_back(pair<string,bool>("MicroVegetDensity", true));
1986 CfgPresetList.push_back(pair<string,bool>("FxNbMaxPoly", false));
1987 CfgPresetList.push_back(pair<string,bool>("Cloud", false));
1988 CfgPresetList.push_back(pair<string,bool>("CloudQuality", true));
1989 CfgPresetList.push_back(pair<string,bool>("CloudUpdate", false));
1990 CfgPresetList.push_back(pair<string,bool>("Shadows", false));
1991 CfgPresetList.push_back(pair<string,bool>("SkinNbMaxPoly", false));
1992 CfgPresetList.push_back(pair<string,bool>("NbMaxSkeletonNotCLod", false));
1993 CfgPresetList.push_back(pair<string,bool>("CharacterFarClip", true));
1995 CfgPresetList.push_back(pair<string,bool>("FXAA", false));
1996 CfgPresetList.push_back(pair<string,bool>("Bloom", false));
1997 CfgPresetList.push_back(pair<string,bool>("SquareBloom", false));
1998 CfgPresetList.push_back(pair<string,bool>("DensityBloom", true));
2000 // Check if all the preset-able cfg-variable are in a preset mode
2001 sint nPreset = -1;
2002 for (uint32 i = 0; i < CfgPresetList.size(); ++i)
2004 CConfigFile::CVar *cfgVarPtr = ClientCfg.ConfigFile.getVarPtr(CfgPresetList[i].first);
2005 if (cfgVarPtr == NULL) continue;
2006 // Get the preset of the variable i
2007 sint nVarPreset = 0;
2008 for (uint32 j = 0; j < 4; ++j) // CInterfaceDDX::NumPreset
2010 string sPresetName = CfgPresetList[i].first + "_ps" + toString(j);
2011 CConfigFile::CVar *presetVarPtr = ClientCfg.ConfigFile.getVarPtr(sPresetName);
2012 if(presetVarPtr)
2014 if (CfgPresetList[i].second) // Is it a double ?
2016 if (cfgVarPtr->asDouble() == presetVarPtr->asDouble())
2017 nVarPreset |= (1 << j);
2019 else
2021 if (cfgVarPtr->asInt() == presetVarPtr->asInt())
2022 nVarPreset |= (1 << j);
2027 if (nPreset == -1)
2028 nPreset = nVarPreset;
2029 else
2030 nPreset &= nVarPreset;
2032 if (nPreset == 0)
2033 break;
2036 if (nPreset != 0)
2038 if (nPreset&1) CurrentPreset = 0;
2039 else if (nPreset&2) CurrentPreset = 1;
2040 else if (nPreset&4) CurrentPreset = 2;
2041 else if (nPreset&8) CurrentPreset = 3;
2044 pVT = dynamic_cast<CViewText*>(CWidgetManager::getInstance()->getElementFromId("ui:login:checkpass:content:lod_value"));
2045 if (pVT != NULL)
2046 pVT->setHardText(StringPresetList[CurrentPreset]);
2049 REGISTER_ACTION_HANDLER (CAHInitResLod, "init_res_lod");
2051 // ***************************************************************************
2052 class CAHMoreRes : public IActionHandler
2054 virtual void execute (CCtrlBase * /* pCaller */, const string &/* sParams */)
2056 nlinfo("CAHMoreRes called");
2057 if (CurrentMode < ((sint)StringModeList.size()-1))
2058 CurrentMode++;
2059 CInterfaceManager *pIM = CInterfaceManager::getInstance();
2060 CViewText *pVT = dynamic_cast<CViewText*>(CWidgetManager::getInstance()->getElementFromId("ui:login:checkpass:content:res_value"));
2061 if (pVT != NULL)
2062 pVT->setHardText(StringModeList[CurrentMode]);
2065 REGISTER_ACTION_HANDLER (CAHMoreRes, "more_res");
2067 // ***************************************************************************
2068 class CAHLessRes : public IActionHandler
2070 virtual void execute (CCtrlBase * /* pCaller */, const string &/* sParams */)
2072 nlinfo("CAHLessRes called");
2073 if (CurrentMode > 0)
2074 CurrentMode--;
2075 CInterfaceManager *pIM = CInterfaceManager::getInstance();
2076 CViewText *pVT = dynamic_cast<CViewText*>(CWidgetManager::getInstance()->getElementFromId("ui:login:checkpass:content:res_value"));
2077 if (pVT != NULL)
2078 pVT->setHardText(StringModeList[CurrentMode]);
2081 REGISTER_ACTION_HANDLER (CAHLessRes, "less_res");
2083 // ***************************************************************************
2084 class CAHMoreLod : public IActionHandler
2086 virtual void execute (CCtrlBase * /* pCaller */, const string &/* sParams */)
2088 nlinfo("CAHMoreLod called");
2089 if (CurrentPreset < ((sint)StringPresetList.size()-1))
2090 CurrentPreset++;
2091 CInterfaceManager *pIM = CInterfaceManager::getInstance();
2092 CViewText *pVT = dynamic_cast<CViewText*>(CWidgetManager::getInstance()->getElementFromId("ui:login:checkpass:content:lod_value"));
2093 if (pVT != NULL)
2094 pVT->setHardText(StringPresetList[CurrentPreset]);
2097 REGISTER_ACTION_HANDLER (CAHMoreLod, "more_lod");
2099 // ***************************************************************************
2100 class CAHLessLod : public IActionHandler
2102 virtual void execute (CCtrlBase * /* pCaller */, const string &/* sParams */)
2104 nlinfo("CAHMoreLod called");
2105 if (CurrentPreset > 0)
2106 CurrentPreset--;
2107 CInterfaceManager *pIM = CInterfaceManager::getInstance();
2108 CViewText *pVT = dynamic_cast<CViewText*>(CWidgetManager::getInstance()->getElementFromId("ui:login:checkpass:content:lod_value"));
2109 if (pVT != NULL)
2110 pVT->setHardText(StringPresetList[CurrentPreset]);
2113 REGISTER_ACTION_HANDLER (CAHLessLod, "less_lod");
2115 // ***************************************************************************
2116 // TODO: remove resolution change from login screen
2117 class CAHUninitResLod : public IActionHandler
2119 virtual void execute (CCtrlBase * /* pCaller */, const string &/* sParams */)
2121 //nlinfo("CAHUninitResLod called");
2123 // If the mode requested is a windowed mode do nothnig
2124 if (CurrentMode == 0)
2126 ClientCfg.Windowed = true;
2127 ClientCfg.writeBool("FullScreen", false);
2129 else
2131 ClientCfg.Windowed = false;
2132 // Get W, H
2133 uint16 w = 0, h = 0;
2135 string vidModeStr = StringModeList[CurrentMode];
2136 string tmp = vidModeStr.substr(0,vidModeStr.find('x')-1);
2137 fromString(tmp, w);
2138 tmp = vidModeStr.substr(vidModeStr.find('x')+2,vidModeStr.size());
2139 fromString(tmp, h);
2141 ClientCfg.Width = w;
2142 ClientCfg.Height = h;
2144 ClientCfg.writeBool("FullScreen", true);
2145 ClientCfg.writeInt("Width", w);
2146 ClientCfg.writeInt("Height", h);
2149 if (CurrentPreset != 4) // CInterfaceDDX::CustomPreset
2151 for (uint32 i = 0; i < CfgPresetList.size(); ++i)
2153 CConfigFile::CVar *cfgVarPtr = ClientCfg.ConfigFile.getVarPtr(CfgPresetList[i].first);
2154 if (cfgVarPtr == NULL) continue;
2156 string sPresetName = CfgPresetList[i].first + "_ps" + toString(CurrentPreset);
2157 CConfigFile::CVar *presetVarPtr = ClientCfg.ConfigFile.getVarPtr(sPresetName);
2158 if(presetVarPtr)
2160 if (CfgPresetList[i].second) // Is it a double ?
2161 cfgVarPtr->setAsDouble(presetVarPtr->asDouble());
2162 else
2163 cfgVarPtr->setAsInt(presetVarPtr->asInt());
2168 // **** Save the config
2169 if (ClientCfg.SaveConfig)
2170 ClientCfg.ConfigFile.save ();
2171 ClientCfg.IsInvalidated = true;
2174 REGISTER_ACTION_HANDLER (CAHUninitResLod, "uninit_res_lod");
2177 void initDataScan()
2179 CInterfaceManager *pIM = CInterfaceManager::getInstance();
2180 CPatchManager *pPM = CPatchManager::getInstance();
2182 // reset the log
2183 setDataScanLog(string());
2185 // Start Scanning
2186 pPM->startScanDataThread();
2187 NLGUI::CDBManager::getInstance()->getDbProp("UI:VARIABLES:SCREEN")->setValue32(UI_VARIABLES_SCREEN_DATASCAN);
2188 NLGUI::CDBManager::getInstance()->getDbProp("UI:VARIABLES:DATASCAN_RUNNING")->setValue32(1);
2191 // ***************************************************************************
2192 // Called after the check has been done. The page is full of optional categories that must be selected for patching
2193 class CAHOnScanDataStart : public IActionHandler
2195 virtual void execute (CCtrlBase * /* pCaller */, const string &/* Params */)
2197 nlinfo("CAHOnScanDataStart called");
2199 LoginSM.pushEvent(CLoginStateMachine::ev_data_scan);
2203 REGISTER_ACTION_HANDLER (CAHOnScanDataStart, "on_scan_data_start");
2205 // ***************************************************************************
2206 // Called when the user cancel the scan
2207 class CAHOnScanDataClose : public IActionHandler
2209 virtual void execute (CCtrlBase * /* pCaller */, const string &/* Params */)
2211 nlinfo("CAHOnScanDataClose called");
2212 CInterfaceManager *pIM = CInterfaceManager::getInstance();
2213 CPatchManager *pPM = CPatchManager::getInstance();
2215 // if the scan is still running
2216 if(NLGUI::CDBManager::getInstance()->getDbProp("UI:VARIABLES:DATASCAN_RUNNING")->getValue32()!=0)
2218 // request to stop the thread
2219 pPM->askForStopScanDataThread();
2221 // Log.
2222 setDataScanState(CI18N::get("uiCancelingScanData"));
2224 else
2226 LoginSM.pushEvent(CLoginStateMachine::ev_close_data_scan);
2227 // Come Back to Login Screen.
2228 // NLGUI::CDBManager::getInstance()->getDbProp("UI:VARIABLES:SCREEN")->setValue32(UI_VARIABLES_SCREEN_CHECKPASS);
2230 // // Give focus to password if some login entered
2231 // string loginEB;
2232 // CGroupEditBox *pGEB = dynamic_cast<CGroupEditBox*>(CWidgetManager::getInstance()->getElementFromId(CTRL_EDITBOX_LOGIN));
2233 // if(pGEB)
2234 // loginEB= pGEB->getInputStringAsStdString();
2235 // // if none entered
2236 // if (loginEB.empty())
2237 // CAHManager::getInstance()->runActionHandler("set_keyboard_focus", NULL, "target=" CTRL_EDITBOX_LOGIN "|select_all=false");
2238 // else
2239 // CAHManager::getInstance()->runActionHandler("set_keyboard_focus", NULL, "target=" CTRL_EDITBOX_PASSWORD "|select_all=false");
2243 REGISTER_ACTION_HANDLER (CAHOnScanDataClose, "on_scan_data_close");
2245 // ***************************************************************************
2247 inline string parseTooltip(const string & initString, const string & tagName)
2249 string tooltip;
2251 string::size_type tooltipPos = initString.find(tagName);
2252 if(tooltipPos != string::npos)
2254 tooltip = initString.substr(tooltipPos);
2256 // start of tooltip
2257 tooltip = tooltip.substr(tooltip.find(">")+1);
2259 // end of tooltip
2260 tooltip = tooltip.substr(0, tooltip.find("<"));
2263 return tooltip;
2266 inline string parseCommentError(const string & initString, const string & tagName)
2268 string error;
2270 string::size_type errorPos = initString.find(tagName);
2271 if(errorPos != string::npos)
2273 error = initString.substr(errorPos);
2275 // start of comment
2276 error = error.substr(error.find(">")+1);
2278 // end of comment
2279 error = error.substr(0, error.find("<"));
2282 return error;
2285 bool initCreateAccount()
2287 CInterfaceManager *pIM = CInterfaceManager::getInstance();
2289 // reset UI
2290 CInterfaceGroup *createAccountUI = dynamic_cast<CInterfaceGroup*>(CWidgetManager::getInstance()->getElementFromId("ui:login:create_account"));
2291 if(createAccountUI)
2293 // show "submit interface", hide "login interface"
2294 CInterfaceGroup * grSubmit = dynamic_cast<CInterfaceGroup*>(createAccountUI->findFromShortId("submit_gr"));
2295 if(grSubmit)
2296 grSubmit->setActive(true);
2298 CInterfaceGroup * grLogin = dynamic_cast<CInterfaceGroup*>(createAccountUI->findFromShortId("login_gr"));
2299 if(grLogin)
2300 grLogin->setActive(false);
2302 // empty edit boxes
2303 std::vector< std::string > editBoxes(4);
2304 editBoxes[0] = "eb_login";
2305 editBoxes[1] = "eb_password";
2306 editBoxes[2] = "eb_confirm_password";
2307 editBoxes[3] = "eb_email";
2309 for(uint i=0; i<editBoxes.size(); i++)
2311 CGroupEditBox * eb = dynamic_cast<CGroupEditBox*>(createAccountUI->findFromShortId(editBoxes[i] + ":eb"));
2312 if(eb)
2313 eb->setInputString(std::string());
2316 // conditions button
2317 CCtrlBaseButton * but = dynamic_cast<CCtrlBaseButton*>(createAccountUI->findFromShortId("accept_cond"));
2318 if(but)
2319 but->setPushed(true);
2321 // get rules from url
2322 string url = ClientCfg.CreateAccountURL;
2323 CPatchManager *pPM = CPatchManager::getInstance();
2325 if (!CurlHttpClient.connect(url))
2327 nlwarning("Can't connect");
2328 return false;
2331 std::string lang = ClientCfg.LanguageCode;
2332 if(lang=="wk") lang = "uk";
2334 CurlHttpClient.verifyServer(true); // set this to false if you need to connect to the test environment
2336 std::string params = "language=" + lang;
2338 if (!LoginCustomParameters.empty())
2339 params += LoginCustomParameters;
2341 if(!CurlHttpClient.sendGet(url, params, pPM->isVerboseLog()))
2343 string errorMessage("Can't send (error code 60)");
2344 errorMessageBox(errorMessage);
2345 nlwarning(errorMessage.c_str());
2346 return false;
2349 string res;
2350 if(!CurlHttpClient.receive(res, pPM->isVerboseLog()))
2352 string errorMessage("Can't receive (error code 61)");
2353 errorMessageBox(errorMessage);
2354 nlwarning(errorMessage.c_str());
2355 return false;
2358 if(res.empty())
2360 string errorMessage("Empty result (error code 13)");
2361 errorMessageBox(errorMessage);
2362 nlwarning(errorMessage.c_str());
2363 return false;
2366 CurlHttpClient.disconnect();
2368 // initialize rules in interface
2369 std::vector< std::pair< std::string , std::string > > rules(5);
2370 rules[0] = std::pair<std::string , std::string>("rules_login", "id=tooltip-Username");
2371 rules[1] = std::pair<std::string , std::string>("rules_password", "id=tooltip-Password");
2372 rules[2] = std::pair<std::string , std::string>("rules_password_conf", "id=tooltip-ConfirmPass");
2373 rules[3] = std::pair<std::string , std::string>("rules_email", "id=tooltip-Email");
2374 rules[4] = std::pair<std::string , std::string>("rules_conditions", "id=tooltip-TaC");
2376 for(uint i=0; i<rules.size(); i++)
2378 CViewText * text = dynamic_cast<CViewText*>(createAccountUI->findFromShortId(rules[i].first));
2379 if(text)
2381 string tooltip = parseTooltip(res, rules[i].second);
2382 text->setHardText(tooltip);
2383 text->setActive(false);
2387 // welcome text
2388 CViewText * text = dynamic_cast<CViewText*>(createAccountUI->findFromShortId("errors_list"));
2389 if(text)
2391 text->setHardText(toString(CI18N::get("uiCreateAccountWelcome")));
2392 text->setColor(CRGBA(255, 255, 255, 255));
2394 CInterfaceGroup * group = dynamic_cast<CInterfaceGroup*>(createAccountUI->findFromShortId("erros_txt"));
2395 if(group)
2397 group->updateCoords();
2399 CInterfaceGroup * groupScroll = dynamic_cast<CInterfaceGroup*>(createAccountUI->findFromShortId("err_back_scrollbar"));
2400 if(groupScroll) groupScroll->setActive(group->getHReal() > group->getMaxHReal());
2401 CCtrlScroll * scroll = dynamic_cast<CCtrlScroll*>(createAccountUI->findFromShortId("err_scroll_bar"));
2402 if(scroll)
2403 scroll->setTrackPos(scroll->getHReal());
2407 // hide rules
2408 CInterfaceGroup * rulesGr = dynamic_cast<CInterfaceGroup*>(createAccountUI->findFromShortId("rules_gr"));
2409 if(rulesGr)
2410 rulesGr->setActive(false);
2412 // must be done after hide rules
2413 CAHManager::getInstance()->runActionHandler("set_keyboard_focus", NULL, "target=" CTRL_EDITBOX_CREATEACCOUNT_LOGIN "|select_all=false");
2417 NLGUI::CDBManager::getInstance()->getDbProp("UI:VARIABLES:SCREEN")->setValue32(UI_VARIABLES_SCREEN_CREATE_ACCOUNT);
2419 return true;
2422 // ***************************************************************************
2423 // Called when the user focus one of the edit boxes during the account creation
2424 class CAHCreateAccountRules : public IActionHandler
2426 virtual void execute (CCtrlBase * /* pCaller */, const string &Params)
2428 nlinfo("CAHCreateAccountRules called");
2430 CInterfaceManager *pIM = CInterfaceManager::getInstance();
2431 CInterfaceGroup *createAccountUI = dynamic_cast<CInterfaceGroup*>(CWidgetManager::getInstance()->getElementFromId("ui:login:create_account"));
2432 if(createAccountUI)
2434 CInterfaceGroup * rulesGr = dynamic_cast<CInterfaceGroup*>(createAccountUI->findFromShortId("rules_gr"));
2435 if(rulesGr)
2436 rulesGr->setActive(false);
2438 std::vector< std::string > rules(4);
2439 rules[0] = "rules_login";
2440 rules[1] = "rules_password";
2441 rules[2] = "rules_password_conf";
2442 rules[3] = "rules_email";
2444 for(uint i=0; i<rules.size(); i++)
2446 CViewText * text = dynamic_cast<CViewText*>(createAccountUI->findFromShortId(rules[i]));
2447 if(text)
2449 text->setActive(Params==rules[i]);
2450 if(Params==rules[i])
2452 if(rulesGr)
2453 rulesGr->setActive(!text->getText().empty());
2460 REGISTER_ACTION_HANDLER (CAHCreateAccountRules, "create_account_rules");
2462 // ***************************************************************************
2463 // Called when the user choose the account creation
2464 class CAHOnCreateAccount : public IActionHandler
2466 virtual void execute (CCtrlBase * /* pCaller */, const string &/* Params */)
2468 nlinfo("CAHOnCreateAccount called");
2470 LoginSM.pushEvent(CLoginStateMachine::ev_create_account);
2473 REGISTER_ACTION_HANDLER (CAHOnCreateAccount, "on_create_account");
2475 // ***************************************************************************
2476 // Called when the user submit the account creation
2477 class CAHOnCreateAccountSubmit : public IActionHandler
2479 virtual void execute (CCtrlBase * /* pCaller */, const string &/* Params */)
2481 nlinfo("CAHOnCreateAccountSubmit called");
2483 CInterfaceManager *pIM = CInterfaceManager::getInstance();
2485 CInterfaceGroup *createAccountUI = dynamic_cast<CInterfaceGroup*>(CWidgetManager::getInstance()->getElementFromId("ui:login:create_account"));
2486 if(createAccountUI)
2488 // recover data from UI
2489 std::vector< std::string > editBoxes(4);
2490 editBoxes[0] = "eb_login";
2491 editBoxes[1] = "eb_password";
2492 editBoxes[2] = "eb_confirm_password";
2493 editBoxes[3] = "eb_email";
2494 std::vector< std::string > results(4);
2496 for(uint i=0; i<editBoxes.size(); i++)
2498 CGroupEditBox * eb = dynamic_cast<CGroupEditBox*>(createAccountUI->findFromShortId(editBoxes[i] + ":eb"));
2499 if(eb)
2500 results[i] = eb->getInputString();
2503 // text
2504 CViewText * text = dynamic_cast<CViewText*>(createAccountUI->findFromShortId("email_adress"));
2505 if(text)
2506 text->setHardText(results[3]);
2508 // conditions button
2509 bool conditionsPushed = false;
2510 CCtrlBaseButton * but = dynamic_cast<CCtrlBaseButton*>(createAccountUI->findFromShortId("accept_cond"));
2511 if(but)
2512 conditionsPushed = !but->getPushed();
2514 string url = ClientCfg.CreateAccountURL;
2515 CPatchManager *pPM = CPatchManager::getInstance();
2517 if (!CurlHttpClient.connect(url))
2519 string errorMessage("Can't connect");
2520 errorMessageBox(errorMessage);
2521 nlwarning(errorMessage.c_str());
2522 return;
2525 std::string params = "Username=" + results[0] + "&Password=" + results[1]
2526 + "&ConfirmPass=" + results[2] + "&Email=" + results[3];
2528 if(conditionsPushed)
2529 params += "&TaC=1";
2531 if (!LoginCustomParameters.empty())
2532 params += LoginCustomParameters;
2534 std::string md5 = results[0] + results[1] + "" + results[3];
2535 md5 = NLMISC::getMD5((uint8*)md5.data(), (uint32)md5.size()).toString();
2537 params += "&SC=" + md5;
2538 std::string lang = ClientCfg.LanguageCode;
2539 if(lang=="wk") lang = "uk";
2540 params += "&Language=" + lang;
2542 CurlHttpClient.verifyServer(true); // set this to false if you need to connect to the test environment
2544 if(!CurlHttpClient.sendPost(url, params, pPM->isVerboseLog()))
2546 string errorMessage("Can't send (error code 60)");
2547 errorMessageBox(errorMessage);
2548 nlwarning(errorMessage.c_str());
2549 return;
2552 string res;
2553 if(!CurlHttpClient.receive(res, pPM->isVerboseLog()))
2555 string errorMessage("Can't receive (error code 61)");
2556 errorMessageBox(errorMessage);
2557 nlwarning(errorMessage.c_str());
2558 return;
2561 if(res.empty())
2563 string errorMessage("Empty result (error code 13)");
2564 errorMessageBox(errorMessage);
2565 nlwarning(errorMessage.c_str());
2566 return;
2569 CurlHttpClient.disconnect();
2571 // parse html
2572 string::size_type okPos = res.find("email_sent");
2573 if(okPos != string::npos)
2575 // show "submit interface", hide "login interface"
2576 CInterfaceGroup * grSubmit = dynamic_cast<CInterfaceGroup*>(createAccountUI->findFromShortId("submit_gr"));
2577 if(grSubmit)
2578 grSubmit->setActive(false);
2580 CInterfaceGroup * grLogin = dynamic_cast<CInterfaceGroup*>(createAccountUI->findFromShortId("login_gr"));
2581 if(grLogin)
2582 grLogin->setActive(true);
2584 else
2586 // initialize error comments in interface
2587 CViewText * text = dynamic_cast<CViewText*>(createAccountUI->findFromShortId("errors_list"));
2588 if(text)
2590 text->setColor(CRGBA(250, 30, 30, 255));
2592 std::vector< std::string > errors(5);
2593 errors[0] = "id=\"comment-Username\"";
2594 errors[1] = "id=\"comment-Password\"";
2595 errors[2] = "id=\"comment-ConfirmPass\"";
2596 errors[3] = "id=\"comment-Email\"";
2597 errors[4] = "id=\"comment-TaC\"";
2599 string error;
2600 for(uint i=0; i<errors.size(); i++)
2602 string comment = parseCommentError(res, errors[i]);
2603 if(!comment.empty())
2604 error += "- " + comment + "\n";
2607 text->setHardText(error);
2609 CInterfaceGroup * group = dynamic_cast<CInterfaceGroup*>(createAccountUI->findFromShortId("erros_txt"));
2610 if(group)
2612 group->updateCoords();
2614 CInterfaceGroup * groupScroll = dynamic_cast<CInterfaceGroup*>(createAccountUI->findFromShortId("err_back_scrollbar"));
2615 if(groupScroll) groupScroll->setActive(group->getHReal() > group->getMaxHReal());
2616 CCtrlScroll * scroll = dynamic_cast<CCtrlScroll*>(createAccountUI->findFromShortId("err_scroll_bar"));
2617 if(scroll)
2618 scroll->setTrackPos(scroll->getHReal());
2625 REGISTER_ACTION_HANDLER (CAHOnCreateAccountSubmit, "on_create_account_submit");
2627 // ***************************************************************************
2628 // Called when the user cancel the account creation
2629 class CAHOnCreateAccountClose : public IActionHandler
2631 virtual void execute (CCtrlBase * /* pCaller */, const string &/* Params */)
2633 nlinfo("CAHOnCreateAccountClose called");
2635 LoginSM.pushEvent(CLoginStateMachine::ev_close_create_account);
2638 REGISTER_ACTION_HANDLER (CAHOnCreateAccountClose, "on_create_account_close");
2640 // ***************************************************************************
2641 class CAHCreateAccountLogin : public IActionHandler
2643 virtual void execute (CCtrlBase * /* pCaller */, const string &/* Params */)
2645 nlinfo("CAHCreateAccountLogin called");
2647 CInterfaceManager *pIM = CInterfaceManager::getInstance();
2649 CInterfaceGroup *createAccountUI = dynamic_cast<CInterfaceGroup*>(CWidgetManager::getInstance()->getElementFromId("ui:login:create_account"));
2650 if(createAccountUI)
2652 CGroupEditBox * eb = dynamic_cast<CGroupEditBox*>(createAccountUI->findFromShortId("eb_login:eb"));
2653 if(eb)
2654 LoginLogin = eb->getInputString();
2656 eb = dynamic_cast<CGroupEditBox*>(createAccountUI->findFromShortId("eb_password:eb"));
2657 if(eb)
2658 LoginPassword = eb->getInputString();
2660 onlogin(false);
2664 REGISTER_ACTION_HANDLER (CAHCreateAccountLogin, "create_account_login");
2666 // ***************************************************************************
2667 // Called by html embeded lua script
2668 class CAHOnConnectToShard: public IActionHandler
2670 virtual void execute (CCtrlBase * /* pCaller */, const string &Params)
2672 // warning : pCaller is null when event come from lua scrip embeded in HTML
2673 Cookie = getParam(Params, "cookie");
2674 FSAddr = getParam(Params, "fsAddr");
2676 // replace the '_' with '|' in the cookie string
2677 for (uint i=0; i<Cookie.size(); ++i)
2679 if (Cookie[i] == '_')
2680 Cookie[i] = '|';
2683 setLoginFinished( true );
2684 loginOK = true;
2686 LoginSM.pushEvent(CLoginStateMachine::ev_connect);
2689 REGISTER_ACTION_HANDLER (CAHOnConnectToShard, "on_connect_to_shard");
2691 // ***************************************************************************
2692 // Called to return to login screen in case of error
2693 class CAHOnBackToLogin: public IActionHandler
2695 virtual void execute (CCtrlBase * /* pCaller */, const string &/* Params */)
2697 setLoginFinished( false );
2698 loginOK = false;
2699 LoginSM.pushEvent(CLoginStateMachine::ev_relog);
2701 // CInterfaceManager *pIM = CInterfaceManager::getInstance();
2702 // // need to reset password and current screen
2703 // NLGUI::CDBManager::getInstance()->getDbProp("UI:VARIABLES:SCREEN")->setValue32(UI_VARIABLES_SCREEN_CHECKPASS);
2706 REGISTER_ACTION_HANDLER (CAHOnBackToLogin, "on_back_to_login");
2708 // ***************************************************************************
2709 // ***************************************************************************
2710 // ***************************************************************************
2711 // NETWORK CONNECTION
2712 // ***************************************************************************
2713 // ***************************************************************************
2714 // ***************************************************************************
2717 // ***************************************************************************
2718 string checkLogin(const string &login, const string &password, const string &clientApp, const std::string &customParameters)
2720 CPatchManager *pPM = CPatchManager::getInstance();
2721 Shards.clear();
2723 if(ClientCfg.ConfigFile.exists("VerboseLog"))
2724 pPM->setVerboseLog(ClientCfg.ConfigFile.getVar("VerboseLog").asInt() == 1);
2725 if(pPM->isVerboseLog()) nlinfo("Using verbose log mode");
2727 if(!HttpClient.connectToLogin())
2728 return "Can't connect (error code 1)";
2730 if(pPM->isVerboseLog()) nlinfo("Connected");
2732 string res;
2734 std::string url = ClientCfg.ConfigFile.getVar("StartupHost").asString() + ClientCfg.ConfigFile.getVar("StartupPage").asString();
2736 // don't use login with alt method
2737 if (!login.empty())
2739 // ask server for salt
2740 if(!HttpClient.sendGet(url + "?cmd=ask&cp=2&login=" + login + "&lg=" + ClientCfg.LanguageCode, "", pPM->isVerboseLog()))
2741 return std::string("Can't send (error code 60) ") + HttpClient.lastError();
2743 if(pPM->isVerboseLog()) nlinfo("Sent request for password salt");
2745 if(!HttpClient.receive(res, pPM->isVerboseLog()))
2746 return "Can't receive (error code 61)";
2748 if(pPM->isVerboseLog()) nlinfo("Received request login check");
2750 if(res.empty())
2751 return "Empty answer from server (error code 62)";
2753 size_t first = res.find("\n\n");
2754 if (first == std::string::npos)
2756 first = res.find("\r\r");
2757 if (first == std::string::npos)
2759 first = res.find("\r\n\r\n");
2760 if (first != std::string::npos)
2762 res = res.substr(first + 4);
2765 else
2767 res = res.substr(first + 2);
2770 else
2772 res = res.substr(first + 2);
2775 nldebug("res1: %s", res.c_str());
2777 if (res[0] == 'H')
2779 nlwarning("missing response body: %s", res.c_str());
2780 return "missing response body (error code 64)";
2782 else if(res[0] == '0')
2784 // server returns an error
2785 nlwarning("server error: %s", res.substr(2).c_str());
2786 return res.substr(2);
2788 else if(res[0] == '1')
2790 Salt = res.substr(2);
2792 else
2794 // server returns ???
2795 nlwarning("%s", res.c_str());
2796 return res;
2799 // send login + crypted password + client app and cp=2 (as crypted password)
2800 if(!HttpClient.connectToLogin())
2801 return "Can't connect (error code 63)";
2803 if(pPM->isVerboseLog()) nlinfo("Connected");
2806 if (ClientCfg.R2Mode)
2808 // R2 login sequence
2810 if (!login.empty())
2812 std::string cryptedPassword = CCrypt::crypt(password, Salt);
2814 if(!HttpClient.sendGet(url + "?cmd=login&login=" + login + "&password=" + cryptedPassword + "&clientApplication=" + clientApp + "&cp=2" + "&lg=" + ClientCfg.LanguageCode + customParameters))
2815 return std::string("Can't send (error code 2) ") + HttpClient.lastError();
2817 else
2819 // don't send login and password if empty
2820 if(!HttpClient.sendGet(url + "?cmd=login&clientApplication=" + clientApp + "&cp=2" + "&lg=" + ClientCfg.LanguageCode + customParameters))
2821 return std::string("Can't send (error code 2) ") + HttpClient.lastError();
2824 // the response should contains the result code and the cookie value
2825 if(pPM->isVerboseLog()) nlinfo("Sent request login check");
2827 if(!HttpClient.receive(res, pPM->isVerboseLog()))
2828 return "Can't receive (error code 3)";
2830 if(pPM->isVerboseLog()) nlinfo("Received request login check");
2832 if(res.empty())
2833 return "Empty answer from server (error code 4)";
2835 size_t first = res.find("\n\n");
2836 if (first == std::string::npos)
2838 first = res.find("\r\r");
2839 if (first == std::string::npos)
2841 first = res.find("\r\n\r\n");
2842 if (first != std::string::npos)
2844 res = res.substr(first + 4);
2847 else
2849 res = res.substr(first + 2);
2852 else
2854 res = res.substr(first + 2);
2857 nldebug("res2: %s", res.c_str());
2859 if (res[0] == 'H')
2861 nlwarning("missing response body: %s", res.c_str());
2862 return "missing response body (error code 65)";
2864 else if(res[0] == '0')
2866 // server returns an error
2867 nlwarning("server error: %s", res.substr(2).c_str());
2868 return res.substr(2);
2870 else if(res[0] == '1')
2872 //nlwarning(res.c_str());
2873 vector<string> lines;
2874 explode(res, std::string("\n"), lines, false);
2875 if (lines.size() != 2)
2877 return toString("Invalid server return, found %u lines, want 2", lines.size());
2880 vector<string> parts;
2881 explode(lines[0], std::string("#"), parts, false);
2882 if (parts.size() < 5)
2883 return "Invalid server return, missing cookie and/or Ring URLs";
2885 // server returns ok, we have the cookie
2887 // store the cookie value and FS address for next page request
2888 CurrentCookie = parts[1];
2889 Cookie = CurrentCookie;
2890 FSAddr = parts[2];
2892 // store the ring startup page
2893 RingMainURL = parts[3];
2894 FarTP.setURLBase(parts[4]);
2896 if(parts.size() >= 6 && parts[5] == "1")
2898 // we want stats
2899 extern bool startStat;
2900 startStat = true;
2903 // parse the second line (contains the domain info)
2904 parts.clear();
2905 explode(lines[1], std::string("#"), parts, false);
2906 if (parts.size() < 3)
2907 return "Invalid server return, missing patch URLs";
2909 R2ServerVersion = parts[0].c_str();
2910 R2BackupPatchURL = parts[1];
2911 explode(parts[2], std::string(" "), R2PatchURLs, true);
2913 else
2915 // unexpected content
2916 #if !FINAL_VERSION
2917 string ret = toString("DEV : Invalid server return, missing return code in \n%s", res.c_str());
2918 return ret;
2919 #else
2920 return "Invalid server return, missing return code";
2921 #endif
2925 else
2927 // standard ryzom login sequence
2928 std::string cryptedPassword = CCrypt::crypt(password, Salt);
2930 if(!HttpClient.sendGet(url + "?login=" + login + "&password=" + cryptedPassword + "&clientApplication=" + clientApp + "&cp=2"))
2931 return std::string("Can't send (error code 2) ") + HttpClient.lastError();
2933 if(!send(ClientCfg.ConfigFile.getVar("StartupPage").asString()+"?login="+login+"&password="+password+"&clientApplication="+clientApp))
2934 return "Can't send (error code 2)";
2936 if(pPM->isVerboseLog()) nlinfo("Sent request login check");
2938 if(!HttpClient.receive(res, pPM->isVerboseLog()))
2939 return "Can't receive (error code 3)";
2941 if(pPM->isVerboseLog()) nlinfo("Received request login check");
2943 if(res.empty())
2944 return "Empty answer from server (error code 4)";
2946 size_t first = res.find("\n\n");
2947 if (first == std::string::npos)
2949 first = res.find("\r\r");
2950 if (first == std::string::npos)
2952 first = res.find("\r\n\r\n");
2953 if (first != std::string::npos)
2955 res = res.substr(first + 4);
2958 else
2960 res = res.substr(first + 2);
2963 else
2965 res = res.substr(first + 2);
2968 nldebug("res2: %s", res.c_str());
2970 if (res[0] == 'H')
2972 nlwarning("missing response body: %s", res.c_str());
2973 return "missing response body (error code 66)";
2975 else if(res[0] == '0')
2977 // server returns an error
2978 nlwarning("server error: %s", res.substr(2).c_str());
2979 return res.substr(2);
2981 else if(res[0] == '1')
2983 // server returns ok, we have the list of shard
2984 uint nbs;
2985 fromString(res.substr(2), nbs);
2986 vector<string> lines;
2988 explode(res, std::string("\n"), lines, true);
2990 if(pPM->isVerboseLog())
2992 nlinfo ("Exploded, with nl, %u res", (uint)lines.size());
2993 /* for (uint i = 0; i < lines.size(); i++)
2995 nlinfo (" > '%s'", lines[i].c_str());
2999 if(lines.size() != nbs+1)
3001 nlwarning("bad shard lines number %u != %d", (uint)lines.size(), nbs+1);
3002 nlwarning("'%s'", res.c_str());
3003 return "bad lines numbers (error code 5)";
3006 for(uint i = 1; i < lines.size(); i++)
3008 vector<string> res;
3009 explode(lines[i], std::string("|"), res);
3011 if(pPM->isVerboseLog())
3013 nlinfo ("Exploded with '%s', %u res", "|", (uint)res.size());
3014 /* for (uint i = 0; i < res.size(); i++)
3016 nlinfo (" > '%s'", res[i].c_str());
3020 if (res.size() < 7 && res.size() > 8)
3022 nlwarning("bad | numbers %u != %d", (uint)res.size(), 8);
3023 nlwarning("'%s'", lines[i].c_str());
3024 return "bad pipe numbers (error code 6)";
3026 bool online;
3027 fromString(res[1], online);
3028 uint32 shardId;
3029 fromString(res[2], shardId);
3030 uint32 nbPlayers;
3031 fromString(res[4], nbPlayers);
3032 Shards.push_back(CShard(res[0], online, shardId, res[3], nbPlayers, res[5], res[6]));
3033 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());
3034 if (res.size() == 8)
3036 explode(res[7], std::string(" "), Shards.back().PatchURIs);
3040 else
3042 // server returns ???
3043 nlwarning("%s", res.c_str());
3044 return res;
3048 return "";
3051 // ***************************************************************************
3052 string selectShard(uint32 shardId, string &cookie, string &addr)
3054 cookie.clear();
3055 addr.clear();
3057 if(!HttpClient.connectToLogin()) return "Can't connect (error code 7)";
3059 if(LoginLogin.empty()) return "Empty Login (error code 8)";
3060 if(LoginPassword.empty()) return "Empty Password (error code 9)";
3061 if(ClientApp.empty()) return "Empty Client Application (error code 10)";
3063 // send login + crypted password + client app and cp=2 (as crypted password)
3064 std::string cryptedPassword = CCrypt::crypt(LoginPassword, Salt);
3066 std::string url = ClientCfg.ConfigFile.getVar("StartupHost").asString() + ClientCfg.ConfigFile.getVar("StartupPage").asString();
3068 if(!HttpClient.sendGet(url + "?cmd=login&shardid=" + toString(shardId) + "&login=" + LoginLogin + "&password=" + cryptedPassword + "&clientApplication=" + ClientApp + "&cp=2"))
3069 return "Can't send (error code 11)";
3071 string res;
3073 CPatchManager *pPM = CPatchManager::getInstance();
3074 if(!HttpClient.receive(res, pPM->isVerboseLog()))
3075 return "Can't receive (error code 12)";
3077 if(res.empty())
3078 return "Empty result (error code 13)";
3080 size_t first = res.find("\n\n");
3081 if (first == std::string::npos)
3083 first = res.find("\r\r");
3084 if (first == std::string::npos)
3086 first = res.find("\r\n\r\n");
3087 if (first != std::string::npos)
3089 res = res.substr(first + 4);
3092 else
3094 res = res.substr(first + 2);
3097 else
3099 res = res.substr(first + 2);
3102 nldebug("res2: %s", res.c_str());
3104 if (res[0] == 'H')
3106 nlwarning("missing response body: %s", res.c_str());
3107 return "missing response body (error code 66)";
3109 else if(res[0] == '0')
3111 // server returns an error
3112 nlwarning("server error: %s", res.substr(2).c_str());
3113 return res.substr(2);
3115 else if(res[0] == '1')
3117 // server returns ok, we have the access
3119 vector<string> line;
3120 explode(res, std::string(" "), line, true);
3122 if (line.size() < 2 || line.size() > 3)
3124 nlwarning("bad launch lines number %d != %d", line.size(), 2);
3125 return "bad launch line number (error code 14)";
3128 cookie = line[0].substr(2);
3129 addr = line[1];
3131 std::vector<std::string> patchURIs;
3133 CShard* shard = NULL;
3134 uint i;
3135 for (i=0; i<Shards.size(); ++i)
3137 if (Shards[i].ShardId == shardId)
3139 shard = &Shards[i];
3140 break;
3144 if (shard != NULL && line.size() >= 3)
3146 explode(line[2], "|", shard->PatchURIs, true);
3148 nlinfo("received %d main patch server URIs:", shard->PatchURIs.size());
3149 uint i;
3150 for (i=0; i<shard->PatchURIs.size(); ++i)
3151 nlinfo("%d: '%s'", i, shard->PatchURIs[i].c_str());
3155 else
3157 // server returns ???
3158 nlwarning("%s", res.c_str());
3159 return res;
3162 return "";
3166 /*void mainLandPatch()
3168 if (!AvailablePatchs) return;
3169 nlassert(AvailablePatchs & (1 << BGDownloader::DownloadID_MainLand)); // only handled case for now
3170 // no-op
3171 BGDownloaderWantedPatch = BGDownloader::DownloadID_MainLand;
3172 CInterfaceManager *im = CInterfaceManager::getInstance();
3173 im->initLogin();
3174 // login machine should be in the 'end' state !!
3175 nlassert(LoginSM.getCurrentState() == CLoginStateMachine::st_end);
3176 LoginSM.pushEvent(CLoginStateMachine::ev_mainland_patch);
3177 loginMainLoop(); // patch is handled in the login mainloop
3178 // there should have been a reboot there, so quit if something went wrong...
3179 release();
3180 exit(0);
3186 // ***************************************************************************
3187 // ***************************************************************************
3188 // INTRO HANDLING
3189 // ***************************************************************************
3190 // ***************************************************************************
3192 #include "init_main_loop.h"
3194 bool loginIntroSkip;
3196 void loginIntro()
3198 // Display of nevrax logo is done at init time (see init.cpp) just before addSearchPath (second one)
3199 for (uint i = 0; i < 1; i++) // previously display nevrax then nvidia
3201 if (i != 0)
3203 beginLoading(IntroNVidia);
3204 string nmsg("");
3205 ProgressBar.newMessage (nmsg);
3208 Driver->AsyncListener.reset();
3209 updateClientTime();
3210 CInputHandlerManager::getInstance()->pumpEventsNoIM();
3211 updateClientTime();
3213 loginIntroSkip = false;
3215 sint64 CurTime = T0;
3217 while (loginIntroSkip == false)
3219 updateClientTime();
3220 if ((T0 - CurTime) > 5000) // 5s before quiting
3221 break;
3222 // Update messages
3223 CInputHandlerManager::getInstance()->pumpEventsNoIM();
3225 // Exit ?
3226 if (Driver->AsyncListener.isKeyPushed (KeyESCAPE) || Driver->AsyncListener.isKeyPushed (KeyRETURN) ||
3227 Driver->AsyncListener.isKeyPushed (KeySPACE))
3228 break;
3230 const string nmsg("");
3231 ProgressBar.newMessage (nmsg);
3232 IngameDbMngr.flushObserverCalls();
3233 NLGUI::CDBManager::getInstance()->flushObserverCalls();
3236 beginLoading(StartBackground);
3237 ProgressBar.finish();