Linux multi-monitor fullscreen support
[ryzomcore.git] / ryzom / client / src / login.cpp
blobda038cdd2109783d77f9d4a110ec33e03d55649e
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 return connect(ClientCfg.ConfigFile.getVar("StartupHost").asString(0))
165 && verifyServer(ClientCfg.ConfigFile.getVar("StartupVerify").asBool(0));
168 CStartupHttpClient HttpClient;
169 #endif // RY_BG_DOWNLOADER
172 // ***************************************************************************
173 #define WIN_COMBO_BOX_SELECT_MENU "ui:interface:combo_box_select_menu"
174 #define WIN_COMBO_BOX_MEASURE_MENU "ui:interface:combo_box_measure_menu"
175 #define WIN_COMBO_BOX_SELECT_MENU_OUTGAME "ui:outgame:combo_box_select_menu"
176 #define WIN_COMBO_BOX_SELECT_MENU_LOGIN "ui:login:combo_box_select_menu"
177 #define WIN_COMBO_BOX_MEASURE_MENU_LOGIN "ui:login:combo_box_measure_menu"
179 bool isLoginFinished()
181 return loginFinished;
184 void setLoginFinished( bool f )
186 loginFinished = f;
187 if( loginFinished )
189 CDBGroupComboBox::measureMenu.assign( WIN_COMBO_BOX_MEASURE_MENU );
190 CDBGroupComboBox::selectMenu.assign( WIN_COMBO_BOX_SELECT_MENU );
192 else
194 CDBGroupComboBox::measureMenu.assign( WIN_COMBO_BOX_MEASURE_MENU_LOGIN );
195 CDBGroupComboBox::selectMenu.assign( WIN_COMBO_BOX_SELECT_MENU_LOGIN );
200 // ***************************************************************************
201 // Pop a fatal error message box, giving the option to 'quit' the client, plus a help button
202 static void fatalMessageBox(const std::string &msg)
204 CInterfaceManager *im = CInterfaceManager::getInstance();
205 im->messageBoxWithHelp(msg, "ui:login", "login_quit");
208 // ***************************************************************************
209 // Pop an error message box, giving the option to go back to main menu, plus a help button
210 static void errorMessageBox(const std::string &msg)
212 CInterfaceManager *im = CInterfaceManager::getInstance();
213 im->messageBoxWithHelp(msg, "ui:login", "on_back_to_login");
216 // ***************************************************************************
217 void createOptionalCatUI()
219 CInterfaceManager *pIM = CInterfaceManager::getInstance();
220 CInterfaceGroup *pList = dynamic_cast<CInterfaceGroup*>(CWidgetManager::getInstance()->getElementFromId(GROUP_LIST_CAT));
221 if (pList == NULL)
223 nlwarning("element " GROUP_LIST_CAT " not found probably bad login_main.xml");
224 return;
227 // Update optional categories
229 CInterfaceGroup *pPrevLine = NULL;
230 for(uint i = 0; i < InfoOnPatch.OptCat.size(); i++)
232 vector< pair < string, string > > params;
233 params.clear();
234 params.push_back(pair<string,string>("id", "c"+toString(i)));
235 if (i>0)
236 params.push_back(pair<string,string>("posref", "BL TL"));
238 CInterfaceGroup *pNewLine = CWidgetManager::getInstance()->getParser()->createGroupInstance("t_cat", GROUP_LIST_CAT, params);
239 if (pNewLine != NULL)
241 CViewText *pVT = dynamic_cast<CViewText*>(pNewLine->getView("name"));
242 if (pVT != NULL) pVT->setText(InfoOnPatch.OptCat[i].Name);
243 pVT = dynamic_cast<CViewText*>(pNewLine->getView("size"));
244 if (pVT != NULL)
246 pVT->setText(BGDownloader::getWrittenSize(InfoOnPatch.OptCat[i].Size));
249 // Add to the list
250 pNewLine->setParent(pList);
251 pNewLine->setParentSize(pList);
252 pNewLine->setParentPos(pPrevLine);
253 pList->addGroup(pNewLine);
255 pPrevLine = pNewLine;
258 pList->invalidateCoords();
261 // ***************************************************************************
262 void initEula()
264 CInterfaceManager *pIM = CInterfaceManager::getInstance();
265 if (!ClientCfg.SkipEULA && CFile::fileExists(getLogDirectory() + "show_eula"))
267 NLGUI::CDBManager::getInstance()->getDbProp("UI:VARIABLES:SCREEN")->setValue32(UI_VARIABLES_SCREEN_EULA);
269 // if we display the eula, it means we make a patch so we clean the cache directory
270 // (clear cache after each patch)
271 nlinfo("Deleting cached files");
272 vector<string> cached;
273 CPath::getPathContent("cache", true, false, true, cached);
274 for(uint i = 0; i < cached.size(); i++)
275 CFile::deleteFile(cached[i]);
277 else
279 CAHManager::getInstance()->runActionHandler("accept_eula", NULL);
283 // ***************************************************************************
284 static void setDataScanLog(const std::string &text)
286 CInterfaceManager *pIM= CInterfaceManager::getInstance();
287 CViewText *pVT = dynamic_cast<CViewText*>(CWidgetManager::getInstance()->getElementFromId("ui:login:datascan:content:log_txt:log"));
288 if (pVT != NULL)
290 pVT->setText(text);
294 // ***************************************************************************
295 static void setDataScanState(const std::string &text, const std::string &progress = string())
297 CInterfaceManager *pIM= CInterfaceManager::getInstance();
298 CViewText *pVT = dynamic_cast<CViewText*>(CWidgetManager::getInstance()->getElementFromId("ui:login:datascan:content:state"));
299 if (pVT != NULL) pVT->setText(text);
301 pVT = dynamic_cast<CViewText*>(CWidgetManager::getInstance()->getElementFromId("ui:login:datascan:content:progress"));
302 if (pVT != NULL) pVT->setText(progress);
305 void initCatDisplay()
307 CInterfaceManager *pIM = CInterfaceManager::getInstance();
308 CPatchManager *pPM = CPatchManager::getInstance();
310 // Check is good now ask the player if he wants to apply the patch
311 pPM->getInfoToDisp(InfoOnPatch);
313 if ((!InfoOnPatch.NonOptCat.empty()) ||
314 (!InfoOnPatch.OptCat.empty()) ||
315 (!InfoOnPatch.ReqCat.empty()))
317 createOptionalCatUI();
318 NLGUI::CDBManager::getInstance()->getDbProp("UI:VARIABLES:SCREEN")->setValue32(UI_VARIABLES_SCREEN_CATDISP);
320 else
322 LoginSM.pushEvent(CLoginStateMachine::ev_run_patch);
323 // CAHManager::getInstance()->runActionHandler("login_patch", NULL);
327 void initReboot()
329 CInterfaceManager *pIM = CInterfaceManager::getInstance();
330 NLGUI::CDBManager::getInstance()->getDbProp("UI:VARIABLES:SCREEN")->setValue32(UI_VARIABLES_SCREEN_REBOOT);
334 // ***************************************************************************
335 static void setPatcherStateText(const std::string &baseUIPath, const std::string &str)
337 CInterfaceManager *pIM = CInterfaceManager::getInstance();
338 CViewText *pVT = dynamic_cast<CViewText*>(CWidgetManager::getInstance()->getElementFromId(baseUIPath + ":content:state"));
339 if (pVT != NULL)
341 pVT->setText(str);
345 // ***************************************************************************
346 static void setPatcherProgressText(const std::string &baseUIPath, const std::string &str)
348 CInterfaceManager *pIM = CInterfaceManager::getInstance();
349 CViewText *pVT = dynamic_cast<CViewText*>(CWidgetManager::getInstance()->getElementFromId(baseUIPath + ":content:progress"));
350 if (pVT != NULL)
352 pVT->setText(str);
356 // ***************************************************************************
357 static void updatePatchingInfoText(const std::string &baseUIPath)
359 CPatchManager *pPM = CPatchManager::getInstance();
360 #ifdef RYZOM_BG_DOWNLOADER
361 CBGDownloaderAccess &bgDownloader = CBGDownloaderAccess::getInstance();
362 if (isBGDownloadEnabled())
364 bgDownloader.update();
365 if (bgDownloader.getDownloadThreadPriority() == BGDownloader::ThreadPriority_Paused)
367 setPatcherStateText(baseUIPath, CI18N::get("uiBGD_Paused"));
368 setPatcherProgressText(baseUIPath, string());
370 else
372 setPatcherStateText(baseUIPath, bgDownloader.getCurrentMessage());
373 if (bgDownloader.getTotalFilesToGet() != 0)
375 setPatcherProgressText(baseUIPath, toString("%d/%d", (int) bgDownloader.getCurrentFilesToGet(), (int) bgDownloader.getTotalFilesToGet()));
377 else
379 setPatcherProgressText(baseUIPath, string());
383 else
384 #endif
386 string state;
387 vector<string> log;
388 if(pPM->getThreadState(state, log))
390 setPatcherStateText(baseUIPath, state);
391 if (pPM->getTotalFilesToGet() != 0)
393 setPatcherProgressText(baseUIPath, toString("%d/%d", pPM->getCurrentFilesToGet(), pPM->getTotalFilesToGet()));
395 else
397 setPatcherProgressText(baseUIPath, string());
403 // ***************************************************************************
404 // Main loop of the login step
405 void loginMainLoop()
407 CDBGroupComboBox::selectMenuOut.assign( WIN_COMBO_BOX_SELECT_MENU_OUTGAME );
408 CInterfaceManager *pIM = CInterfaceManager::getInstance();
409 CPatchManager *pPM = CPatchManager::getInstance();
411 #ifdef RYZOM_BG_DOWNLOADER
412 CBGDownloaderAccess &bgDownloader = CBGDownloaderAccess::getInstance();
413 #endif
415 bool windowBlinkDone = false;
416 bool fatalMessageBoxShown = false;
418 while (LoginSM.getCurrentState() != CLoginStateMachine::st_connect
419 && LoginSM.getCurrentState() != CLoginStateMachine::st_end
420 && LoginSM.getCurrentState() != CLoginStateMachine::st_ingame)
421 // while (loginFinished == false)
423 IngameDbMngr.flushObserverCalls();
424 NLGUI::CDBManager::getInstance()->flushObserverCalls();
426 // Update the DT T0 and T1 global variables
427 updateClientTime();
431 CInputHandlerManager::getInstance()->pumpEvents();
432 Driver->clearBuffers(CRGBA::Black);
433 Driver->setMatrixMode2D11();
435 // Update sound
436 if (SoundMngr != NULL)
437 SoundMngr->update();
439 // Interface handling & displaying
440 pIM->updateFrameEvents();
441 pIM->updateFrameViews(NULL);
442 IngameDbMngr.flushObserverCalls();
443 NLGUI::CDBManager::getInstance()->flushObserverCalls();
447 // if (::GetAsyncKeyState(VK_SPACE))
448 // {
449 // pIM->displayUIViewBBoxs("");
450 // pIM->displayUICtrlBBoxs("");
451 // pIM->displayUIGroupBBoxs("");
452 // }
454 // Force the client to sleep a bit.
455 if(ClientCfg.Sleep >= 0)
457 nlSleep(ClientCfg.Sleep);
459 // Display
460 Driver->swapBuffers();
462 // sint32 screen = NLGUI::CDBManager::getInstance()->getDbProp("UI:VARIABLES:SCREEN")->getValue32();
463 if (LoginSM.getCurrentState() == CLoginStateMachine::st_check_patch)
464 // if (screen == UI_VARIABLES_SCREEN_CHECKING) // If we are in checking mode
466 nlSleep(10); // For the checking thread
467 bool res = false;
468 BGDownloader::TTaskResult taskResult = BGDownloader::TaskResult_Unknown;
469 bool finished = false;
470 #ifdef RYZOM_BG_DOWNLOADER
471 string bgDownloaderError;
472 if (isBGDownloadEnabled())
474 finished = bgDownloader.isTaskEnded(taskResult, bgDownloaderError);
476 else
477 #endif
479 finished = pPM->isCheckThreadEnded(res);
482 if (finished)
484 setPatcherStateText("ui:login:checking", string());
485 setPatcherProgressText("ui:login:checking", string());
487 #ifdef RYZOM_BG_DOWNLOADER
488 if (isBGDownloadEnabled())
490 AvailablePatchs = bgDownloader.getAvailablePatchs();
491 #ifdef NL_OS_WINDOWS
493 // Get the window
494 HWND hWnd = Driver->getDisplay();
495 nlassert (hWnd);
496 // Show the window, unless it has been minimized, in
497 // which case we don't pop it unexpectedly
498 if (!windowBlinkDone)
500 bgDownloader.hideDownloader();
501 ShowWindow (hWnd, SW_RESTORE);
502 windowBlinkDone = true;
506 #endif
507 switch(taskResult)
509 case BGDownloader::TaskResult_Success:
510 if (AvailablePatchs & (1 << BGDownloaderWantedPatch)) // is there a patch for what we want now ?
512 LoginSM.pushEvent(CLoginStateMachine::ev_patch_needed);
514 else
516 LoginSM.pushEvent(CLoginStateMachine::ev_no_patch);
518 break;
519 case BGDownloader::TaskResult_Error:
521 if (!fatalMessageBoxShown)
523 fatalMessageBox(bgDownloaderError);
524 fatalMessageBoxShown = true;
527 break;
528 default:
529 if (!fatalMessageBoxShown)
531 fatalMessageBox(CI18N::get("uiErrChecking"));
532 fatalMessageBoxShown = true;
534 break;
538 else
539 #endif
541 if(res)
543 // Check is good now ask the player if he wants to apply the patch
544 pPM->getInfoToDisp(InfoOnPatch);
546 AvailablePatchs = InfoOnPatch.getAvailablePatchsBitfield();
548 if ((!InfoOnPatch.NonOptCat.empty()) ||
549 (!InfoOnPatch.OptCat.empty()) ||
550 (!InfoOnPatch.ReqCat.empty()))
552 LoginSM.pushEvent(CLoginStateMachine::ev_patch_needed);
553 // createOptionalCatUI();
554 // NLGUI::CDBManager::getInstance()->getDbProp("UI:VARIABLES:SCREEN")->setValue32(UI_VARIABLES_SCREEN_CATDISP);
556 else
558 LoginSM.pushEvent(CLoginStateMachine::ev_no_patch);
559 // CAHManager::getInstance()->runActionHandler("login_patch", NULL);
562 else
564 string errMsg = CI18N::get("uiErrChecking");
565 if (!pPM->getLastErrorMessage().empty())
567 errMsg = pPM->getLastErrorMessage();
569 if (!fatalMessageBoxShown)
571 fatalMessageBox(errMsg);
572 fatalMessageBoxShown = true;
577 else
579 // update interface content
580 updatePatchingInfoText("ui:login:checking");
583 // else if (screen == UI_VARIABLES_SCREEN_DATASCAN) // If we are in ScanData mode
584 else if (LoginSM.getCurrentState() == CLoginStateMachine::st_scan_data)
586 nlSleep(10); // For the checking thread
588 bool res;
589 if (pPM->isScanDataThreadEnded(res))
591 // if interface consider it was running before
592 if(NLGUI::CDBManager::getInstance()->getDbProp("UI:VARIABLES:DATASCAN_RUNNING")->getValue32()!=0)
594 // no more running
595 NLGUI::CDBManager::getInstance()->getDbProp("UI:VARIABLES:DATASCAN_RUNNING")->setValue32(0);
597 if(res)
599 // touch any file with checksum error, and get their number
600 uint numFiles= pPM->applyScanDataResult();
602 // Report result
603 if(numFiles==0)
604 setDataScanState(CI18N::get("uiScanDataSucess"));
605 else
607 string fmt= CI18N::get("uiScanDataErrors");
608 strFindReplace(fmt, "%d", toString(numFiles));
609 setDataScanState(fmt);
612 else
614 string errMsg = CI18N::get("uiErrDataScanning");
615 if (!pPM->getLastErrorMessage().empty())
617 errMsg = pPM->getLastErrorMessage();
619 pIM->messageBoxWithHelp(errMsg, "ui:login");
622 // the log may have changed
623 string dsLog;
624 if(pPM->getDataScanLog(dsLog))
625 setDataScanLog(dsLog);
628 else
630 // update inteface content
631 string state;
632 vector<string> log;
633 // get state
634 if(pPM->getThreadState(state, log))
636 // set state
637 setDataScanState(state, toString("%d/%d", pPM->getCurrentFilesToGet(), pPM->getTotalFilesToGet()));
639 // set special data scan log
640 string dsLog;
641 if(pPM->getDataScanLog(dsLog))
642 setDataScanLog(dsLog);
645 // else if (screen == UI_VARIABLES_SCREEN_PATCHING) // If we are in patching mode
646 else if (LoginSM.getCurrentState() == CLoginStateMachine::st_patch)
648 nlSleep(30); // For the patching thread
650 int currentPatchingSize;
651 int totalPatchSize;
653 #ifdef RYZOM_BG_DOWNLOADER
654 if (isBGDownloadEnabled())
656 currentPatchingSize = bgDownloader.getPatchingSize();
657 totalPatchSize = bgDownloader.getTotalSize();
658 BGDownloader::TTaskResult taskResult;
659 bool finished = false;
660 string bgDownloaderError;
661 finished = bgDownloader.isTaskEnded(taskResult, bgDownloaderError);
662 if (finished)
664 //bgDownloader.hideDownloader();
665 // restore the search paths (all bnp files were removed from CPath to allows
666 // the patcher to overwrite them)
668 // create a file to prompt eula next time
669 CFile::createEmptyFile(getLogDirectory() + "show_eula");
671 if (taskResult == BGDownloader::TaskResult_Error)
673 setPatcherStateText("ui:login:patching", string());
674 setPatcherProgressText("ui:login:patching", string());
676 if (!fatalMessageBoxShown)
678 fatalMessageBox(bgDownloaderError);
679 fatalMessageBoxShown = true;
682 else
684 bgDownloader.getPatchCompletionFlag(true /* clear flag */);
685 LoginSM.pushEvent(CLoginStateMachine::ev_close_patch);
688 else
690 updatePatchingInfoText("ui:login:patching");
693 else
694 #endif
696 totalPatchSize = TotalPatchSize;
697 currentPatchingSize = pPM->getPatchingSize();
698 bool res;
699 if (pPM->isPatchThreadEnded(res))
701 if(res)
703 LoginSM.pushEvent(CLoginStateMachine::ev_close_patch);
705 else
707 string errMsg = CI18N::get("uiErrPatchApply");
708 if (!pPM->getLastErrorMessage().empty())
710 errMsg = pPM->getLastErrorMessage();
712 if (!fatalMessageBoxShown)
714 fatalMessageBox(errMsg);
715 fatalMessageBoxShown = true;
719 else
721 updatePatchingInfoText("ui:login:patching");
725 CViewText *pVT = dynamic_cast<CViewText*>(CWidgetManager::getInstance()->getElementFromId(VIEW_TOTAL_SIZE_PATCH));
726 string sTmp;
727 sTmp = BGDownloader::getWrittenSize(currentPatchingSize);
728 sTmp += " / " + BGDownloader::getWrittenSize(totalPatchSize);
729 if (pVT != NULL) pVT->setText(sTmp);
731 // else if (screen == UI_VARIABLES_SCREEN_CATDISP) // If we are displaying patch info
732 else if (LoginSM.getCurrentState() == CLoginStateMachine::st_display_cat)
734 // Non optional stuff (non opt cat and req cat)
736 // Add req cat size : given the optional cat we determines the required cat
737 uint32 nNonOptSize = 0;
738 TotalPatchSize = 0;
739 vector<sint32> ReqCat;
740 CInterfaceGroup *pList = dynamic_cast<CInterfaceGroup*>(CWidgetManager::getInstance()->getElementFromId(GROUP_LIST_CAT));
741 if (pList != NULL)
743 for(uint i = 0; i < InfoOnPatch.OptCat.size(); i++)
745 CInterfaceGroup *pLine = pList->getGroup("c"+toString(i));
746 if (pLine != NULL)
748 CCtrlButton *pCB = dynamic_cast<CCtrlButton*>(pLine->getCtrl("on_off"));
749 if ((pCB != NULL) && (pCB->getPushed()))
751 TotalPatchSize += InfoOnPatch.OptCat[i].Size;
752 if (InfoOnPatch.OptCat[i].Req != -1)
754 uint32 j;
755 for (j = 0; j < ReqCat.size(); ++j)
756 if (ReqCat[j] == InfoOnPatch.OptCat[i].Req)
757 break;
758 // Add just once the req cat size to the non optional size
759 if (j == ReqCat.size())
761 ReqCat.push_back(InfoOnPatch.OptCat[i].Req);
762 nNonOptSize += InfoOnPatch.ReqCat[InfoOnPatch.OptCat[i].Req].Size;
770 // Add non optional cats
771 for (uint32 i = 0; i < InfoOnPatch.NonOptCat.size(); ++i)
772 nNonOptSize += InfoOnPatch.NonOptCat[i].Size;
774 TotalPatchSize += nNonOptSize;
775 // Total size of the patches is optional cats + required cat (f(optCat)) + non opt cat
777 CViewText *pVT = dynamic_cast<CViewText*>(CWidgetManager::getInstance()->getElementFromId(VIEW_TOTAL_SIZE));
778 if (pVT != NULL) pVT->setText(BGDownloader::getWrittenSize(TotalPatchSize));
780 pVT = dynamic_cast<CViewText*>(CWidgetManager::getInstance()->getElementFromId(VIEW_NON_OPTIONAL_SIZE));
781 if (pVT != NULL) pVT->setText(BGDownloader::getWrittenSize(nNonOptSize));
786 void initLoginScreen()
788 CInterfaceManager *pIM = CInterfaceManager::getInstance();
789 CPatchManager *pPM = CPatchManager::getInstance();
790 NLGUI::CDBManager::getInstance()->getDbProp("UI:VARIABLES:SCREEN")->setValue32(UI_VARIABLES_SCREEN_CHECKPASS);
791 NLGUI::CDBManager::getInstance()->getDbProp("UI:VARIABLES:DISPLAY_ACCOUNT_BUTTONS")->setValue32(ClientCfg.DisplayAccountButtons);
793 // Active inputs
794 Actions.enable(true);
795 EditActions.enable(true);
797 if(ClientCfg.ConfigFile.exists("VerboseLog"))
798 pPM->setVerboseLog(ClientCfg.ConfigFile.getVar("VerboseLog").asInt() == 1);
799 if(pPM->isVerboseLog()) nlinfo("Using verbose log mode");
801 ClientApp = ClientCfg.ConfigFile.getVar("Application").asString(0);
803 // version
804 std::string ext;
805 if (ClientApp.find("ryzom_") != string::npos)
806 ext = " (" + ClientApp.substr(6) + ")";
808 CViewText *pV = dynamic_cast<CViewText*>(CWidgetManager::getInstance()->getElementFromId("ui:login:checkpass:content:ver_value"));
809 if (pV)
810 pV->setHardText(getDisplayVersion() + (ext.empty() ? "" : ext));
812 // give priority to login specified as argument
813 string l = !LoginLogin.empty() ? LoginLogin:ClientCfg.LastLogin;
815 if(!l.empty())
817 CGroupEditBox *pGEB = dynamic_cast<CGroupEditBox*>(CWidgetManager::getInstance()->getElementFromId(CTRL_EDITBOX_LOGIN));
818 if (pGEB != NULL && (pGEB->getInputString().empty()))
820 pGEB->setInputString(l);
822 CAHManager::getInstance()->runActionHandler("set_keyboard_focus", NULL, "target=" CTRL_EDITBOX_PASSWORD "|select_all=false");
824 else
826 CAHManager::getInstance()->runActionHandler("set_keyboard_focus", NULL, "target=" CTRL_EDITBOX_LOGIN "|select_all=false");
830 CCtrlTextButton *pCB = dynamic_cast<CCtrlTextButton*>(CWidgetManager::getInstance()->getElementFromId(CTRL_BUTTON_CONNECT));
831 if (pCB != NULL) pCB->setActive(false);
833 setLoginFinished( false );
834 loginOK = false;
837 void initAutoLogin()
839 CInterfaceManager *pIM = CInterfaceManager::getInstance();
840 CGroupEditBox *pGEBLog = dynamic_cast<CGroupEditBox*>(CWidgetManager::getInstance()->getElementFromId(CTRL_EDITBOX_LOGIN));
841 CGroupEditBox *pGEBPwd = dynamic_cast<CGroupEditBox*>(CWidgetManager::getInstance()->getElementFromId(CTRL_EDITBOX_PASSWORD));
842 pGEBLog->setInputString(LoginLogin);
843 pGEBPwd->setInputString(LoginPassword);
844 CAHManager::getInstance()->runActionHandler("on_login", NULL, "");
846 if (ClientCfg.R2Mode)
848 LoginSM.pushEvent(CLoginStateMachine::ev_login_ok);
850 else
852 // Select good shard
853 ShardSelected = -1;
854 for (uint32 i = 0; i < Shards.size(); ++i)
856 if (Shards[i].ShardId == LoginShardId)
858 ShardSelected = i;
859 break;
863 if (ShardSelected == -1)
865 pIM->messageBoxWithHelp(CI18N::get("uiErrServerLost"), "ui:login");
866 LoginSM.pushEvent(CLoginStateMachine::ev_quit);
868 else
870 LoginSM.pushEvent(CLoginStateMachine::ev_login_ok);
871 // CAHManager::getInstance()->runActionHandler("login_connect_2", NULL);
876 void initAltLogin()
878 // Check the alt param
879 if (!LoginCustomParameters.empty() && LoginCustomParameters != "&dbg=1")
881 // don't use login and password for alternate login
882 string res = checkLogin("", "", ClientApp, LoginCustomParameters);
883 if (res.empty())
885 if (ClientCfg.R2Mode)
887 LoginSM.pushEvent(CLoginStateMachine::ev_login_ok);
889 else
891 // Select good shard
892 ShardSelected = -1;
893 for (uint32 i = 0; i < Shards.size(); ++i)
895 if (Shards[i].ShardId == LoginShardId)
897 ShardSelected = i;
898 break;
902 if (ShardSelected == -1)
904 CInterfaceManager *pIM = CInterfaceManager::getInstance();
905 pIM->messageBoxWithHelp(CI18N::get("uiErrServerLost"), "ui:login");
906 LoginSM.pushEvent(CLoginStateMachine::ev_quit);
908 else
910 LoginSM.pushEvent(CLoginStateMachine::ev_login_ok);
914 return;
918 // close the socket in case of error
919 HttpClient.disconnect();
921 // ignore error
922 LoginSM.pushEvent(CLoginStateMachine::ev_login_not_alt);
926 // ***************************************************************************
927 // Called from client.cpp
928 bool login()
930 CLoginProgressPostThread::getInstance().step(CLoginStep(LoginStep_LoginScreen, "login_step_login_screen"));
932 CInterfaceManager *pIM = CInterfaceManager::getInstance();
933 CPatchManager *pPM = CPatchManager::getInstance();
935 if (LoginLogin.empty())
936 loginIntro();
938 pIM->initLogin();
939 IngameDbMngr.flushObserverCalls();
940 NLGUI::CDBManager::getInstance()->flushObserverCalls();
942 SetMousePosFirstTime = true;
943 InitMouseWithCursor(false);
944 Driver->showCursor (false);
945 SetMouseFreeLook ();
946 SetMouseCursor (false);
947 SetMouseSpeed (ClientCfg.CursorSpeed);
948 SetMouseAcceleration (ClientCfg.CursorAcceleration);
949 SetMousePosFirstTime = true;
950 InitMouseWithCursor (ClientCfg.HardwareCursor && !StereoDisplayAttached);
952 // if (ClientCfg.TestBrowser)
953 // {
954 // NLGUI::CDBManager::getInstance()->getDbProp("UI:VARIABLES:SCREEN")->setValue32(UI_VARIABLES_SCREEN_WEBSTART);
956 // // hide 'back to login' button
957 // CInterfaceElement *backToLogin = CWidgetManager::getInstance()->getElementFromId(CTRL_BUTTON_BACKTOLOGIN);
958 // if (backToLogin)
959 // backToLogin->setActive(false);
961 // // show 'reload test page' button
962 // CInterfaceElement *reloadTest = CWidgetManager::getInstance()->getElementFromId(CTRL_BUTTON_RELOADTESTPAGE);
963 // if (reloadTest)
964 // reloadTest->setActive(true);
966 // // start the browser
967 // CGroupHTML *pGH = dynamic_cast<CGroupHTML*>(CWidgetManager::getInstance()->getElementFromId(GROUP_BROWSER));
969 // pGH->browse(ClientCfg.TestBrowserUrl.c_str());
971 // }
972 // else
973 // {
974 //// NLGUI::CDBManager::getInstance()->getDbProp("UI:VARIABLES:SCREEN")->setValue32(UI_VARIABLES_SCREEN_CHECKPASS);
975 //// NLGUI::CDBManager::getInstance()->getDbProp("UI:VARIABLES:DISPLAY_ACCOUNT_BUTTONS")->setValue32(ClientCfg.DisplayAccountButtons);
976 // }
978 // Active inputs
979 Actions.enable(true);
980 EditActions.enable(true);
982 if(ClientCfg.ConfigFile.exists("VerboseLog"))
983 pPM->setVerboseLog(ClientCfg.ConfigFile.getVar("VerboseLog").asInt() == 1);
984 if(pPM->isVerboseLog()) nlinfo("Using verbose log mode");
986 ClientApp = ClientCfg.ConfigFile.getVar("Application").asString(0);
988 // string l = getRegKeyValue("Login").c_str();
990 // if(!l.empty())
991 // {
992 // CGroupEditBox *pGEB = dynamic_cast<CGroupEditBox*>(CWidgetManager::getInstance()->getElementFromId(CTRL_EDITBOX_LOGIN));
993 // if (pGEB != NULL)
994 // pGEB->setInputString(l);
995 // CAHManager::getInstance()->runActionHandler("set_keyboard_focus", NULL, "target=" CTRL_EDITBOX_PASSWORD "|select_all=false");
996 // }
997 // else
998 // {
999 // CAHManager::getInstance()->runActionHandler("set_keyboard_focus", NULL, "target=" CTRL_EDITBOX_LOGIN "|select_all=false");
1000 // }
1002 ShardSelected = -1;
1003 // CCtrlTextButton *pCB = dynamic_cast<CCtrlTextButton*>(CWidgetManager::getInstance()->getElementFromId(CTRL_BUTTON_CONNECT));
1004 // if (pCB != NULL) pCB->setActive(false);
1006 // setLoginFinished( false );
1007 // loginFinished = false;
1008 // loginOK = false;
1010 // Comes from a current patch
1011 // if (!LoginLogin.empty())
1012 // {
1013 // CInterfaceManager *pIM = CInterfaceManager::getInstance();
1014 // CGroupEditBox *pGEBLog = dynamic_cast<CGroupEditBox*>(CWidgetManager::getInstance()->getElementFromId(CTRL_EDITBOX_LOGIN));
1015 // CGroupEditBox *pGEBPwd = dynamic_cast<CGroupEditBox*>(CWidgetManager::getInstance()->getElementFromId(CTRL_EDITBOX_PASSWORD));
1016 // pGEBLog->setInputString(LoginLogin);
1017 // pGEBPwd->setInputString(LoginPassword);
1018 // CAHManager::getInstance()->runActionHandler("on_login", NULL, "");
1019 // // Select good shard
1020 // ShardSelected = -1;
1021 // for (uint32 i = 0; i < Shards.size(); ++i)
1022 // {
1023 // if (Shards[i].ShardId == LoginShardId)
1024 // {
1025 // ShardSelected = i;
1026 // break;
1027 // }
1028 // }
1030 // if (ShardSelected == -1)
1031 // pIM->messageBox(CI18N::get("uiErrServerLost"), "ui:login");
1032 // else
1033 // CAHManager::getInstance()->runActionHandler("login_connect_2", NULL);
1034 // }
1036 // start the login state machine
1037 LoginSM.pushEvent(CLoginStateMachine::ev_init_done);
1039 // run the main loop
1040 loginMainLoop();
1042 // Uninit all
1043 pIM->uninitLogin();
1045 // Disable inputs
1046 Actions.enable(false);
1047 EditActions.enable(false);
1049 return loginOK;
1052 // ***************************************************************************
1053 // INTERFACE HELPERS
1054 // ***************************************************************************
1056 // ***************************************************************************
1057 void removeSpace(string &s)
1059 uint i = 0;
1060 while (!s.empty())
1062 if (s[i] == ' ')
1063 s.erase(i, 1);
1064 else
1065 i++;
1066 if (i >= s.size()) break;
1070 // ***************************************************************************
1071 static void getPatchParameters(std::string &url, std::string &ver, std::vector<std::string> &patchURIs)
1073 if (ClientCfg.R2Mode)
1075 url = ClientCfg.PatchUrl;
1076 ver = ClientCfg.PatchVersion;
1078 // if PatchUrl is forced, don't use URLs returned by server
1079 if (url.empty())
1081 patchURIs = R2PatchURLs;
1082 url = R2BackupPatchURL;
1083 ver = R2ServerVersion;
1086 else
1088 nlassert(ShardSelected != -1);
1089 patchURIs = Shards[ShardSelected].PatchURIs;
1090 url = Shards[ShardSelected].EmergencyPatchURL;
1091 ver = Shards[ShardSelected].Version;
1093 if (!ClientCfg.PatchUrl.empty())
1094 url = ClientCfg.PatchUrl;
1096 if (!ClientCfg.PatchVersion.empty())
1097 ver = ClientCfg.PatchVersion;
1101 // ***************************************************************************
1102 std::string getBGDownloaderCommandLine()
1104 #ifdef NL_DEBUG
1105 CConfigFile::CVar *bgdCommandLine = ClientCfg.ConfigFile.getVarPtr("BackgroundDownloaderCommandLine");
1106 if (bgdCommandLine != NULL && !bgdCommandLine->asString().empty())
1108 return bgdCommandLine->asString();
1110 #endif
1111 string url;
1112 string ver;
1113 std::vector<std::string> patchURIs;
1114 getPatchParameters(url, ver, patchURIs);
1115 std::string commandLine = /*R2ServerVersion + " " + VersionName + " " + */ url + " " + ver;
1116 for (uint i = 0; i < patchURIs.size(); ++i)
1118 commandLine += " " + patchURIs[i];
1120 return commandLine;
1123 // ***************************************************************************
1124 void initPatchCheck()
1126 // start the patching system
1127 CInterfaceManager *pIM = CInterfaceManager::getInstance();
1128 CPatchManager *pPM = CPatchManager::getInstance();
1130 string url;
1131 string ver;
1132 std::vector<std::string> patchURIs;
1134 if (!ClientCfg.R2Mode)
1136 // nb Nico : refactored this code.
1137 // In previous code, the following was not set in R2Mode, possible bug ?...let as before anyway ...
1138 // store the selected shard for restarting after patch
1139 LoginShardId = Shards[ShardSelected].ShardId;
1142 #ifdef RYZOM_BG_DOWNLOADER
1143 if (!isBGDownloadEnabled())
1144 #endif
1146 getPatchParameters(url, ver, patchURIs);
1147 pPM->init(patchURIs, url, ver);
1148 pPM->startCheckThread(true /* include background patchs */);
1150 #ifdef RYZOM_BG_DOWNLOADER
1151 else
1153 BGDownloader::CTaskDesc taskDesc(BGDownloader::DLState_CheckPatch);
1154 CBGDownloaderAccess::getInstance().requestDownloadThreadPriority(BGDownloader::ThreadPriority_Normal, false);
1155 CBGDownloaderAccess::getInstance().startTask(taskDesc, getBGDownloaderCommandLine(), true /* showDownloader */);
1157 #endif
1158 NLGUI::CDBManager::getInstance()->getDbProp("UI:VARIABLES:SCREEN")->setValue32(UI_VARIABLES_SCREEN_CHECKING);
1160 setPatcherStateText("ui:login:checking", string());
1161 setPatcherProgressText("ui:login:checking", string());
1164 void initShardDisplay()
1166 CInterfaceManager *pIM = CInterfaceManager::getInstance();
1167 NLGUI::CDBManager::getInstance()->getDbProp("UI:VARIABLES:SCREEN")->setValue32(UI_VARIABLES_SCREEN_SHARDDISP);
1169 CInterfaceGroup *pList = dynamic_cast<CInterfaceGroup*>(CWidgetManager::getInstance()->getElementFromId(GROUP_LIST_SHARD));
1170 if (pList == NULL)
1172 nlwarning("element " GROUP_LIST_SHARD " not found probably bad login_main.xml");
1173 return;
1175 /* // To test more servers
1176 for (uint fff = 0; fff < 20; ++fff)
1178 CShard s ( toString("%05d",fff), fff%3, fff+32, toString("%s%d","pipo",fff),
1179 32*fff%46546, "32.32.32.32", "http://www.ryzom.com" );
1180 Shards.push_back(s);
1183 CInterfaceGroup *pPrevLine = NULL;
1184 for(uint i = 0; i < Shards.size(); i++)
1186 vector< pair < string, string > > params;
1187 params.clear();
1188 params.push_back(pair<string,string>("id", "s"+toString(i)));
1189 if (i>0)
1190 params.push_back(pair<string,string>("posref", "BL TL"));
1192 CInterfaceGroup *pNewLine = CWidgetManager::getInstance()->getParser()->createGroupInstance("t_shard", GROUP_LIST_SHARD, params);
1193 if (pNewLine != NULL)
1195 CViewText *pVT = dynamic_cast<CViewText*>(pNewLine->getView("name"));
1196 if (pVT != NULL) pVT->setText(Shards[i].Name);
1198 pVT = dynamic_cast<CViewText*>(pNewLine->getView("version"));
1199 if (pVT != NULL) pVT->setText(Shards[i].Version);
1201 CViewBase *pVBon = pNewLine->getView("online");
1202 CViewBase *pVBoff = pNewLine->getView("offline");
1203 if ((pVBon != NULL) && (pVBoff != NULL))
1205 pVBon->setActive (Shards[i].Online);
1206 pVBoff->setActive (!Shards[i].Online);
1209 pVT = dynamic_cast<CViewText*>(pNewLine->getView("nbplayer"));
1210 if (pVT != NULL) pVT->setText(toString(Shards[i].NbPlayers));
1213 // Add to the list
1214 pNewLine->setParent(pList);
1215 pNewLine->setParentSize(pList);
1216 pNewLine->setParentPos(pPrevLine);
1217 pList->addGroup(pNewLine);
1219 pPrevLine = pNewLine;
1222 // UI Patch
1223 if (!Shards.empty())
1225 CCtrlButton *pCB = dynamic_cast<CCtrlButton*>(CWidgetManager::getInstance()->getElementFromId(GROUP_LIST_SHARD ":s0:but"));
1226 if (pCB != NULL)
1228 pCB->setPushed(true);
1229 CAHManager::getInstance()->runActionHandler(pCB->getActionOnLeftClick(), pCB, pCB->getParamsOnLeftClick());
1232 pList->invalidateCoords();
1235 // ***************************************************************************
1237 void onlogin(bool vanishScreen = true)
1239 CInterfaceManager *pIM = CInterfaceManager::getInstance();
1241 // Remove space before and after each string login & password
1242 removeSpace(LoginLogin);
1243 removeSpace(LoginPassword);
1245 if(!LoginLogin.empty())
1247 ClientCfg.LastLogin = LoginLogin;
1248 ClientCfg.writeString("LastLogin", ClientCfg.LastLogin, true);
1251 if(vanishScreen)
1252 NLGUI::CDBManager::getInstance()->getDbProp("UI:VARIABLES:SCREEN")->setValue32(-1);
1254 // Check the login/pass
1256 // main menu page for r2mode
1257 string res = checkLogin(LoginLogin, LoginPassword, ClientApp, LoginCustomParameters);
1258 if (res.empty())
1260 // if not in auto login, push login ok event
1261 if (LoginSM.getCurrentState() != CLoginStateMachine::st_auto_login)
1262 LoginSM.pushEvent(CLoginStateMachine::ev_login_ok);
1264 return;
1265 // Ok there is something ! Display next window
1267 if (ClientCfg.R2Mode)
1269 // if (ClientCfg.PatchWanted)
1270 // {
1271 // // start the patching system
1272 // CPatchManager *pPM = CPatchManager::getInstance();
1274 // pPM->init(R2PatchURLs, R2BackupPatchURL, R2ServerVersion);
1276 // pPM->startCheckThread();
1277 // NLGUI::CDBManager::getInstance()->getDbProp("UI:VARIABLES:SCREEN")->setValue32(UI_VARIABLES_SCREEN_CHECKING);
1278 // }
1279 // else
1280 // {
1281 // // go directly to web browser
1282 // NLGUI::CDBManager::getInstance()->getDbProp("UI:VARIABLES:SCREEN")->setValue32(UI_VARIABLES_SCREEN_WEBSTART);
1284 // CInterfaceManager *pIM = CInterfaceManager::getInstance();
1285 // // start the browser
1286 // CGroupHTML *pGH = dynamic_cast<CGroupHTML*>(CWidgetManager::getInstance()->getElementFromId(GROUP_BROWSER));
1288 // pGH->browse(RingMainURL.c_str());
1289 // }
1290 // return;
1292 else
1294 // NLGUI::CDBManager::getInstance()->getDbProp("UI:VARIABLES:SCREEN")->setValue32(UI_VARIABLES_SCREEN_SHARDDISP);
1297 // CInterfaceGroup *pList = dynamic_cast<CInterfaceGroup*>(CWidgetManager::getInstance()->getElementFromId(GROUP_LIST_SHARD));
1298 // if (pList == NULL)
1299 // {
1300 // nlwarning("element "GROUP_LIST_SHARD" not found probably bad login_main.xml");
1301 // return;
1302 // }
1303 // /* // To test more servers
1304 // for (uint fff = 0; fff < 20; ++fff)
1305 // {
1306 // CShard s ( toString("%05d",fff), fff%3, fff+32, toString("%s%d","pipo",fff),
1307 // 32*fff%46546, "32.32.32.32", "http://www.ryzom.com" );
1308 // Shards.push_back(s);
1309 // }*/
1311 // CInterfaceGroup *pPrevLine = NULL;
1312 // for(uint i = 0; i < Shards.size(); i++)
1313 // {
1314 // vector< pair < string, string > > params;
1315 // params.clear();
1316 // params.push_back(pair<string,string>("id", "s"+toString(i)));
1317 // if (i>0)
1318 // params.push_back(pair<string,string>("posref", "BL TL"));
1320 // CInterfaceGroup *pNewLine =pIM->createGroupInstance("t_shard", GROUP_LIST_SHARD, params);
1321 // if (pNewLine != NULL)
1322 // {
1323 // CViewText *pVT = dynamic_cast<CViewText*>(pNewLine->getView("name"));
1324 // if (pVT != NULL) pVT->setText(Shards[i].Name);
1326 // pVT = dynamic_cast<CViewText*>(pNewLine->getView("version"));
1327 // if (pVT != NULL) pVT->setText(Shards[i].Version);
1329 // CViewBase *pVBon = pNewLine->getView("online");
1330 // CViewBase *pVBoff = pNewLine->getView("offline");
1331 // if ((pVBon != NULL) && (pVBoff != NULL))
1332 // {
1333 // pVBon->setActive (Shards[i].Online);
1334 // pVBoff->setActive (!Shards[i].Online);
1335 // }
1337 // pVT = dynamic_cast<CViewText*>(pNewLine->getView("nbplayer"));
1338 // if (pVT != NULL) pVT->setText(toString(Shards[i].NbPlayers));
1341 // // Add to the list
1342 // pNewLine->setParent(pList);
1343 // pNewLine->setParentSize(pList);
1344 // pNewLine->setParentPos(pPrevLine);
1345 // pList->addGroup(pNewLine);
1347 // pPrevLine = pNewLine;
1348 // }
1349 // }
1350 // // UI Patch
1351 // if (!Shards.empty())
1352 // {
1353 // CCtrlButton *pCB = dynamic_cast<CCtrlButton*>(CWidgetManager::getInstance()->getElementFromId(GROUP_LIST_SHARD ":s0:but"));
1354 // if (pCB != NULL)
1355 // pCB->setPushed(true);
1356 // CAHManager::getInstance()->runActionHandler (pCB->getActionOnLeftClick(), pCB, pCB->getParamsOnLeftClick());
1358 // }
1359 // pList->invalidateCoords();
1361 else
1363 // close the socket in case of error
1364 HttpClient.disconnect();
1366 pIM->messageBoxWithHelp("Error : " + res, "ui:login");
1368 LoginSM.pushEvent(CLoginStateMachine::ev_bad_login);
1369 // NLGUI::CDBManager::getInstance()->getDbProp("UI:VARIABLES:SCREEN")->setValue32(UI_VARIABLES_SCREEN_CHECKPASS);
1371 // if (LoginLogin.empty())
1372 // CAHManager::getInstance()->runActionHandler("set_keyboard_focus", NULL, "target=" CTRL_EDITBOX_LOGIN "|select_all=false");
1373 // else
1374 // CAHManager::getInstance()->runActionHandler("set_keyboard_focus", NULL, "target=" CTRL_EDITBOX_PASSWORD "|select_all=false");
1379 class CAHOnLogin : public IActionHandler
1381 virtual void execute (CCtrlBase * /* pCaller */, const string &/* Params */)
1383 //nlinfo("CAHOnLogin called");
1385 CInterfaceManager *pIM = CInterfaceManager::getInstance();
1387 CGroupEditBox *pGEBLog = dynamic_cast<CGroupEditBox*>(CWidgetManager::getInstance()->getElementFromId(CTRL_EDITBOX_LOGIN));
1388 CGroupEditBox *pGEBPwd = dynamic_cast<CGroupEditBox*>(CWidgetManager::getInstance()->getElementFromId(CTRL_EDITBOX_PASSWORD));
1389 if ((pGEBLog == NULL) || (pGEBPwd == NULL))
1391 nlwarning("element " CTRL_EDITBOX_LOGIN " or " CTRL_EDITBOX_PASSWORD " not found probably bad login_main.xml");
1392 return;
1395 LoginLogin = pGEBLog->getInputString();
1396 LoginPassword = pGEBPwd->getInputString();
1398 onlogin();
1401 REGISTER_ACTION_HANDLER (CAHOnLogin, "on_login");
1404 // ***************************************************************************
1405 class CAHOnGameConfiguration : public IActionHandler
1407 virtual void execute (CCtrlBase * /* pCaller */, const string &/* Params */)
1409 nlinfo("CAHOnGameConfiguration called");
1411 static string Configurator = "ryzom_configuration_rd.exe";
1413 if (CFile::fileExists (Configurator))
1415 // launch the ryzom configurator
1416 launchProgram(Configurator, "");
1417 setLoginFinished( true );
1418 loginOK = false;
1420 LoginSM.pushEvent(CLoginStateMachine::ev_quit);
1422 else
1424 nlwarning("<CAHOnGameConfiguration::execute> can't find ryzom configurator : %s",Configurator.c_str());
1428 REGISTER_ACTION_HANDLER (CAHOnGameConfiguration, "on_game_configuration");
1431 // ***************************************************************************
1432 class CAHLoginQuit : public IActionHandler
1434 virtual void execute (CCtrlBase * /* pCaller */, const string &/* Params */)
1436 nlinfo("CAHLoginQuit called");
1438 setLoginFinished( true );
1439 loginOK = false;
1441 LoginSM.pushEvent(CLoginStateMachine::ev_quit);
1444 REGISTER_ACTION_HANDLER (CAHLoginQuit, "login_quit");
1447 // ***************************************************************************
1448 class CAHLoginTab : public IActionHandler
1450 virtual void execute (CCtrlBase * /* pCaller */, const string &/* Params */)
1452 nlinfo("CAHLoginTab called");
1454 CInterfaceManager *pIM = CInterfaceManager::getInstance();
1456 if (NLGUI::CDBManager::getInstance()->getDbProp("UI:VARIABLES:SCREEN")->getValue32() == UI_VARIABLES_SCREEN_CHECKPASS)
1458 CCtrlBase *pCB = CWidgetManager::getInstance()->getCaptureKeyboard();
1459 if (pCB != NULL)
1461 CCtrlBase *pNewCB;
1462 string sID = pCB->getId();
1463 if (sID == CTRL_EDITBOX_LOGIN)
1464 pNewCB = dynamic_cast<CCtrlBase*>(CWidgetManager::getInstance()->getElementFromId(CTRL_EDITBOX_PASSWORD));
1465 else
1466 pNewCB = dynamic_cast<CCtrlBase*>(CWidgetManager::getInstance()->getElementFromId(CTRL_EDITBOX_LOGIN));
1467 CWidgetManager::getInstance()->setCaptureKeyboard(pNewCB);
1470 else if (NLGUI::CDBManager::getInstance()->getDbProp("UI:VARIABLES:SCREEN")->getValue32() == UI_VARIABLES_SCREEN_CREATE_ACCOUNT)
1472 CCtrlBase *pCB = CWidgetManager::getInstance()->getCaptureKeyboard();
1473 if (pCB != NULL)
1475 CCtrlBase *pNewCB;
1476 string sID = pCB->getId();
1477 if (sID == CTRL_EDITBOX_CREATEACCOUNT_LOGIN)
1478 pNewCB = dynamic_cast<CCtrlBase*>(CWidgetManager::getInstance()->getElementFromId(CTRL_EDITBOX_CREATEACCOUNT_PASSWORD));
1479 else if (sID == CTRL_EDITBOX_CREATEACCOUNT_PASSWORD)
1480 pNewCB = dynamic_cast<CCtrlBase*>(CWidgetManager::getInstance()->getElementFromId(CTRL_EDITBOX_CREATEACCOUNT_CONFIRMPASSWORD));
1481 else if (sID == CTRL_EDITBOX_CREATEACCOUNT_CONFIRMPASSWORD)
1482 pNewCB = dynamic_cast<CCtrlBase*>(CWidgetManager::getInstance()->getElementFromId(CTRL_EDITBOX_CREATEACCOUNT_EMAIL));
1483 else
1484 pNewCB = dynamic_cast<CCtrlBase*>(CWidgetManager::getInstance()->getElementFromId(CTRL_EDITBOX_CREATEACCOUNT_LOGIN));
1485 CWidgetManager::getInstance()->setCaptureKeyboard(pNewCB);
1490 REGISTER_ACTION_HANDLER (CAHLoginTab, "login_tab");
1493 // ***************************************************************************
1494 class CAHShardSelect : public IActionHandler
1496 virtual void execute (CCtrlBase *pCaller, const string &/* Params */)
1498 nlinfo("CAHShardSelect called");
1500 CInterfaceManager *pIM = CInterfaceManager::getInstance();
1502 CCtrlButton *pCB = NULL;
1503 // Unselect
1504 if (ShardSelected != -1)
1506 pCB = dynamic_cast<CCtrlButton*>(CWidgetManager::getInstance()->getElementFromId(GROUP_LIST_SHARD ":s"+toString(ShardSelected)+":but"));
1507 if (pCB != NULL)
1508 pCB->setPushed(false);
1511 pCB = dynamic_cast<CCtrlButton*>(pCaller);
1512 if (pCB != NULL)
1514 string name = pCB->getId();
1515 name = name.substr(0,name.rfind(':'));
1516 name = name.substr(name.rfind(':')+2,name.size());
1517 fromString(name, ShardSelected);
1519 pCB->setPushed(true);
1522 CCtrlTextButton *pCTB = dynamic_cast<CCtrlTextButton*>(CWidgetManager::getInstance()->getElementFromId(CTRL_BUTTON_CONNECT));
1523 if (pCTB != NULL)
1524 pCTB->setActive(true);
1527 REGISTER_ACTION_HANDLER (CAHShardSelect, "shard_select");
1529 // ***************************************************************************
1530 void ConnectToShard()
1532 //nlinfo("ConnectToShard called");
1534 if (ClientCfg.R2Mode)
1536 // r2 mode
1537 setLoginFinished( true );
1538 loginOK = true;
1540 LoginSM.pushEvent(CLoginStateMachine::ev_enter_game);
1542 else
1544 // legacy mode
1545 nlassert(ShardSelected != -1);
1547 string res = selectShard(Shards[ShardSelected].ShardId, Cookie, FSAddr);
1549 if(res.empty())
1551 setLoginFinished( true );
1552 loginOK = true;
1554 LoginSM.pushEvent(CLoginStateMachine::ev_enter_game);
1556 else
1558 CInterfaceManager *pIM = CInterfaceManager::getInstance();
1559 pIM->messageBoxWithHelp("Error :" + res, "ui:login");
1561 LoginSM.pushEvent(CLoginStateMachine::ev_conn_failed);
1568 // ***************************************************************************
1569 class CAHLoginConnect : public IActionHandler
1571 virtual void execute (CCtrlBase * /* pCaller */, const string &/* Params */)
1573 nlinfo("CAHLoginConnect called");
1575 CInterfaceManager *pIM = CInterfaceManager::getInstance();
1577 if (ShardSelected == -1)
1578 return;
1580 if (!Shards[ShardSelected].Online)
1582 pIM->messageBoxWithHelp(CI18N::get("uiErrOffLineShard"), "ui:login");
1583 return;
1586 LoginSM.pushEvent(CLoginStateMachine::ev_shard_selected);
1588 // std::vector<std::string> patchURIs = Shards[ShardSelected].PatchURIs;
1589 // string url = Shards[ShardSelected].EmergencyPatchURL;
1590 // string ver = Shards[ShardSelected].Version;
1592 // if (!ClientCfg.PatchUrl.empty())
1593 // url = ClientCfg.PatchUrl;
1595 // if (!ClientCfg.PatchVersion.empty())
1596 // ver = ClientCfg.PatchVersion;
1598 // pPM->init(patchURIs, url, ver);
1600 // LoginShardId = Shards[ShardSelected].ShardId;
1602 // if (ClientCfg.PatchWanted)
1603 // {
1604 // pPM->startCheckThread();
1605 // NLGUI::CDBManager::getInstance()->getDbProp("UI:VARIABLES:SCREEN")->setValue32(UI_VARIABLES_SCREEN_CHECKING);
1606 // }
1607 // else
1608 // {
1609 // CAHManager::getInstance()->runActionHandler("login_patch",NULL);
1610 // }
1613 REGISTER_ACTION_HANDLER (CAHLoginConnect, "login_connect");
1615 // ***************************************************************************
1616 // Can be called after a patching process (ryzom relaunch and call this AH to
1617 // see if we have to continue patching or directly go ingame)
1618 class CAHLoginConnect2 : public IActionHandler
1620 virtual void execute (CCtrlBase * /* pCaller */, const string &/* Params */)
1622 nlinfo("CAHLoginConnect2 called");
1623 CInterfaceManager *pIM = CInterfaceManager::getInstance();
1625 if (Shards[ShardSelected].PatchURIs.empty() && Shards[ShardSelected].EmergencyPatchURL.empty())
1627 pIM->messageBoxWithHelp(CI18N::get("uiErrCantPatch"), "ui:login");
1628 return;
1631 LoginSM.pushEvent(CLoginStateMachine::ev_shard_selected);
1633 // std::vector<std::string> patchURIs = Shards[ShardSelected].PatchURIs;
1634 // string url = Shards[ShardSelected].EmergencyPatchURL;
1635 // string ver = Shards[ShardSelected].Version;
1637 // if (!ClientCfg.PatchUrl.empty())
1638 // url = ClientCfg.PatchUrl;
1640 // if (!ClientCfg.PatchVersion.empty())
1641 // ver = ClientCfg.PatchVersion;
1643 // pPM->init(patchURIs, url, ver);
1645 // if ((ClientCfg.PatchWanted) &&
1646 // (!Shards[ShardSelected].Version.empty()) &&
1647 // (Shards[ShardSelected].Version != pPM->getClientVersion()))
1648 // {
1649 // pPM->startCheckThread();
1650 // NLGUI::CDBManager::getInstance()->getDbProp("UI:VARIABLES:SCREEN")->setValue32(UI_VARIABLES_SCREEN_CHECKING);
1651 // }
1652 // else
1653 // {
1654 // // Version is good, eula then connect and launch the client
1655 // showEULA();
1656 // }
1659 REGISTER_ACTION_HANDLER (CAHLoginConnect2, "login_connect_2");
1661 void initPatch()
1663 CInterfaceManager *pIM = CInterfaceManager::getInstance();
1664 CPatchManager *pPM = CPatchManager::getInstance();
1666 #ifdef RYZOM_BG_DOWNLOADER
1667 if (!isBGDownloadEnabled())
1668 #endif
1670 // Get the list of optional categories to patch
1671 vector<string> vCategories;
1673 CInterfaceGroup *pList = dynamic_cast<CInterfaceGroup*>(CWidgetManager::getInstance()->getElementFromId(GROUP_LIST_CAT));
1674 if (pList == NULL)
1676 nlwarning("element " GROUP_LIST_CAT " not found probably bad login_main.xml");
1677 return;
1680 for(uint i = 0; i < InfoOnPatch.OptCat.size(); i++)
1682 // Ok for the moment all optional categories must be patched even if the player
1683 // does not want it. Because we cant detect that a continent have to be patched ingame.
1684 vCategories.push_back(InfoOnPatch.OptCat[i].Name);
1687 // Code to check if the player wants an optional category or not
1688 CInterfaceGroup *pLine = pList->getGroup("c"+toString(i));
1689 if (pLine != NULL)
1691 CCtrlButton *pCB = dynamic_cast<CCtrlButton*>(pLine->getCtrl("on_off"));
1692 if (pCB != NULL)
1694 if (pCB->getPushed())
1695 vCategories.push_back(rAllCats[i]);
1701 pPM->startPatchThread(vCategories, true);
1703 #ifdef RYZOM_BG_DOWNLOADER
1704 else
1706 // NB : here we only do a part of the download each time
1707 BGDownloader::CTaskDesc taskDesc(BGDownloader::DLState_GetAndApplyPatch, (1 << BGDownloaderWantedPatch));
1708 CBGDownloaderAccess::getInstance().startTask(taskDesc, string(), true /* showDownloader */); // no command line since bg downloader should already be started
1709 // release lock on bnp, so that they can be written
1710 NLMISC::CBigFile::getInstance().removeAll();
1711 NLMISC::CStreamedPackageManager::getInstance().unloadAll();
1713 #endif
1714 NLGUI::CDBManager::getInstance()->getDbProp("UI:VARIABLES:SCREEN")->setValue32(UI_VARIABLES_SCREEN_PATCHING);
1716 CInterfaceElement *closeBtn = CWidgetManager::getInstance()->getElementFromId(CTRL_BUTTON_CLOSE_PATCH);
1717 if (closeBtn)
1718 closeBtn->setActive(false);
1720 setPatcherStateText("ui:login:patching", string());
1721 setPatcherProgressText("ui:login:patching", string());
1724 // ***************************************************************************
1725 // Called after the check has been done. The page is full of optional categories that must be selected for patching
1726 class CAHLoginPatch : public IActionHandler
1728 virtual void execute (CCtrlBase * /* pCaller */, const string &/* Params */)
1730 nlinfo("CAHLoginPatch called");
1732 LoginSM.pushEvent(CLoginStateMachine::ev_run_patch);
1734 // CInterfaceManager *pIM = CInterfaceManager::getInstance();
1735 // CPatchManager *pPM = CPatchManager::getInstance();
1737 // // Get the list of optional categories to patch
1738 // vector<string> vCategories;
1740 // CInterfaceGroup *pList = dynamic_cast<CInterfaceGroup*>(CWidgetManager::getInstance()->getElementFromId(GROUP_LIST_CAT));
1741 // if (pList == NULL)
1742 // {
1743 // nlwarning("element "GROUP_LIST_CAT" not found probably bad login_main.xml");
1744 // return;
1745 // }
1747 // for(uint i = 0; i < InfoOnPatch.OptCat.size(); i++)
1748 // {
1749 // // Ok for the moment all optional categories must be patched even if the player
1750 // // does not want it. Because we cant detect that a continent have to be patched ingame.
1751 // vCategories.push_back(InfoOnPatch.OptCat[i].Name);
1753 // /*
1754 // // Code to check if the player wants an optional category or not
1755 // CInterfaceGroup *pLine = pList->getGroup("c"+toString(i));
1756 // if (pLine != NULL)
1757 // {
1758 // CCtrlButton *pCB = dynamic_cast<CCtrlButton*>(pLine->getCtrl("on_off"));
1759 // if (pCB != NULL)
1760 // {
1761 // if (pCB->getPushed())
1762 // vCategories.push_back(rAllCats[i]);
1763 // }
1764 // }
1765 // */
1766 // }
1768 // // Start patching
1769 // if (ClientCfg.PatchWanted)
1770 // {
1771 // pPM->startPatchThread(vCategories);
1772 // NLGUI::CDBManager::getInstance()->getDbProp("UI:VARIABLES:SCREEN")->setValue32(UI_VARIABLES_SCREEN_PATCHING);
1773 // }
1774 // else
1775 // {
1776 // ConnectToShard();
1777 // }
1780 REGISTER_ACTION_HANDLER (CAHLoginPatch, "login_patch");
1782 // ***************************************************************************
1783 // Called after the check has been done. The page is full of optional categories that must be selected for patching
1784 class CAHClosePatch : public IActionHandler
1786 virtual void execute (CCtrlBase * /* pCaller */, const string &/* Params */)
1788 nlinfo("CAHClosePatch called");
1790 LoginSM.pushEvent(CLoginStateMachine::ev_close_patch);
1793 REGISTER_ACTION_HANDLER (CAHClosePatch, "close_patch");
1796 // ***************************************************************************
1797 // Called after pushing the read note at the opening of the modal window
1798 class CAHSetReleaseNote : public IActionHandler
1800 virtual void execute (CCtrlBase * /* pCaller */, const string &sParams)
1802 nlinfo("CAHSetReleaseNote called");
1804 CInterfaceManager *pIM = CInterfaceManager::getInstance();
1806 string sShard = getParam(sParams, "shard");
1807 string sGroupHtml = getParam(sParams, "group");
1809 CGroupHTML *pQH = dynamic_cast<CGroupHTML*>(CWidgetManager::getInstance()->getElementFromId(sGroupHtml));
1810 if (pQH == NULL)
1811 return;
1813 string sURL;
1814 if (ClientCfg.R2Mode)
1816 // ring release note
1817 sURL = ClientCfg.RingReleaseNotePath +
1818 "?version=" + (VersionName.empty() ? R2ServerVersion : VersionName)+
1819 "&lang=" + ClientCfg.LanguageCode +
1820 "&ca=" + ClientCfg.ConfigFile.getVar("Application").asString(0);
1821 "&startPage="+RingMainURL;
1823 else
1825 // legacy ryzom release note
1826 uint32 nShardId;
1827 if (sShard == "selected")
1828 nShardId = ShardSelected;
1829 else
1830 fromString(sShard.substr(1), nShardId);
1832 sURL = ClientCfg.ReleaseNotePath +
1833 "?version=" + Shards[nShardId].Version +
1834 "&lang=" + ClientCfg.LanguageCode +
1835 "&id=" + toString(Shards[nShardId].ShardId) +
1836 "&ca=" + ClientCfg.ConfigFile.getVar("Application").asString(0);
1840 pQH->browse(sURL.c_str());
1843 REGISTER_ACTION_HANDLER (CAHSetReleaseNote, "set_release_note");
1845 // ***************************************************************************
1846 // Called after pushing the read note at the opening of the modal window
1847 class CAHReboot : public IActionHandler
1849 virtual void execute (CCtrlBase * /* pCaller */, const string &/* sParams */)
1851 nlinfo("CAHReboot called");
1853 // create a file to prompt eula next time
1854 CFile::createEmptyFile(getLogDirectory() + "show_eula");
1856 CInterfaceManager *im = CInterfaceManager::getInstance();
1859 #ifdef RYZOM_BG_DOWNLOADER
1860 if (isBGDownloadEnabled())
1862 CBGDownloaderAccess::getInstance().reboot();
1864 else
1865 #endif
1867 CPatchManager::getInstance()->reboot();
1869 LoginSM.pushEvent(CLoginStateMachine::ev_reboot);
1871 catch (const NLMISC::EDiskFullError &)
1873 im->messageBoxWithHelp(CI18N::get("uiPatchDiskFull"), "ui:login");
1875 catch (const NLMISC::EWriteError &)
1877 im->messageBoxWithHelp(CI18N::get("uiPatchWriteError"), "ui:login");
1879 catch (const std::exception &e)
1881 im->messageBoxWithHelp(e.what(), "ui:login", "login_quit");
1885 REGISTER_ACTION_HANDLER (CAHReboot, "reboot");
1889 // ***************************************************************************
1890 class CAHAcceptEula : public IActionHandler
1892 virtual void execute (CCtrlBase * /* pCaller */, const string &/* sParams */)
1894 //nlinfo("CAHAcceptEula called");
1895 if(CFile::fileExists(getLogDirectory() + "show_eula"))
1896 CFile::deleteFile(getLogDirectory() + "show_eula");
1897 LoginSM.pushEvent(CLoginStateMachine::ev_accept_eula);
1899 // if (ClientCfg.R2Mode)
1900 // {
1901 // // open web browser
1902 // CInterfaceManager *pIM = CInterfaceManager::getInstance();
1903 // NLGUI::CDBManager::getInstance()->getDbProp("UI:VARIABLES:SCREEN")->setValue32(UI_VARIABLES_SCREEN_WEBSTART);
1905 // // start the browser
1906 // CGroupHTML *pGH = dynamic_cast<CGroupHTML*>(CWidgetManager::getInstance()->getElementFromId(GROUP_BROWSER));
1908 // pGH->browse(RingMainURL.c_str());
1909 // }
1910 // else
1911 // {
1912 // ConnectToShard();
1913 // }
1916 REGISTER_ACTION_HANDLER (CAHAcceptEula, "accept_eula");
1918 // ***************************************************************************
1919 class CAHOpenURL : public IActionHandler
1921 virtual void execute (CCtrlBase * /* pCaller */, const string &sParams)
1923 nlinfo("CAHOpenURL called");
1925 string url;
1927 string installTag;
1929 #ifdef NL_OS_WINDOWS
1931 // Check for special install tag
1932 const char *KeyName = "InstallTag";
1934 installTag = CSystemUtils::getRegKey(KeyName);
1936 if (installTag.length() > 1)
1938 nldebug("Found install tag '%s'", url.c_str());
1940 else
1942 // Process any inserts in lpMsgBuf.
1943 // ...
1944 // Display the string.
1945 nlwarning("RegQueryValue for '%s' : %s", KeyName, NLMISC::formatErrorMessage(0).c_str());
1947 #else
1948 // TODO: for Linux and Mac OS
1949 #endif
1951 if (sParams == "cfg_EditAccountURL")
1953 url = ClientCfg.EditAccountURL;
1955 else if (sParams == "cfg_BetaAccountURL")
1957 url = ClientCfg.BetaAccountURL;
1959 else if (sParams == "cfg_ForgetPwdURL")
1961 url = ClientCfg.ForgetPwdURL;
1963 else if (sParams == "cfg_LoginSupportURL")
1965 url= ClientCfg.LoginSupportURL;
1967 else if (sParams == "cfg_FreeTrialURL")
1969 url = ClientCfg.FreeTrialURL;
1971 if (!installTag.empty())
1973 url += string("&from=")+installTag;
1976 else if (sParams == "cfg_ConditionsTermsURL")
1978 url = ClientCfg.ConditionsTermsURL;
1980 else if (sParams == "cfg_NamingPolicyURL")
1982 url = ClientCfg.NamingPolicyURL;
1984 else
1986 nlwarning("no URL found");
1987 return;
1990 // modify existing languages
1992 // old site
1993 string::size_type pos_lang = url.find("/en/");
1995 // or new forums
1996 if (pos_lang == string::npos)
1997 pos_lang = url.find("=en#");
1999 if (pos_lang != string::npos)
2001 url.replace(pos_lang + 1, 2, ClientCfg.getHtmlLanguageCode());
2003 else
2005 // append language
2006 if (url.find('?') != string::npos)
2007 url += "&";
2008 else
2009 url += "?";
2011 url += "language=" + ClientCfg.LanguageCode;
2013 if (!LoginCustomParameters.empty())
2014 url += LoginCustomParameters;
2017 openURL(url);
2019 nlinfo("openURL %s", url.c_str());
2022 REGISTER_ACTION_HANDLER (CAHOpenURL, "open_url");
2024 static vector<UDriver::CMode> VideoModes;
2025 vector<string> StringModeList;
2026 vector<string> StringPresetList;
2027 vector< pair<string, bool> > CfgPresetList;
2028 sint CurrentMode = -1;
2029 sint CurrentPreset = -1;
2031 // ***************************************************************************
2032 class CAHInitResLod : public IActionHandler
2034 virtual void execute (CCtrlBase * /* pCaller */, const string &/* sParams */)
2036 //nlinfo("CAHInitResLod called");
2037 if (Driver == NULL) return;
2039 VideoModes.clear();
2040 StringModeList.clear();
2042 std::vector<std::string> stringFreqList;
2043 sint currentFreq;
2045 getRyzomModes(VideoModes, StringModeList, stringFreqList, CurrentMode, currentFreq);
2047 // getRyzomModes() expects empty list, so we need to insert 'Windowed' after mode list is filled
2048 StringModeList.insert(StringModeList.begin(), "uiConfigWindowed");
2050 // If the client is in windowed mode, still in windowed mode and do not change anything
2051 if (ClientCfg.Windowed)
2052 CurrentMode = 0;
2053 // If we have not found the mode so it can be an error or machine change, so propose the first available
2054 else if (CurrentMode == -1)
2055 CurrentMode = 1;
2056 // We inserted 'Windowed' as first mode, so index needs to move too
2057 else
2058 ++CurrentMode;
2060 CInterfaceManager *pIM = CInterfaceManager::getInstance();
2061 CViewText *pVT = dynamic_cast<CViewText*>(CWidgetManager::getInstance()->getElementFromId("ui:login:checkpass:content:res_value"));
2062 if (pVT != NULL)
2063 pVT->setHardText(StringModeList[CurrentMode]);
2065 StringPresetList.clear();
2066 StringPresetList.push_back("uiLodValueLow");
2067 StringPresetList.push_back("uiLodValueMedium");
2068 StringPresetList.push_back("uiLodValueNormal");
2069 StringPresetList.push_back("uiLodValueHigh");
2070 StringPresetList.push_back("uiLodValueCustom");
2071 CurrentPreset = 4; // CInterfaceDDX::CustomPreset
2073 // first indicates the preset-able cfg-variable
2074 // second indicates if its a double variable (else it's an int)
2075 CfgPresetList.clear();
2076 CfgPresetList.push_back(pair<string,bool>("LandscapeTileNear", true));
2077 CfgPresetList.push_back(pair<string,bool>("LandscapeThreshold", true));
2078 CfgPresetList.push_back(pair<string,bool>("Vision", true));
2079 CfgPresetList.push_back(pair<string,bool>("MicroVeget", false));
2080 CfgPresetList.push_back(pair<string,bool>("MicroVegetDensity", true));
2081 CfgPresetList.push_back(pair<string,bool>("FxNbMaxPoly", false));
2082 CfgPresetList.push_back(pair<string,bool>("Cloud", false));
2083 CfgPresetList.push_back(pair<string,bool>("CloudQuality", true));
2084 CfgPresetList.push_back(pair<string,bool>("CloudUpdate", false));
2085 CfgPresetList.push_back(pair<string,bool>("Shadows", false));
2086 CfgPresetList.push_back(pair<string,bool>("SkinNbMaxPoly", false));
2087 CfgPresetList.push_back(pair<string,bool>("NbMaxSkeletonNotCLod", false));
2088 CfgPresetList.push_back(pair<string,bool>("CharacterFarClip", true));
2090 CfgPresetList.push_back(pair<string,bool>("FXAA", false));
2091 CfgPresetList.push_back(pair<string,bool>("Bloom", false));
2092 CfgPresetList.push_back(pair<string,bool>("SquareBloom", false));
2093 CfgPresetList.push_back(pair<string,bool>("DensityBloom", true));
2095 // Check if all the preset-able cfg-variable are in a preset mode
2096 sint nPreset = -1;
2097 for (uint32 i = 0; i < CfgPresetList.size(); ++i)
2099 CConfigFile::CVar *cfgVarPtr = ClientCfg.ConfigFile.getVarPtr(CfgPresetList[i].first);
2100 if (cfgVarPtr == NULL) continue;
2101 // Get the preset of the variable i
2102 sint nVarPreset = 0;
2103 for (uint32 j = 0; j < 4; ++j) // CInterfaceDDX::NumPreset
2105 string sPresetName = CfgPresetList[i].first + "_ps" + toString(j);
2106 CConfigFile::CVar *presetVarPtr = ClientCfg.ConfigFile.getVarPtr(sPresetName);
2107 if(presetVarPtr)
2109 if (CfgPresetList[i].second) // Is it a double ?
2111 if (cfgVarPtr->asDouble() == presetVarPtr->asDouble())
2112 nVarPreset |= (1 << j);
2114 else
2116 if (cfgVarPtr->asInt() == presetVarPtr->asInt())
2117 nVarPreset |= (1 << j);
2122 if (nPreset == -1)
2123 nPreset = nVarPreset;
2124 else
2125 nPreset &= nVarPreset;
2127 if (nPreset == 0)
2128 break;
2131 if (nPreset != 0)
2133 if (nPreset&1) CurrentPreset = 0;
2134 else if (nPreset&2) CurrentPreset = 1;
2135 else if (nPreset&4) CurrentPreset = 2;
2136 else if (nPreset&8) CurrentPreset = 3;
2139 pVT = dynamic_cast<CViewText*>(CWidgetManager::getInstance()->getElementFromId("ui:login:checkpass:content:lod_value"));
2140 if (pVT != NULL)
2141 pVT->setHardText(StringPresetList[CurrentPreset]);
2144 REGISTER_ACTION_HANDLER (CAHInitResLod, "init_res_lod");
2146 // ***************************************************************************
2147 class CAHMoreRes : public IActionHandler
2149 virtual void execute (CCtrlBase * /* pCaller */, const string &/* sParams */)
2151 nlinfo("CAHMoreRes called");
2152 if (CurrentMode < ((sint)StringModeList.size()-1))
2153 CurrentMode++;
2154 CInterfaceManager *pIM = CInterfaceManager::getInstance();
2155 CViewText *pVT = dynamic_cast<CViewText*>(CWidgetManager::getInstance()->getElementFromId("ui:login:checkpass:content:res_value"));
2156 if (pVT != NULL)
2157 pVT->setHardText(StringModeList[CurrentMode]);
2160 REGISTER_ACTION_HANDLER (CAHMoreRes, "more_res");
2162 // ***************************************************************************
2163 class CAHLessRes : public IActionHandler
2165 virtual void execute (CCtrlBase * /* pCaller */, const string &/* sParams */)
2167 nlinfo("CAHLessRes called");
2168 if (CurrentMode > 0)
2169 CurrentMode--;
2170 CInterfaceManager *pIM = CInterfaceManager::getInstance();
2171 CViewText *pVT = dynamic_cast<CViewText*>(CWidgetManager::getInstance()->getElementFromId("ui:login:checkpass:content:res_value"));
2172 if (pVT != NULL)
2173 pVT->setHardText(StringModeList[CurrentMode]);
2176 REGISTER_ACTION_HANDLER (CAHLessRes, "less_res");
2178 // ***************************************************************************
2179 class CAHMoreLod : public IActionHandler
2181 virtual void execute (CCtrlBase * /* pCaller */, const string &/* sParams */)
2183 nlinfo("CAHMoreLod called");
2184 if (CurrentPreset < ((sint)StringPresetList.size()-1))
2185 CurrentPreset++;
2186 CInterfaceManager *pIM = CInterfaceManager::getInstance();
2187 CViewText *pVT = dynamic_cast<CViewText*>(CWidgetManager::getInstance()->getElementFromId("ui:login:checkpass:content:lod_value"));
2188 if (pVT != NULL)
2189 pVT->setHardText(StringPresetList[CurrentPreset]);
2192 REGISTER_ACTION_HANDLER (CAHMoreLod, "more_lod");
2194 // ***************************************************************************
2195 class CAHLessLod : public IActionHandler
2197 virtual void execute (CCtrlBase * /* pCaller */, const string &/* sParams */)
2199 nlinfo("CAHMoreLod called");
2200 if (CurrentPreset > 0)
2201 CurrentPreset--;
2202 CInterfaceManager *pIM = CInterfaceManager::getInstance();
2203 CViewText *pVT = dynamic_cast<CViewText*>(CWidgetManager::getInstance()->getElementFromId("ui:login:checkpass:content:lod_value"));
2204 if (pVT != NULL)
2205 pVT->setHardText(StringPresetList[CurrentPreset]);
2208 REGISTER_ACTION_HANDLER (CAHLessLod, "less_lod");
2210 // ***************************************************************************
2211 // TODO: remove resolution change from login screen
2212 class CAHUninitResLod : public IActionHandler
2214 virtual void execute (CCtrlBase * /* pCaller */, const string &/* sParams */)
2216 //nlinfo("CAHUninitResLod called");
2218 // If the mode requested is a windowed mode do nothnig
2219 if (CurrentMode == 0)
2221 ClientCfg.Windowed = true;
2222 ClientCfg.writeBool("FullScreen", false);
2224 else
2226 ClientCfg.Windowed = false;
2227 // Get W, H
2228 uint16 w = 0, h = 0;
2230 string vidModeStr = StringModeList[CurrentMode];
2231 string tmp = vidModeStr.substr(0,vidModeStr.find('x')-1);
2232 fromString(tmp, w);
2233 tmp = vidModeStr.substr(vidModeStr.find('x')+2,vidModeStr.size());
2234 fromString(tmp, h);
2236 ClientCfg.Width = w;
2237 ClientCfg.Height = h;
2239 ClientCfg.writeBool("FullScreen", true);
2240 ClientCfg.writeInt("Width", w);
2241 ClientCfg.writeInt("Height", h);
2244 if (CurrentPreset != 4) // CInterfaceDDX::CustomPreset
2246 for (uint32 i = 0; i < CfgPresetList.size(); ++i)
2248 CConfigFile::CVar *cfgVarPtr = ClientCfg.ConfigFile.getVarPtr(CfgPresetList[i].first);
2249 if (cfgVarPtr == NULL) continue;
2251 string sPresetName = CfgPresetList[i].first + "_ps" + toString(CurrentPreset);
2252 CConfigFile::CVar *presetVarPtr = ClientCfg.ConfigFile.getVarPtr(sPresetName);
2253 if(presetVarPtr)
2255 if (CfgPresetList[i].second) // Is it a double ?
2256 cfgVarPtr->setAsDouble(presetVarPtr->asDouble());
2257 else
2258 cfgVarPtr->setAsInt(presetVarPtr->asInt());
2263 // **** Save the config
2264 if (ClientCfg.SaveConfig)
2265 ClientCfg.ConfigFile.save ();
2266 ClientCfg.IsInvalidated = true;
2269 REGISTER_ACTION_HANDLER (CAHUninitResLod, "uninit_res_lod");
2272 void initDataScan()
2274 CInterfaceManager *pIM = CInterfaceManager::getInstance();
2275 CPatchManager *pPM = CPatchManager::getInstance();
2277 // reset the log
2278 setDataScanLog(string());
2280 // Start Scanning
2281 pPM->startScanDataThread();
2282 NLGUI::CDBManager::getInstance()->getDbProp("UI:VARIABLES:SCREEN")->setValue32(UI_VARIABLES_SCREEN_DATASCAN);
2283 NLGUI::CDBManager::getInstance()->getDbProp("UI:VARIABLES:DATASCAN_RUNNING")->setValue32(1);
2286 // ***************************************************************************
2287 // Called after the check has been done. The page is full of optional categories that must be selected for patching
2288 class CAHOnScanDataStart : public IActionHandler
2290 virtual void execute (CCtrlBase * /* pCaller */, const string &/* Params */)
2292 nlinfo("CAHOnScanDataStart called");
2294 LoginSM.pushEvent(CLoginStateMachine::ev_data_scan);
2298 REGISTER_ACTION_HANDLER (CAHOnScanDataStart, "on_scan_data_start");
2300 // ***************************************************************************
2301 // Called when the user cancel the scan
2302 class CAHOnScanDataClose : public IActionHandler
2304 virtual void execute (CCtrlBase * /* pCaller */, const string &/* Params */)
2306 nlinfo("CAHOnScanDataClose called");
2307 CInterfaceManager *pIM = CInterfaceManager::getInstance();
2308 CPatchManager *pPM = CPatchManager::getInstance();
2310 // if the scan is still running
2311 if(NLGUI::CDBManager::getInstance()->getDbProp("UI:VARIABLES:DATASCAN_RUNNING")->getValue32()!=0)
2313 // request to stop the thread
2314 pPM->askForStopScanDataThread();
2316 // Log.
2317 setDataScanState(CI18N::get("uiCancelingScanData"));
2319 else
2321 LoginSM.pushEvent(CLoginStateMachine::ev_close_data_scan);
2322 // Come Back to Login Screen.
2323 // NLGUI::CDBManager::getInstance()->getDbProp("UI:VARIABLES:SCREEN")->setValue32(UI_VARIABLES_SCREEN_CHECKPASS);
2325 // // Give focus to password if some login entered
2326 // string loginEB;
2327 // CGroupEditBox *pGEB = dynamic_cast<CGroupEditBox*>(CWidgetManager::getInstance()->getElementFromId(CTRL_EDITBOX_LOGIN));
2328 // if(pGEB)
2329 // loginEB= pGEB->getInputStringAsStdString();
2330 // // if none entered
2331 // if (loginEB.empty())
2332 // CAHManager::getInstance()->runActionHandler("set_keyboard_focus", NULL, "target=" CTRL_EDITBOX_LOGIN "|select_all=false");
2333 // else
2334 // CAHManager::getInstance()->runActionHandler("set_keyboard_focus", NULL, "target=" CTRL_EDITBOX_PASSWORD "|select_all=false");
2338 REGISTER_ACTION_HANDLER (CAHOnScanDataClose, "on_scan_data_close");
2340 // ***************************************************************************
2342 inline string parseTooltip(const string & initString, const string & tagName)
2344 string tooltip;
2346 string::size_type tooltipPos = initString.find(tagName);
2347 if(tooltipPos != string::npos)
2349 tooltip = initString.substr(tooltipPos);
2351 // start of tooltip
2352 tooltip = tooltip.substr(tooltip.find(">")+1);
2354 // end of tooltip
2355 tooltip = tooltip.substr(0, tooltip.find("<"));
2358 return tooltip;
2361 inline string parseCommentError(const string & initString, const string & tagName)
2363 string error;
2365 string::size_type errorPos = initString.find(tagName);
2366 if(errorPos != string::npos)
2368 error = initString.substr(errorPos);
2370 // start of comment
2371 error = error.substr(error.find(">")+1);
2373 // end of comment
2374 error = error.substr(0, error.find("<"));
2377 return error;
2380 bool initCreateAccount()
2382 CInterfaceManager *pIM = CInterfaceManager::getInstance();
2384 // reset UI
2385 CInterfaceGroup *createAccountUI = dynamic_cast<CInterfaceGroup*>(CWidgetManager::getInstance()->getElementFromId("ui:login:create_account"));
2386 if(createAccountUI)
2388 // show "submit interface", hide "login interface"
2389 CInterfaceGroup * grSubmit = dynamic_cast<CInterfaceGroup*>(createAccountUI->findFromShortId("submit_gr"));
2390 if(grSubmit)
2391 grSubmit->setActive(true);
2393 CInterfaceGroup * grLogin = dynamic_cast<CInterfaceGroup*>(createAccountUI->findFromShortId("login_gr"));
2394 if(grLogin)
2395 grLogin->setActive(false);
2397 // empty edit boxes
2398 std::vector< std::string > editBoxes(4);
2399 editBoxes[0] = "eb_login";
2400 editBoxes[1] = "eb_password";
2401 editBoxes[2] = "eb_confirm_password";
2402 editBoxes[3] = "eb_email";
2404 for(uint i=0; i<editBoxes.size(); i++)
2406 CGroupEditBox * eb = dynamic_cast<CGroupEditBox*>(createAccountUI->findFromShortId(editBoxes[i] + ":eb"));
2407 if(eb)
2408 eb->setInputString(std::string());
2411 // conditions button
2412 CCtrlBaseButton * but = dynamic_cast<CCtrlBaseButton*>(createAccountUI->findFromShortId("accept_cond"));
2413 if(but)
2414 but->setPushed(true);
2416 // get rules from url
2417 string url = ClientCfg.CreateAccountURL;
2418 CPatchManager *pPM = CPatchManager::getInstance();
2420 if (!CurlHttpClient.connect(url))
2422 nlwarning("Can't connect");
2423 return false;
2426 std::string lang = ClientCfg.LanguageCode;
2427 if(lang=="wk") lang = "uk";
2429 CurlHttpClient.verifyServer(true); // set this to false if you need to connect to the test environment
2431 std::string params = "language=" + lang;
2433 if (!LoginCustomParameters.empty())
2434 params += LoginCustomParameters;
2436 if(!CurlHttpClient.sendGet(url, params, pPM->isVerboseLog()))
2438 string errorMessage("Can't send (error code 60)");
2439 errorMessageBox(errorMessage);
2440 nlwarning(errorMessage.c_str());
2441 return false;
2444 string res;
2445 if(!CurlHttpClient.receive(res, pPM->isVerboseLog()))
2447 string errorMessage("Can't receive (error code 61)");
2448 errorMessageBox(errorMessage);
2449 nlwarning(errorMessage.c_str());
2450 return false;
2453 if(res.empty())
2455 string errorMessage("Empty result (error code 13)");
2456 errorMessageBox(errorMessage);
2457 nlwarning(errorMessage.c_str());
2458 return false;
2461 CurlHttpClient.disconnect();
2463 // initialize rules in interface
2464 std::vector< std::pair< std::string , std::string > > rules(5);
2465 rules[0] = std::pair<std::string , std::string>("rules_login", "id=tooltip-Username");
2466 rules[1] = std::pair<std::string , std::string>("rules_password", "id=tooltip-Password");
2467 rules[2] = std::pair<std::string , std::string>("rules_password_conf", "id=tooltip-ConfirmPass");
2468 rules[3] = std::pair<std::string , std::string>("rules_email", "id=tooltip-Email");
2469 rules[4] = std::pair<std::string , std::string>("rules_conditions", "id=tooltip-TaC");
2471 for(uint i=0; i<rules.size(); i++)
2473 CViewText * text = dynamic_cast<CViewText*>(createAccountUI->findFromShortId(rules[i].first));
2474 if(text)
2476 string tooltip = parseTooltip(res, rules[i].second);
2477 text->setHardText(tooltip);
2478 text->setActive(false);
2482 // welcome text
2483 CViewText * text = dynamic_cast<CViewText*>(createAccountUI->findFromShortId("errors_list"));
2484 if(text)
2486 text->setHardText(toString(CI18N::get("uiCreateAccountWelcome")));
2487 text->setColor(CRGBA(255, 255, 255, 255));
2489 CInterfaceGroup * group = dynamic_cast<CInterfaceGroup*>(createAccountUI->findFromShortId("erros_txt"));
2490 if(group)
2492 group->updateCoords();
2494 CInterfaceGroup * groupScroll = dynamic_cast<CInterfaceGroup*>(createAccountUI->findFromShortId("err_back_scrollbar"));
2495 if(groupScroll) groupScroll->setActive(group->getHReal() > group->getMaxHReal());
2496 CCtrlScroll * scroll = dynamic_cast<CCtrlScroll*>(createAccountUI->findFromShortId("err_scroll_bar"));
2497 if(scroll)
2498 scroll->setTrackPos(scroll->getHReal());
2502 // hide rules
2503 CInterfaceGroup * rulesGr = dynamic_cast<CInterfaceGroup*>(createAccountUI->findFromShortId("rules_gr"));
2504 if(rulesGr)
2505 rulesGr->setActive(false);
2507 // must be done after hide rules
2508 CAHManager::getInstance()->runActionHandler("set_keyboard_focus", NULL, "target=" CTRL_EDITBOX_CREATEACCOUNT_LOGIN "|select_all=false");
2512 NLGUI::CDBManager::getInstance()->getDbProp("UI:VARIABLES:SCREEN")->setValue32(UI_VARIABLES_SCREEN_CREATE_ACCOUNT);
2514 return true;
2517 // ***************************************************************************
2518 // Called when the user focus one of the edit boxes during the account creation
2519 class CAHCreateAccountRules : public IActionHandler
2521 virtual void execute (CCtrlBase * /* pCaller */, const string &Params)
2523 nlinfo("CAHCreateAccountRules called");
2525 CInterfaceManager *pIM = CInterfaceManager::getInstance();
2526 CInterfaceGroup *createAccountUI = dynamic_cast<CInterfaceGroup*>(CWidgetManager::getInstance()->getElementFromId("ui:login:create_account"));
2527 if(createAccountUI)
2529 CInterfaceGroup * rulesGr = dynamic_cast<CInterfaceGroup*>(createAccountUI->findFromShortId("rules_gr"));
2530 if(rulesGr)
2531 rulesGr->setActive(false);
2533 std::vector< std::string > rules(4);
2534 rules[0] = "rules_login";
2535 rules[1] = "rules_password";
2536 rules[2] = "rules_password_conf";
2537 rules[3] = "rules_email";
2539 for(uint i=0; i<rules.size(); i++)
2541 CViewText * text = dynamic_cast<CViewText*>(createAccountUI->findFromShortId(rules[i]));
2542 if(text)
2544 text->setActive(Params==rules[i]);
2545 if(Params==rules[i])
2547 if(rulesGr)
2548 rulesGr->setActive(!text->getText().empty());
2555 REGISTER_ACTION_HANDLER (CAHCreateAccountRules, "create_account_rules");
2557 // ***************************************************************************
2558 // Called when the user choose the account creation
2559 class CAHOnCreateAccount : public IActionHandler
2561 virtual void execute (CCtrlBase * /* pCaller */, const string &/* Params */)
2563 nlinfo("CAHOnCreateAccount called");
2565 LoginSM.pushEvent(CLoginStateMachine::ev_create_account);
2568 REGISTER_ACTION_HANDLER (CAHOnCreateAccount, "on_create_account");
2570 // ***************************************************************************
2571 // Called when the user submit the account creation
2572 class CAHOnCreateAccountSubmit : public IActionHandler
2574 virtual void execute (CCtrlBase * /* pCaller */, const string &/* Params */)
2576 nlinfo("CAHOnCreateAccountSubmit called");
2578 CInterfaceManager *pIM = CInterfaceManager::getInstance();
2580 CInterfaceGroup *createAccountUI = dynamic_cast<CInterfaceGroup*>(CWidgetManager::getInstance()->getElementFromId("ui:login:create_account"));
2581 if(createAccountUI)
2583 // recover data from UI
2584 std::vector< std::string > editBoxes(4);
2585 editBoxes[0] = "eb_login";
2586 editBoxes[1] = "eb_password";
2587 editBoxes[2] = "eb_confirm_password";
2588 editBoxes[3] = "eb_email";
2589 std::vector< std::string > results(4);
2591 for(uint i=0; i<editBoxes.size(); i++)
2593 CGroupEditBox * eb = dynamic_cast<CGroupEditBox*>(createAccountUI->findFromShortId(editBoxes[i] + ":eb"));
2594 if(eb)
2595 results[i] = eb->getInputString();
2598 // text
2599 CViewText * text = dynamic_cast<CViewText*>(createAccountUI->findFromShortId("email_adress"));
2600 if(text)
2601 text->setHardText(results[3]);
2603 // conditions button
2604 bool conditionsPushed = false;
2605 CCtrlBaseButton * but = dynamic_cast<CCtrlBaseButton*>(createAccountUI->findFromShortId("accept_cond"));
2606 if(but)
2607 conditionsPushed = !but->getPushed();
2609 string url = ClientCfg.CreateAccountURL;
2610 CPatchManager *pPM = CPatchManager::getInstance();
2612 if (!CurlHttpClient.connect(url))
2614 string errorMessage("Can't connect");
2615 errorMessageBox(errorMessage);
2616 nlwarning(errorMessage.c_str());
2617 return;
2620 std::string params = "Username=" + results[0] + "&Password=" + results[1]
2621 + "&ConfirmPass=" + results[2] + "&Email=" + results[3];
2623 if(conditionsPushed)
2624 params += "&TaC=1";
2626 if (!LoginCustomParameters.empty())
2627 params += LoginCustomParameters;
2629 std::string md5 = results[0] + results[1] + "" + results[3];
2630 md5 = NLMISC::getMD5((uint8*)md5.data(), (uint32)md5.size()).toString();
2632 params += "&SC=" + md5;
2633 std::string lang = ClientCfg.LanguageCode;
2634 if(lang=="wk") lang = "uk";
2635 params += "&Language=" + lang;
2637 CurlHttpClient.verifyServer(true); // set this to false if you need to connect to the test environment
2639 if(!CurlHttpClient.sendPost(url, params, pPM->isVerboseLog()))
2641 string errorMessage("Can't send (error code 60)");
2642 errorMessageBox(errorMessage);
2643 nlwarning(errorMessage.c_str());
2644 return;
2647 string res;
2648 if(!CurlHttpClient.receive(res, pPM->isVerboseLog()))
2650 string errorMessage("Can't receive (error code 61)");
2651 errorMessageBox(errorMessage);
2652 nlwarning(errorMessage.c_str());
2653 return;
2656 if(res.empty())
2658 string errorMessage("Empty result (error code 13)");
2659 errorMessageBox(errorMessage);
2660 nlwarning(errorMessage.c_str());
2661 return;
2664 CurlHttpClient.disconnect();
2666 // parse html
2667 string::size_type okPos = res.find("email_sent");
2668 if(okPos != string::npos)
2670 // show "submit interface", hide "login interface"
2671 CInterfaceGroup * grSubmit = dynamic_cast<CInterfaceGroup*>(createAccountUI->findFromShortId("submit_gr"));
2672 if(grSubmit)
2673 grSubmit->setActive(false);
2675 CInterfaceGroup * grLogin = dynamic_cast<CInterfaceGroup*>(createAccountUI->findFromShortId("login_gr"));
2676 if(grLogin)
2677 grLogin->setActive(true);
2679 else
2681 // initialize error comments in interface
2682 CViewText * text = dynamic_cast<CViewText*>(createAccountUI->findFromShortId("errors_list"));
2683 if(text)
2685 text->setColor(CRGBA(250, 30, 30, 255));
2687 std::vector< std::string > errors(5);
2688 errors[0] = "id=\"comment-Username\"";
2689 errors[1] = "id=\"comment-Password\"";
2690 errors[2] = "id=\"comment-ConfirmPass\"";
2691 errors[3] = "id=\"comment-Email\"";
2692 errors[4] = "id=\"comment-TaC\"";
2694 string error;
2695 for(uint i=0; i<errors.size(); i++)
2697 string comment = parseCommentError(res, errors[i]);
2698 if(!comment.empty())
2699 error += "- " + comment + "\n";
2702 text->setHardText(error);
2704 CInterfaceGroup * group = dynamic_cast<CInterfaceGroup*>(createAccountUI->findFromShortId("erros_txt"));
2705 if(group)
2707 group->updateCoords();
2709 CInterfaceGroup * groupScroll = dynamic_cast<CInterfaceGroup*>(createAccountUI->findFromShortId("err_back_scrollbar"));
2710 if(groupScroll) groupScroll->setActive(group->getHReal() > group->getMaxHReal());
2711 CCtrlScroll * scroll = dynamic_cast<CCtrlScroll*>(createAccountUI->findFromShortId("err_scroll_bar"));
2712 if(scroll)
2713 scroll->setTrackPos(scroll->getHReal());
2720 REGISTER_ACTION_HANDLER (CAHOnCreateAccountSubmit, "on_create_account_submit");
2722 // ***************************************************************************
2723 // Called when the user cancel the account creation
2724 class CAHOnCreateAccountClose : public IActionHandler
2726 virtual void execute (CCtrlBase * /* pCaller */, const string &/* Params */)
2728 nlinfo("CAHOnCreateAccountClose called");
2730 LoginSM.pushEvent(CLoginStateMachine::ev_close_create_account);
2733 REGISTER_ACTION_HANDLER (CAHOnCreateAccountClose, "on_create_account_close");
2735 // ***************************************************************************
2736 class CAHCreateAccountLogin : public IActionHandler
2738 virtual void execute (CCtrlBase * /* pCaller */, const string &/* Params */)
2740 nlinfo("CAHCreateAccountLogin called");
2742 CInterfaceManager *pIM = CInterfaceManager::getInstance();
2744 CInterfaceGroup *createAccountUI = dynamic_cast<CInterfaceGroup*>(CWidgetManager::getInstance()->getElementFromId("ui:login:create_account"));
2745 if(createAccountUI)
2747 CGroupEditBox * eb = dynamic_cast<CGroupEditBox*>(createAccountUI->findFromShortId("eb_login:eb"));
2748 if(eb)
2749 LoginLogin = eb->getInputString();
2751 eb = dynamic_cast<CGroupEditBox*>(createAccountUI->findFromShortId("eb_password:eb"));
2752 if(eb)
2753 LoginPassword = eb->getInputString();
2755 onlogin(false);
2759 REGISTER_ACTION_HANDLER (CAHCreateAccountLogin, "create_account_login");
2761 // ***************************************************************************
2762 // Called by html embeded lua script
2763 class CAHOnConnectToShard: public IActionHandler
2765 virtual void execute (CCtrlBase * /* pCaller */, const string &Params)
2767 // warning : pCaller is null when event come from lua scrip embeded in HTML
2768 Cookie = getParam(Params, "cookie");
2769 FSAddr = getParam(Params, "fsAddr");
2771 // replace the '_' with '|' in the cookie string
2772 for (uint i=0; i<Cookie.size(); ++i)
2774 if (Cookie[i] == '_')
2775 Cookie[i] = '|';
2778 setLoginFinished( true );
2779 loginOK = true;
2781 LoginSM.pushEvent(CLoginStateMachine::ev_connect);
2784 REGISTER_ACTION_HANDLER (CAHOnConnectToShard, "on_connect_to_shard");
2786 // ***************************************************************************
2787 // Called to return to login screen in case of error
2788 class CAHOnBackToLogin: public IActionHandler
2790 virtual void execute (CCtrlBase * /* pCaller */, const string &/* Params */)
2792 setLoginFinished( false );
2793 loginOK = false;
2794 LoginSM.pushEvent(CLoginStateMachine::ev_relog);
2796 // CInterfaceManager *pIM = CInterfaceManager::getInstance();
2797 // // need to reset password and current screen
2798 // NLGUI::CDBManager::getInstance()->getDbProp("UI:VARIABLES:SCREEN")->setValue32(UI_VARIABLES_SCREEN_CHECKPASS);
2801 REGISTER_ACTION_HANDLER (CAHOnBackToLogin, "on_back_to_login");
2803 // ***************************************************************************
2804 // ***************************************************************************
2805 // ***************************************************************************
2806 // NETWORK CONNECTION
2807 // ***************************************************************************
2808 // ***************************************************************************
2809 // ***************************************************************************
2812 // ***************************************************************************
2813 string checkLogin(const string &login, const string &password, const string &clientApp, const std::string &customParameters)
2815 CPatchManager *pPM = CPatchManager::getInstance();
2816 Shards.clear();
2818 if(ClientCfg.ConfigFile.exists("VerboseLog"))
2819 pPM->setVerboseLog(ClientCfg.ConfigFile.getVar("VerboseLog").asInt() == 1);
2820 if(pPM->isVerboseLog()) nlinfo("Using verbose log mode");
2822 if(!HttpClient.connectToLogin())
2823 return "Can't connect (error code 1)";
2825 if(pPM->isVerboseLog()) nlinfo("Connected");
2827 string res;
2829 std::string url = ClientCfg.ConfigFile.getVar("StartupHost").asString() + ClientCfg.ConfigFile.getVar("StartupPage").asString();
2831 // don't use login with alt method
2832 if (!login.empty())
2834 // ask server for salt
2835 if(!HttpClient.sendGet(url + "?cmd=ask&cp=2&login=" + login + "&lg=" + ClientCfg.LanguageCode, "", pPM->isVerboseLog()))
2836 return std::string("Can't send (error code 60) ") + HttpClient.lastError();
2838 if(pPM->isVerboseLog()) nlinfo("Sent request for password salt");
2840 if(!HttpClient.receive(res, pPM->isVerboseLog()))
2841 return "Can't receive (error code 61)";
2843 if(pPM->isVerboseLog()) nlinfo("Received request login check");
2845 if(res.empty())
2846 return "Empty answer from server (error code 62)";
2848 size_t first = res.find("\n\n");
2849 if (first == std::string::npos)
2851 first = res.find("\r\r");
2852 if (first == std::string::npos)
2854 first = res.find("\r\n\r\n");
2855 if (first != std::string::npos)
2857 res = res.substr(first + 4);
2860 else
2862 res = res.substr(first + 2);
2865 else
2867 res = res.substr(first + 2);
2870 nldebug("res1: %s", res.c_str());
2872 if (res[0] == 'H')
2874 nlwarning("missing response body: %s", res.c_str());
2875 return "missing response body (error code 64)";
2877 else if(res[0] == '0')
2879 // server returns an error
2880 nlwarning("server error: %s", res.substr(2).c_str());
2881 return res.substr(2);
2883 else if(res[0] == '1')
2885 Salt = res.substr(2);
2887 else
2889 // server returns ???
2890 nlwarning("%s", res.c_str());
2891 return res;
2894 // send login + crypted password + client app and cp=2 (as crypted password)
2895 if(!HttpClient.connectToLogin())
2896 return "Can't connect (error code 63)";
2898 if(pPM->isVerboseLog()) nlinfo("Connected");
2901 if (ClientCfg.R2Mode)
2903 // R2 login sequence
2905 if (!login.empty())
2907 std::string cryptedPassword = CCrypt::crypt(password, Salt);
2909 if(!HttpClient.sendGet(url + "?cmd=login&login=" + login + "&password=" + cryptedPassword + "&clientApplication=" + clientApp + "&cp=2" + "&lg=" + ClientCfg.LanguageCode + customParameters))
2910 return std::string("Can't send (error code 2) ") + HttpClient.lastError();
2912 else
2914 // don't send login and password if empty
2915 if(!HttpClient.sendGet(url + "?cmd=login&clientApplication=" + clientApp + "&cp=2" + "&lg=" + ClientCfg.LanguageCode + customParameters))
2916 return std::string("Can't send (error code 2) ") + HttpClient.lastError();
2919 // the response should contains the result code and the cookie value
2920 if(pPM->isVerboseLog()) nlinfo("Sent request login check");
2922 if(!HttpClient.receive(res, pPM->isVerboseLog()))
2923 return "Can't receive (error code 3)";
2925 if(pPM->isVerboseLog()) nlinfo("Received request login check");
2927 if(res.empty())
2928 return "Empty answer from server (error code 4)";
2930 size_t first = res.find("\n\n");
2931 if (first == std::string::npos)
2933 first = res.find("\r\r");
2934 if (first == std::string::npos)
2936 first = res.find("\r\n\r\n");
2937 if (first != std::string::npos)
2939 res = res.substr(first + 4);
2942 else
2944 res = res.substr(first + 2);
2947 else
2949 res = res.substr(first + 2);
2952 nldebug("res2: %s", res.c_str());
2954 if (res[0] == 'H')
2956 nlwarning("missing response body: %s", res.c_str());
2957 return "missing response body (error code 65)";
2959 else if(res[0] == '0')
2961 // server returns an error
2962 nlwarning("server error: %s", res.substr(2).c_str());
2963 return res.substr(2);
2965 else if(res[0] == '1')
2967 //nlwarning(res.c_str());
2968 vector<string> lines;
2969 explode(res, std::string("\n"), lines, false);
2970 if (lines.size() != 2)
2972 return toString("Invalid server return, found %u lines, want 2", lines.size());
2975 vector<string> parts;
2976 explode(lines[0], std::string("#"), parts, false);
2977 if (parts.size() < 5)
2978 return "Invalid server return, missing cookie and/or Ring URLs";
2980 // server returns ok, we have the cookie
2982 // store the cookie value and FS address for next page request
2983 CurrentCookie = parts[1];
2984 Cookie = CurrentCookie;
2985 FSAddr = parts[2];
2987 // store the ring startup page
2988 RingMainURL = parts[3];
2989 FarTP.setURLBase(parts[4]);
2991 if(parts.size() >= 6 && parts[5] == "1")
2993 // we want stats
2994 extern bool startStat;
2995 startStat = true;
2998 // parse the second line (contains the domain info)
2999 parts.clear();
3000 explode(lines[1], std::string("#"), parts, false);
3001 if (parts.size() < 3)
3002 return "Invalid server return, missing patch URLs";
3004 R2ServerVersion = parts[0].c_str();
3005 R2BackupPatchURL = parts[1];
3006 explode(parts[2], std::string(" "), R2PatchURLs, true);
3008 else
3010 // unexpected content
3011 #if !FINAL_VERSION
3012 string ret = toString("DEV : Invalid server return, missing return code in \n%s", res.c_str());
3013 return ret;
3014 #else
3015 return "Invalid server return, missing return code";
3016 #endif
3020 else
3022 // standard ryzom login sequence
3023 std::string cryptedPassword = CCrypt::crypt(password, Salt);
3025 if(!HttpClient.sendGet(url + "?login=" + login + "&password=" + cryptedPassword + "&clientApplication=" + clientApp + "&cp=2"))
3026 return std::string("Can't send (error code 2) ") + HttpClient.lastError();
3028 if(!send(ClientCfg.ConfigFile.getVar("StartupPage").asString()+"?login="+login+"&password="+password+"&clientApplication="+clientApp))
3029 return "Can't send (error code 2)";
3031 if(pPM->isVerboseLog()) nlinfo("Sent request login check");
3033 if(!HttpClient.receive(res, pPM->isVerboseLog()))
3034 return "Can't receive (error code 3)";
3036 if(pPM->isVerboseLog()) nlinfo("Received request login check");
3038 if(res.empty())
3039 return "Empty answer from server (error code 4)";
3041 size_t first = res.find("\n\n");
3042 if (first == std::string::npos)
3044 first = res.find("\r\r");
3045 if (first == std::string::npos)
3047 first = res.find("\r\n\r\n");
3048 if (first != std::string::npos)
3050 res = res.substr(first + 4);
3053 else
3055 res = res.substr(first + 2);
3058 else
3060 res = res.substr(first + 2);
3063 nldebug("res2: %s", res.c_str());
3065 if (res[0] == 'H')
3067 nlwarning("missing response body: %s", res.c_str());
3068 return "missing response body (error code 66)";
3070 else if(res[0] == '0')
3072 // server returns an error
3073 nlwarning("server error: %s", res.substr(2).c_str());
3074 return res.substr(2);
3076 else if(res[0] == '1')
3078 // server returns ok, we have the list of shard
3079 uint nbs;
3080 fromString(res.substr(2), nbs);
3081 vector<string> lines;
3083 explode(res, std::string("\n"), lines, true);
3085 if(pPM->isVerboseLog())
3087 nlinfo ("Exploded, with nl, %u res", (uint)lines.size());
3088 /* for (uint i = 0; i < lines.size(); i++)
3090 nlinfo (" > '%s'", lines[i].c_str());
3094 if(lines.size() != nbs+1)
3096 nlwarning("bad shard lines number %u != %d", (uint)lines.size(), nbs+1);
3097 nlwarning("'%s'", res.c_str());
3098 return "bad lines numbers (error code 5)";
3101 for(uint i = 1; i < lines.size(); i++)
3103 vector<string> res;
3104 explode(lines[i], std::string("|"), res);
3106 if(pPM->isVerboseLog())
3108 nlinfo ("Exploded with '%s', %u res", "|", (uint)res.size());
3109 /* for (uint i = 0; i < res.size(); i++)
3111 nlinfo (" > '%s'", res[i].c_str());
3115 if (res.size() < 7 && res.size() > 8)
3117 nlwarning("bad | numbers %u != %d", (uint)res.size(), 8);
3118 nlwarning("'%s'", lines[i].c_str());
3119 return "bad pipe numbers (error code 6)";
3121 bool online;
3122 fromString(res[1], online);
3123 uint32 shardId;
3124 fromString(res[2], shardId);
3125 uint32 nbPlayers;
3126 fromString(res[4], nbPlayers);
3127 Shards.push_back(CShard(res[0], online, shardId, res[3], nbPlayers, res[5], res[6]));
3128 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());
3129 if (res.size() == 8)
3131 explode(res[7], std::string(" "), Shards.back().PatchURIs);
3135 else
3137 // server returns ???
3138 nlwarning("%s", res.c_str());
3139 return res;
3143 return "";
3146 // ***************************************************************************
3147 string selectShard(uint32 shardId, string &cookie, string &addr)
3149 cookie.clear();
3150 addr.clear();
3152 if(!HttpClient.connectToLogin()) return "Can't connect (error code 7)";
3154 if(LoginLogin.empty()) return "Empty Login (error code 8)";
3155 if(LoginPassword.empty()) return "Empty Password (error code 9)";
3156 if(ClientApp.empty()) return "Empty Client Application (error code 10)";
3158 // send login + crypted password + client app and cp=2 (as crypted password)
3159 std::string cryptedPassword = CCrypt::crypt(LoginPassword, Salt);
3161 std::string url = ClientCfg.ConfigFile.getVar("StartupHost").asString() + ClientCfg.ConfigFile.getVar("StartupPage").asString();
3163 if(!HttpClient.sendGet(url + "?cmd=login&shardid=" + toString(shardId) + "&login=" + LoginLogin + "&password=" + cryptedPassword + "&clientApplication=" + ClientApp + "&cp=2"))
3164 return "Can't send (error code 11)";
3166 string res;
3168 CPatchManager *pPM = CPatchManager::getInstance();
3169 if(!HttpClient.receive(res, pPM->isVerboseLog()))
3170 return "Can't receive (error code 12)";
3172 if(res.empty())
3173 return "Empty result (error code 13)";
3175 size_t first = res.find("\n\n");
3176 if (first == std::string::npos)
3178 first = res.find("\r\r");
3179 if (first == std::string::npos)
3181 first = res.find("\r\n\r\n");
3182 if (first != std::string::npos)
3184 res = res.substr(first + 4);
3187 else
3189 res = res.substr(first + 2);
3192 else
3194 res = res.substr(first + 2);
3197 nldebug("res2: %s", res.c_str());
3199 if (res[0] == 'H')
3201 nlwarning("missing response body: %s", res.c_str());
3202 return "missing response body (error code 66)";
3204 else if(res[0] == '0')
3206 // server returns an error
3207 nlwarning("server error: %s", res.substr(2).c_str());
3208 return res.substr(2);
3210 else if(res[0] == '1')
3212 // server returns ok, we have the access
3214 vector<string> line;
3215 explode(res, std::string(" "), line, true);
3217 if (line.size() < 2 || line.size() > 3)
3219 nlwarning("bad launch lines number %d != %d", line.size(), 2);
3220 return "bad launch line number (error code 14)";
3223 cookie = line[0].substr(2);
3224 addr = line[1];
3226 std::vector<std::string> patchURIs;
3228 CShard* shard = NULL;
3229 uint i;
3230 for (i=0; i<Shards.size(); ++i)
3232 if (Shards[i].ShardId == shardId)
3234 shard = &Shards[i];
3235 break;
3239 if (shard != NULL && line.size() >= 3)
3241 explode(line[2], "|", shard->PatchURIs, true);
3243 nlinfo("received %d main patch server URIs:", shard->PatchURIs.size());
3244 uint i;
3245 for (i=0; i<shard->PatchURIs.size(); ++i)
3246 nlinfo("%d: '%s'", i, shard->PatchURIs[i].c_str());
3250 else
3252 // server returns ???
3253 nlwarning("%s", res.c_str());
3254 return res;
3257 return "";
3261 /*void mainLandPatch()
3263 if (!AvailablePatchs) return;
3264 nlassert(AvailablePatchs & (1 << BGDownloader::DownloadID_MainLand)); // only handled case for now
3265 // no-op
3266 BGDownloaderWantedPatch = BGDownloader::DownloadID_MainLand;
3267 CInterfaceManager *im = CInterfaceManager::getInstance();
3268 im->initLogin();
3269 // login machine should be in the 'end' state !!
3270 nlassert(LoginSM.getCurrentState() == CLoginStateMachine::st_end);
3271 LoginSM.pushEvent(CLoginStateMachine::ev_mainland_patch);
3272 loginMainLoop(); // patch is handled in the login mainloop
3273 // there should have been a reboot there, so quit if something went wrong...
3274 release();
3275 exit(0);
3281 // ***************************************************************************
3282 // ***************************************************************************
3283 // INTRO HANDLING
3284 // ***************************************************************************
3285 // ***************************************************************************
3287 #include "init_main_loop.h"
3289 bool loginIntroSkip;
3291 void loginIntro()
3293 // Display of nevrax logo is done at init time (see init.cpp) just before addSearchPath (second one)
3294 #if 0
3295 for (uint i = 0; i < 1; i++) // previously display nevrax then nvidia
3297 if (i != 0)
3299 beginLoading(IntroNVidia);
3300 string nmsg("");
3301 ProgressBar.newMessage (nmsg);
3304 Driver->AsyncListener.reset();
3305 updateClientTime();
3306 CInputHandlerManager::getInstance()->pumpEventsNoIM();
3307 updateClientTime();
3309 loginIntroSkip = false;
3311 sint64 CurTime = T0;
3313 while (loginIntroSkip == false)
3315 updateClientTime();
3316 if ((T0 - CurTime) > 5000) // 5s before quiting
3317 break;
3318 // Update messages
3319 CInputHandlerManager::getInstance()->pumpEventsNoIM();
3321 // Exit ?
3322 if (Driver->AsyncListener.isKeyPushed (KeyESCAPE) || Driver->AsyncListener.isKeyPushed (KeyRETURN) ||
3323 Driver->AsyncListener.isKeyPushed (KeySPACE))
3324 break;
3326 const string nmsg("");
3327 ProgressBar.newMessage (nmsg);
3328 IngameDbMngr.flushObserverCalls();
3329 NLGUI::CDBManager::getInstance()->flushObserverCalls();
3332 #endif
3333 beginLoading(StartBackground);
3334 ProgressBar.finish();