Use configured resolution for login/outgame/ingame
[ryzomcore.git] / ryzom / client / src / init.cpp
blob87b16d1bf2aa4542144eb257ecc30e49806039b7
1 // Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
2 // Copyright (C) 2010-2020 Winch Gate Property Limited
3 //
4 // This source file has been modified by the following contributors:
5 // Copyright (C) 2010 Robert TIMM (rti) <mail@rtti.de>
6 // Copyright (C) 2010-2020 Jan BOON (Kaetemi) <jan.boon@kaetemi.be>
7 // Copyright (C) 2013 Laszlo KIS-ADAM (dfighter) <dfighter1985@gmail.com>
8 //
9 // This program is free software: you can redistribute it and/or modify
10 // it under the terms of the GNU Affero General Public License as
11 // published by the Free Software Foundation, either version 3 of the
12 // License, or (at your option) any later version.
14 // This program is distributed in the hope that it will be useful,
15 // but WITHOUT ANY WARRANTY; without even the implied warranty of
16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 // GNU Affero General Public License for more details.
19 // You should have received a copy of the GNU Affero General Public License
20 // along with this program. If not, see <http://www.gnu.org/licenses/>.
24 #include "stdpch.h"
27 //////////////
28 // INCLUDES //
29 //////////////
30 // Misc.
31 #include "nel/misc/debug.h"
32 #include "nel/misc/displayer.h"
33 #include "nel/misc/path.h"
34 #include "nel/misc/i18n.h"
35 #include "nel/misc/log.h"
36 #include "nel/misc/sheet_id.h"
37 #include "nel/misc/report.h"
38 #include "nel/misc/class_registry.h"
39 #include "nel/misc/system_info.h"
40 #include "nel/misc/block_memory.h"
41 #include "nel/misc/system_utils.h"
42 #include "nel/misc/streamed_package_manager.h"
43 #include "nel/web/http_package_provider.h"
44 #include "nel/misc/cmd_args.h"
45 // 3D Interface.
46 #include "nel/3d/bloom_effect.h"
47 #include "nel/3d/u_driver.h"
48 #include "nel/3d/u_text_context.h"
49 #include "nel/3d/u_shape_bank.h"
50 #include "nel/3d/stereo_hmd.h"
51 // Net.
52 #include "nel/net/email.h"
53 // Ligo.
54 #include "nel/ligo/ligo_config.h"
56 // Client
57 #include "init.h"
58 #include "input.h"
59 #include "client_cfg.h" // Configuration of the client.
60 #include "actions_client.h"
61 #include "color_slot_manager.h"
62 #include "movie_shooter.h"
63 #include "continent_manager.h"
64 #include "interface_v3/animal_position_state.h"
65 //#include "osd_client.h"
66 #include "debug_client.h"
67 #include "ingame_database_manager.h"
68 #include "client_chat_manager.h"
69 #include "interface_v3/input_handler_manager.h"
70 #include "interface_v3/interface_manager.h"
71 //#include "crtdbg.h"
72 #include "sound_manager.h"
73 #include "net_manager.h"
74 #include "sheet_manager.h"
76 #include "interface_v3/sbrick_manager.h"
77 #include "nel/gui/widget_manager.h"
78 #include "nel/gui/http_cache.h"
79 #include "nel/gui/http_hsts.h"
81 #include "gabarit.h"
82 #include "hair_set.h"
83 //#include "starting_roles.h"
85 #include "init_main_loop.h"
87 #include "resource.h"
89 #include "time_client.h"
90 #include "pacs_client.h"
91 #include "interface_v3/music_player.h"
93 #include "input.h"
94 #include "interface_v3/add_on_manager.h"
96 #include "bg_downloader_access.h"
97 #include "user_agent.h"
99 #include "nel/misc/check_fpu.h"
101 #include "login_progress_post_thread.h"
103 #include "browse_faq.h"
105 // XMLLib
106 #include <libxml/xmlmemory.h>
108 #ifdef NL_OS_WINDOWS
109 #include <windows.h>
110 extern HINSTANCE HInstance;
111 extern HWND SlashScreen;
112 #endif // NL_OS_WINDOWS
114 #ifdef NL_OS_MAC
115 #include <stdio.h>
116 #include <sys/resource.h>
117 #include "nel/misc/dynloadlib.h"
118 #endif
120 #include "app_bundle_utils.h"
122 #include <new>
124 #ifdef DEBUG_NEW
125 #define new DEBUG_NEW
126 #endif
128 ///////////
129 // USING //
130 ///////////
131 using namespace NLMISC;
132 using namespace NLNET;
133 using namespace NL3D;
134 using namespace NLLIGO;
135 using namespace std;
137 // NVIDIA recommanded drivers
138 #define NVIDIA_RECOMMANDED_DRIVERS UINT64_CONSTANT(0x0006000e000a1820)
139 #define NVIDIA_RECOMMANDED_DRIVERS_STRING_TEST "nvidia"
140 #define NVIDIA_RECOMMANDED_DRIVERS_STRING_NTEST "go"
141 #define NVIDIA_RECOMMANDED_DRIVERS_VENDOR "NVIDIA"
142 #define NVIDIA_RECOMMANDED_DRIVERS_URL "http://www.nvidia.com/drivers"
144 // ATI recommanded drivers
145 #define ATI_RECOMMANDED_DRIVERS UINT64_CONSTANT(0x0006000e000a191e)
146 #define ATI_RECOMMANDED_DRIVERS_STRING_TEST "radeon"
147 #define ATI_RECOMMANDED_DRIVERS_VENDOR "ATI Technologies Inc."
148 #define ATI_RECOMMANDED_DRIVERS_URL "http://www.ati.com/support/driver.html"
150 // ProgressBar steps in init / connection phase
151 #define BAR_STEP_INIT_CONNECTION 17
153 /////////////
154 // GLOBALS //
155 /////////////
156 // Ligo primitive class
157 CLigoConfig LigoConfig;
159 CClientChatManager ChatMngr;
161 bool LastScreenSaverEnabled = false;
164 extern void registerInterfaceElements();
165 extern CContinentManager ContinentMngr;
167 extern NLMISC::CCmdArgs Args;
169 // Tips of the day count
170 #define RZ_NUM_TIPS 17
171 std::string TipsOfTheDay;
172 uint TipsOfTheDayIndex;
174 // includes for following register classes
175 #include "entities.h"
176 #include "character_cl.h"
177 #include "player_cl.h"
178 #include "user_entity.h"
179 #include "fx_cl.h"
180 #include "item_cl.h"
182 ///////////////
183 // FUNCTIONS //
184 ///////////////
186 // ***************************************************************************
189 // XML allocator functions
190 // Due to Bug #906, we disable the stl xml allocation
192 static volatile bool XmlAllocUsesSTL = true;
194 static std::allocator<uint8> xmlStlAlloc;
198 void XmlFree4NeL (void *ptr)
200 // if (XmlAllocUsesSTL)
202 int size = *(((int *) ptr) - 1);
203 xmlStlAlloc.deallocate((uint8 *) ptr - sizeof(int), size + sizeof(int));
205 // else
206 // {
207 // MemoryDeallocate (ptr);
208 // }
211 void *XmlMalloc4NeL (size_t size)
213 // if (XmlAllocUsesSTL)
215 int *newB = (int *) xmlStlAlloc.allocate(size + sizeof(int));
216 *newB = (int)size;
217 return (void *) (newB + 1);
219 // else
220 // {
221 // return MemoryAllocate(size);
222 // }
225 void *XmlRealloc4NeL (void *ptr, size_t size)
227 // if (XmlAllocUsesSTL)
229 if (ptr == NULL) return XmlMalloc4NeL(size);
230 int oldSize = *(((int *) ptr) - 1);
231 if (oldSize == (int) size) return ptr;
232 void *newB = XmlMalloc4NeL(size);
233 memcpy(newB, ptr, std::min(oldSize, (int) size));
234 XmlFree4NeL(ptr);
235 return newB;
237 // else
238 // {
239 // // Get the block size
240 // return MemoryReallocate (ptr, size);
241 // }
244 char *XmlStrdup4NeL (const char *str)
246 nlassert (str);
247 char *newStr;
248 // if (XmlAllocUsesSTL)
250 newStr = (char *) XmlMalloc4NeL(strlen (str)+1);
252 // else
253 // {
254 // newStr = (char*)MemoryAllocate(strlen (str)+1);
255 // }
256 strcpy (newStr, str);
257 return newStr;
262 #ifdef NL_OS_WINDOWS
265 static std::wstring CurrentErrorMessage;
267 static INT_PTR CALLBACK ExitClientErrorDialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM /* lParam */)
269 switch(uMsg)
271 case WM_INITDIALOG:
273 if (CI18N::hasTranslation("TheSagaOfRyzom"))
275 if (!SetWindowTextW(hwndDlg, nlUtf8ToWide(CI18N::get("TheSagaOfRyzom").c_str())))
277 nlwarning("SetWindowText failed: %s", formatErrorMessage(getLastError()).c_str());
280 SetDlgItemTextW(hwndDlg, IDC_ERROR_MSG_TEXT, (WCHAR*)CurrentErrorMessage.c_str());
281 if (CI18N::hasTranslation("uiRyzomErrorMsgBoxExit"))
283 SetDlgItemTextW(hwndDlg, IDOK, nlUtf8ToWide(CI18N::get("uiRyzomErrorMsgBoxExit").c_str()));
285 if (CI18N::hasTranslation("uiRyzomErrorMsgBoxHelp"))
287 SetDlgItemTextW(hwndDlg, IDC_RYZOM_ERROR_HELP, nlUtf8ToWide(CI18N::get("uiRyzomErrorMsgBoxHelp").c_str()));
289 RECT rect;
290 RECT rectDesktop;
291 GetWindowRect (hwndDlg, &rect);
292 GetWindowRect (GetDesktopWindow (), &rectDesktop);
293 SetWindowPos (hwndDlg, HWND_TOPMOST, (rectDesktop.right-rectDesktop.left-rect.right+rect.left)/2, (rectDesktop.bottom-rectDesktop.top-rect.bottom+rect.top)/2, 0, 0, SWP_NOSIZE);
294 HICON exitClientDlgIcon = LoadIcon(HInstance, MAKEINTRESOURCE(IDI_MAIN_ICON));
295 ::SendMessageA(hwndDlg, WM_SETICON, (WPARAM) ICON_BIG, (LPARAM) exitClientDlgIcon);
297 break;
298 case WM_COMMAND:
299 switch(LOWORD(wParam))
301 case IDOK:
302 EndDialog(hwndDlg, IDOK);
303 break;
304 case IDC_RYZOM_ERROR_HELP:
306 if (Driver)
308 HWND wnd = Driver->getDisplay();
309 ShowWindow(wnd, SW_MINIMIZE);
311 browseFAQ(ClientCfg.ConfigFile);
312 EndDialog(hwndDlg, IDOK);
314 break;
316 break;
317 case WM_CLOSE:
318 EndDialog(hwndDlg, IDOK);
319 break;
321 return FALSE;
324 #endif
328 // Use this function to return an error to the final user and exit the client
329 void ExitClientError (const char *format, ...)
331 char *str;
332 NLMISC_CONVERT_VARGS (str, format, 256/*NLMISC::MaxCStringSize*/);
334 // Driver ?
335 if (Driver)
337 Driver->release();
340 #ifdef NL_OS_WINDOWS
341 CurrentErrorMessage = NLMISC::utf8ToWide(str);
342 DialogBox(HInstance, MAKEINTRESOURCE(IDD_ERROR_HELP_MESSAGE_BOX), NULL, ExitClientErrorDialogProc);
344 MessageBoxW (NULL, nlUtf8ToWide(str.c_str()), nlUtf8ToWide(CI18N::get("TheSagaOfRyzom").c_str()), MB_OK|MB_ICONERROR);
346 #else
347 fprintf (stderr, "%s\n", str);
348 #endif
349 // Exit
350 extern void quitCrashReport ();
351 quitCrashReport ();
352 NLMISC::NL3D_BlockMemoryAssertOnPurge = false; // at this point some object may remain allocated
353 // so don't want to fire an assert here
354 exit (EXIT_FAILURE);
357 // Use this function to return an information to the final user
358 void ClientInfo (const std::string &message)
360 #ifdef NL_OS_WINDOWS
361 MessageBoxW(NULL, nlUtf8ToWide(message.c_str()), nlUtf8ToWide(CI18N::get("TheSagaOfRyzom").c_str()), MB_OK|MB_ICONINFORMATION);
362 #endif
365 // Use this function to ask a question to the final user
366 bool ClientQuestion (const std::string &message)
368 #ifdef NL_OS_WINDOWS
369 return MessageBoxW(NULL, nlUtf8ToWide(message.c_str()), nlUtf8ToWide(CI18N::get("TheSagaOfRyzom").c_str()), MB_YESNO|MB_ICONQUESTION) != IDNO;
370 #else
371 return false;
372 #endif
375 void selectTipsOfTheDay (uint /* tips */)
377 /* todo tips of the day uncomment
378 tips %= RZ_NUM_TIPS;
379 TipsOfTheDayIndex = tips;
380 string title = CI18N::get ("uiTipsTitle");
381 title += toString (tips+1);
382 title += " : ";
383 TipsOfTheDay = title+CI18N::get ("uiTips"+toString (tips));*/
384 // todo tips of the day remove
385 //trap TipsOfTheDay = CI18N::get ("uiMessageOfTheDay");
386 TipsOfTheDay.clear(); //trap
389 // ***************************************************************************
391 // For nel memory
392 void outOfMemory()
394 nlstopex (("OUT OF MEMORY"));
397 uint64 Debug_OldCPUMask = 0;
398 uint64 Debug_NewCPUMask = 0;
400 // For multi cpu, active only one CPU for the main thread
401 void setCPUMask(uint64 userCPUMask)
403 uint64 cpuMask = IProcess::getCurrentProcess()->getCPUMask();
404 Debug_OldCPUMask = cpuMask;
406 // if user CPU mask is valid
407 if (cpuMask & userCPUMask)
409 // use it
410 IProcess::getCurrentProcess ()->setCPUMask(cpuMask & userCPUMask);
412 else
414 // else get first available CPU
416 // get the processor to allow process
417 uint i = 0;
418 while ((i < 64) && ((cpuMask & (UINT64_CONSTANT(1) << i)) == 0))
419 i++;
421 // Set the CPU mask
422 if (i < 64)
424 IProcess::getCurrentProcess ()->setCPUMask(UINT64_CONSTANT(1) << i);
428 // check
429 cpuMask = IProcess::getCurrentProcess ()->getCPUMask();
430 Debug_NewCPUMask = cpuMask;
433 void displayCPUInfo()
435 nlinfo("CPUInfo: CPUMask before change: %x, after change: %x, CPUID: %x, hasHyperThreading: %s", (uint32)Debug_OldCPUMask, (uint32)Debug_NewCPUMask, CSystemInfo::getCPUID(), (CSystemInfo::hasHyperThreading()?"YES":"NO"));
438 string getVersionString (uint64 version)
440 return toString ("%u.%u.%u.%u", (unsigned int) (version >> 48), (unsigned int) ((version >> 32) & 0xffff), (unsigned int) ((version >> 16) & 0xffff), (unsigned int) (version & 0xffff));
444 string getSystemInformation()
446 string s;
447 s += "Memory: " + bytesToHumanReadable(CSystemInfo::availablePhysicalMemory()) + "/" + bytesToHumanReadable(CSystemInfo::totalPhysicalMemory()) + "\n";
448 s += "Process Virtual Memory: " + bytesToHumanReadable(CSystemInfo::virtualMemory()) + "\n";
449 s += "OS: " + CSystemInfo::getOS() + "\n";
450 s += "Processor: " + CSystemInfo::getProc() + "\n";
451 s += toString("CPUID: %x\n", CSystemInfo::getCPUID());
452 s += toString("HT: %s\n", CSystemInfo::hasHyperThreading()?"YES":"NO");
453 s += toString("CpuMask: %x\n", IProcess::getCurrentProcess ()->getCPUMask());
456 if(Driver)
457 s += "NeL3D: " + string(Driver->getVideocardInformation()) + "\n";
458 else
459 s += "NeL3D: No driver\n";
461 // More display info
462 string deviceName;
463 uint64 driverVersion;
464 if (CSystemInfo::getVideoInfo (deviceName, driverVersion))
466 s += "3DCard: ";
467 s += deviceName;
468 s += ", version ";
469 s += getVersionString (driverVersion) + "\n";
472 if (SoundMngr && SoundMngr->getMixer())
473 SoundMngr->getMixer()->writeProfile (s);
474 else
475 s += "No sound\n";
477 return s;
480 static string crashCallback()
482 string s = getDebugInformation();
483 s += getSystemInformation();
485 #ifdef NL_OS_WINDOWS
486 if (Driver)
488 NL3D::UDriver::CMode mode;
489 Driver->getCurrentScreenMode(mode);
490 if (!mode.Windowed)
492 HWND wnd = Driver->getDisplay();
493 ShowWindow(wnd, SW_MINIMIZE);
496 #endif
499 return s;
502 void checkDriverVersion()
504 string deviceName;
505 uint64 driverVersion;
506 if (CSystemInfo::getVideoInfo (deviceName, driverVersion))
508 static uint64 driversVersion[]=
510 NVIDIA_RECOMMANDED_DRIVERS,
511 ATI_RECOMMANDED_DRIVERS
513 static const char *driversTest[]=
515 NVIDIA_RECOMMANDED_DRIVERS_STRING_TEST,
516 ATI_RECOMMANDED_DRIVERS_STRING_TEST
518 static const char *driversNTest[]=
520 NVIDIA_RECOMMANDED_DRIVERS_STRING_NTEST,
521 NULL
523 static const char *driversURL[]=
525 NVIDIA_RECOMMANDED_DRIVERS_URL,
526 ATI_RECOMMANDED_DRIVERS_URL
528 static const char *driversVendor[]=
530 NVIDIA_RECOMMANDED_DRIVERS_VENDOR,
531 ATI_RECOMMANDED_DRIVERS_VENDOR,
534 uint i;
535 for (i=0; i< sizeofarray(driversVersion); i++)
537 string lwr = toLowerAscii(deviceName);
538 if ((lwr.find (driversTest[i])!=string::npos) && (driversNTest[i]==NULL || lwr.find (driversNTest[i])==string::npos))
540 if (driverVersion < driversVersion[i])
542 string message = CI18N::get ("uiUpdateDisplayDriversNotUpToDate") + "\n\n";
543 // message += CI18N::get ("uiUpdateDisplayDriversVendor") + driversVendor[i] + "\n";
544 message += CI18N::get ("uiUpdateDisplayDriversCard") + deviceName + "\n";
545 message += CI18N::get ("uiUpdateDisplayDriversCurrent") + getVersionString (driverVersion) + "\n";
546 message += CI18N::get ("uiUpdateDisplayDriversRecommanded") + getVersionString (driversVersion[i]) + "\n\n";
547 message += CI18N::get ("uiUpdateDisplayDrivers") + "\n";
548 if (ClientQuestion (message))
550 openURL(driversURL[i]);
551 extern void quitCrashReport ();
552 quitCrashReport ();
553 exit (EXIT_FAILURE);
556 break;
559 if (i==sizeof (driversVersion)/sizeof(uint))
560 nlwarning ("Unknown video card : %s", deviceName.c_str());
562 else
563 nlwarning ("Can't check video driver version");
566 void checkDriverDepth ()
568 // Check desktop is in 32 bit else no window mode allowed.
569 if (ClientCfg.Windowed)
571 nlassert (Driver);
572 UDriver::CMode mode;
573 Driver->getCurrentScreenMode(mode);
574 #ifdef NL_OS_WINDOWS
575 if (mode.Depth != 32)
576 #else
577 if (mode.Depth != 16 && mode.Depth != 24 && mode.Depth != 32)
578 #endif
579 ExitClientError (CI18N::get ("uiDesktopNotIn32").c_str ());
583 void listStereoDisplayDevices(std::vector<NL3D::CStereoDeviceInfo> &devices)
585 bool cache = VRDeviceCache.empty();
586 nldebug("VR [C]: List devices");
587 if (cache)
589 VRDeviceCache.push_back(std::pair<std::string, std::string>("Auto", "0"));
591 IStereoDisplay::listDevices(devices);
592 for (std::vector<NL3D::CStereoDeviceInfo>::iterator it(devices.begin()), end(devices.end()); it != end; ++it)
594 std::string name = toString("%s - %s - %s", IStereoDisplay::getLibraryName(it->Library), it->Manufacturer.c_str(), it->ProductName.c_str());
595 std::string fullname = toString("[%s] [%s]", name.c_str(), it->Serial.c_str());
596 nlinfo("VR [C]: Stereo Display: %s", name.c_str());
597 if (cache)
599 VRDeviceCache.push_back(std::pair<std::string, std::string>(name, it->Serial)); // VR_CONFIG
604 void cacheStereoDisplayDevices() // VR_CONFIG
606 if (VRDeviceCache.empty())
608 std::vector<NL3D::CStereoDeviceInfo> devices;
609 listStereoDisplayDevices(devices);
613 void initStereoDisplayDevice()
615 if (ClientCfg.VREnable)
617 // VR_CONFIG
618 nldebug("VR [C]: Enabled");
619 std::vector<NL3D::CStereoDeviceInfo> devices;
620 listStereoDisplayDevices(devices);
621 CStereoDeviceInfo *deviceInfo = NULL;
622 if (ClientCfg.VRDisplayDevice == std::string("Auto"))
624 for (std::vector<NL3D::CStereoDeviceInfo>::iterator it(devices.begin()), end(devices.end()); it != end; ++it)
626 if ((*it).AllowAuto)
628 deviceInfo = &(*it);
629 break;
633 else
635 for (std::vector<NL3D::CStereoDeviceInfo>::iterator it(devices.begin()), end(devices.end()); it != end; ++it)
637 std::string name = toString("%s - %s - %s", IStereoDisplay::getLibraryName(it->Library), it->Manufacturer.c_str(), it->ProductName.c_str());
638 if (name == ClientCfg.VRDisplayDevice)
639 deviceInfo = &(*it);
640 if (ClientCfg.VRDisplayDeviceId == it->Serial)
641 break;
644 if (deviceInfo)
646 nlinfo("VR [C]: Create VR stereo display device");
647 StereoDisplay = IStereoDisplay::createDevice(*deviceInfo);
648 if (StereoDisplay)
650 if (deviceInfo->Class == CStereoDeviceInfo::StereoHMD)
652 nlinfo("VR [C]: Stereo display device is a HMD");
653 StereoHMD = static_cast<IStereoHMD *>(StereoDisplay);
655 if (Driver) // VR_DRIVER
657 StereoDisplay->setDriver(Driver);
662 else
664 nldebug("VR [C]: NOT Enabled");
666 IStereoDisplay::releaseUnusedLibraries();
669 // we want to get executable directory
670 static void addPaths(IProgressCallback &progress, const std::vector<std::string> &paths, bool recurse)
672 // all prefixes for paths
673 std::vector<std::string> directoryPrefixes;
675 // current directory has priority everywhere
676 directoryPrefixes.push_back(CPath::standardizePath(CPath::getCurrentPath()));
678 // startup directory
679 directoryPrefixes.push_back(Args.getStartupPath());
681 #if defined(NL_OS_WINDOWS)
682 // check in same directory as executable
683 directoryPrefixes.push_back(Args.getProgramPath());
684 #elif defined(NL_OS_MAC)
685 // check in bundle (Installer)
686 directoryPrefixes.push_back(getAppBundlePath() + "/Contents/Resources/");
688 // check in same directory as bundle (Steam)
689 directoryPrefixes.push_back(CPath::makePathAbsolute(getAppBundlePath() + "/..", ".", true));
690 #elif defined(NL_OS_UNIX)
691 // check in same directory as executable
692 directoryPrefixes.push_back(Args.getProgramPath());
694 // check in installed directory
695 if (CFile::isDirectory(getRyzomSharePrefix())) directoryPrefixes.push_back(CPath::standardizePath(getRyzomSharePrefix()));
696 #endif
698 std::set<std::string> directoriesToProcessSet;
699 std::vector<std::string> directoriesToProcess;
701 // first pass, build a map with all existing directories to process in second pass
702 for (uint j = 0; j < directoryPrefixes.size(); j++)
704 std::string directoryPrefix = directoryPrefixes[j];
706 for (uint i = 0; i < paths.size(); i++)
708 std::string directory = NLMISC::expandEnvironmentVariables(paths[i]);
710 // only prepend prefix if path is relative
711 if (!directory.empty() && !directoryPrefix.empty() && !CPath::isAbsolutePath(directory))
712 directory = directoryPrefix + directory;
714 // only process existing directories
715 if (CFile::isExists(directory))
717 if (directoriesToProcessSet.find(directory) == directoriesToProcessSet.end())
719 directoriesToProcessSet.insert(directory);
720 directoriesToProcess.push_back(directory);
726 // second pass, add search paths
727 for (size_t i = 0; i < directoriesToProcess.size(); ++i)
729 progress.progress((float)i / (float)directoriesToProcess.size());
730 progress.pushCropedValues((float)i / (float)directoriesToProcess.size(), (float)(i + 1) / (float)directoriesToProcess.size());
732 CPath::addSearchPath(directoriesToProcess[i], recurse, false, &progress);
734 progress.popCropedValues();
738 void initStreamedPackageManager(NLMISC::IProgressCallback &progress)
740 CStreamedPackageManager &spm = CStreamedPackageManager::getInstance();
741 nlassert(!spm.Provider); // If this asserts, init was called twice without release
742 nlassert(!HttpPackageProvider); // Idem
743 NLWEB::CHttpPackageProvider *hpp = new NLWEB::CHttpPackageProvider();
744 hpp->Path = ClientCfg.StreamedPackagePath;
745 for (uint i = 0; i < ClientCfg.StreamedPackageHosts.size(); i++)
746 hpp->Hosts.push_back(ClientCfg.StreamedPackageHosts[i]);
747 spm.Provider = hpp;
748 HttpPackageProvider = hpp;
751 void addSearchPaths(IProgressCallback &progress)
753 // Add search path of UI addon. Allow only a subset of files.
754 // Must do it first because take precedence other standard files
755 InterfaceAddOnManager.addSearchFiles("uiaddon", "*.xml;*.lua;*.tga", "login_*.xml;out_v2_*.xml", &progress);
757 // Add Standard search paths
759 H_AUTO(InitRZAddSearchPath2)
761 addPaths(progress, ClientCfg.DataPath, true);
763 CPath::loadRemappedFiles("remap_files.csv");
766 addPaths(progress, ClientCfg.DataPathNoRecurse, false);
769 void addPreDataPaths(NLMISC::IProgressCallback &progress)
771 NLMISC::TTime initPaths = ryzomGetLocalTime ();
773 H_AUTO(InitRZAddSearchPaths);
775 addPaths(progress, ClientCfg.PreDataPath, true);
777 //nlinfo ("PROFILE: %d seconds for Add search paths Predata", (uint32)(ryzomGetLocalTime ()-initPaths)/1000);
780 static void addPackedSheetUpdatePaths(NLMISC::IProgressCallback &progress)
782 for(uint i = 0; i < ClientCfg.UpdatePackedSheetPath.size(); i++)
784 progress.progress((float)i/(float)ClientCfg.UpdatePackedSheetPath.size());
785 progress.pushCropedValues ((float)i/(float)ClientCfg.UpdatePackedSheetPath.size(), (float)(i+1)/(float)ClientCfg.UpdatePackedSheetPath.size());
786 CPath::addSearchPath(NLMISC::expandEnvironmentVariables(ClientCfg.UpdatePackedSheetPath[i]), true, false, &progress);
787 progress.popCropedValues();
791 #if defined(NL_OS_UNIX) && !defined(NL_OS_MAC)
792 static bool addRyzomIconBitmap(const std::string &directory, vector<CBitmap> &bitmaps)
794 if (CFile::isDirectory(directory))
796 // build filename from directory and default ryzom client icon name
797 std::string filename = NLMISC::toString("%s/%s.png", directory.c_str(), getRyzomClientIcon().c_str());
799 if (CFile::fileExists(filename))
801 CIFile file;
803 if (file.open(filename))
805 CBitmap bitmap;
807 if (bitmap.load(file))
809 bitmaps.push_back(bitmap);
810 return true;
816 return false;
818 #endif
820 //---------------------------------------------------
821 // initLog :
822 // Initialize the client.log file
823 //---------------------------------------------------
824 void initLog()
826 // Add a displayer for Debug Infos.
827 createDebug();
829 // Client.Log displayer
830 nlassert( !ErrorLog->getDisplayer("CLIENT.LOG") );
831 CFileDisplayer *ClientLogDisplayer = new CFileDisplayer(getLogDirectory() + "client.log", true, "CLIENT.LOG");
832 DebugLog->addDisplayer (ClientLogDisplayer);
833 InfoLog->addDisplayer (ClientLogDisplayer);
834 WarningLog->addDisplayer (ClientLogDisplayer);
835 ErrorLog->addDisplayer (ClientLogDisplayer);
836 AssertLog->addDisplayer (ClientLogDisplayer);
838 // Display the client version.
839 nlinfo("RYZOM VERSION: %s", getDebugVersion().c_str());
840 nlinfo("Memory: %s/%s", bytesToHumanReadable(CSystemInfo::availablePhysicalMemory()).c_str(), bytesToHumanReadable(CSystemInfo::totalPhysicalMemory()).c_str());
841 nlinfo("OS: %s", CSystemInfo::getOS().c_str());
842 nlinfo("Processor: %s", CSystemInfo::getProc().c_str());
844 #ifdef NL_OS_MAC
845 struct rlimit rlp, rlp2, rlp3;
847 getrlimit(RLIMIT_NOFILE, &rlp);
849 rlim_t value = 1024;
851 rlp2.rlim_cur = std::min(value, rlp.rlim_max);
852 rlp2.rlim_max = rlp.rlim_max;
854 if (setrlimit(RLIMIT_NOFILE, &rlp2))
856 if (errno == EINVAL)
858 nlwarning("Unable to set rlimit with error: the specified limit is invalid");
860 else if (errno == EPERM)
862 nlwarning("Unable to set rlimit with error: the limit specified would have raised the maximum limit value and the caller is not the super-user");
864 else
866 nlwarning("Unable to set rlimit with error: unknown error");
870 getrlimit(RLIMIT_NOFILE, &rlp3);
871 nlinfo("rlimit before %llu %llu", (uint64)rlp.rlim_cur, (uint64)rlp.rlim_max);
872 nlinfo("rlimit after %llu %llu", (uint64)rlp3.rlim_cur, (uint64)rlp3.rlim_max);
874 // add the bundle's plugins path as library search path (for nel drivers)
875 if (CFile::isExists(getAppBundlePath() + "/Contents/PlugIns/nel"))
877 CLibrary::addLibPath(getAppBundlePath() + "/Contents/PlugIns/nel/");
879 #endif
882 //---------------------------------------------------
883 // prelogInit :
884 // Initialize the application before login
885 // if the init fails, call nlerror
886 //---------------------------------------------------
887 void prelogInit()
891 H_AUTO ( RZ_Client_Init );
893 // Assert if no more memory
894 set_new_handler(outOfMemory);
896 NLMISC_REGISTER_CLASS(CStage);
897 NLMISC_REGISTER_CLASS(CStageSet);
898 NLMISC_REGISTER_CLASS(CEntityManager);
899 NLMISC_REGISTER_CLASS(CCharacterCL);
900 NLMISC_REGISTER_CLASS(CPlayerCL);
901 NLMISC_REGISTER_CLASS(CUserEntity);
902 NLMISC_REGISTER_CLASS(CFxCL);
903 NLMISC_REGISTER_CLASS(CItemCL);
904 NLMISC_REGISTER_CLASS(CNamedEntityPositionState);
905 NLMISC_REGISTER_CLASS(CAnimalPositionState);
907 // Progress bar for init() and connection()
908 ProgressBar.reset (BAR_STEP_INIT_CONNECTION);
910 // save screen saver state and disable it
911 LastScreenSaverEnabled = CSystemUtils::isScreensaverEnabled();
913 if (LastScreenSaverEnabled)
914 CSystemUtils::enableScreensaver(false);
916 // Random init
917 srand ((uint)CTime::getLocalTime());
919 // Set FPU exceptions
920 #ifdef NL_OS_WINDOWS
921 _control87 (_EM_INVALID|_EM_DENORMAL/*|_EM_ZERODIVIDE|_EM_OVERFLOW*/|_EM_UNDERFLOW|_EM_INEXACT, _MCW_EM);
922 #endif // NL_OS_WINDOWS
924 FPU_CHECKER_ONCE
926 NLMISC::TTime initStart = ryzomGetLocalTime ();
928 // _CrtSetDbgFlag( _CRTDBG_CHECK_CRT_DF );
930 // Init XML Lib allocator
931 // Due to Bug #906, we disable the stl xml allocation
932 // nlverify (xmlMemSetup (XmlFree4NeL, XmlMalloc4NeL, XmlRealloc4NeL, XmlStrdup4NeL) == 0);
934 // Init the debug memory
935 initDebugMemory();
937 // Load the application configuration.
938 string nmsg("Loading config file...");
939 ProgressBar.newMessage (nmsg);
941 ClientCfg.init(ConfigFileName);
942 CLoginProgressPostThread::getInstance().init(ClientCfg.ConfigFile);
944 sint cpuMask;
946 if (ClientCfg.CPUMask < 1)
948 CTime::CTimerInfo timerInfo;
949 NLMISC::CTime::probeTimerInfo(timerInfo);
951 cpuMask = timerInfo.RequiresSingleCore ? 1:0;
953 else
955 cpuMask = ClientCfg.CPUMask;
958 if (cpuMask) setCPUMask(cpuMask);
960 setCrashCallback(crashCallback);
962 // Display Some Info On CPU
963 displayCPUInfo();
965 FPU_CHECKER_ONCE
967 // create the save dir.
968 if (!CFile::isExists("save")) CFile::createDirectory("save");
970 // create the user dir.
971 if (!CFile::isExists("user")) CFile::createDirectory("user");
973 #if !FINAL_VERSION
974 // if we're not in final version then start the file access logger to keep track of the files that we read as we play
975 //ICommand::execute("iFileAccessLogStart",*NLMISC::InfoLog);
976 #endif
978 // check "BuildName" in ClientCfg
979 //nlassert(!ClientCfg.BuildName.empty()); // TMP comment by nico do not commit
981 // Start memory allocation log
982 // if (ClientCfg.LogMemoryAllocation)
983 // NLMEMORY::StartAllocationLog ("alloc.memlog", ClientCfg.LogMemoryAllocationSize);
985 // Remap tga files on dds files.
986 CPath::remapExtension ("dds", "tga", true);
987 CPath::remapExtension ("dds", "png", true);
988 CPath::remapExtension ("png", "tga", true);
989 FPU_CHECKER_ONCE
991 initStreamedPackageManager(ProgressBar);
992 addPreDataPaths(ProgressBar);
994 FPU_CHECKER_ONCE
996 H_AUTO(InitRZUIStr)
998 FPU_CHECKER_ONCE
999 // Set the data path for the localisation.
1000 const string nmsg("Loading I18N...");
1001 ProgressBar.newMessage ( nmsg );
1003 FPU_CHECKER_ONCE
1004 STRING_MANAGER::CLoadProxy loadProxy;
1005 CI18N::setLoadProxy(&loadProxy);
1006 CI18N::load(ClientCfg.LanguageCode);
1007 CI18N::setLoadProxy(NULL);
1008 FPU_CHECKER_ONCE
1010 // Yoyo: Append the skills and Bricks to the I18N
1011 STRING_MANAGER::CStringManagerClient::initI18NSpecialWords(ClientCfg.LanguageCode);
1012 FPU_CHECKER_ONCE
1015 FPU_CHECKER_ONCE
1017 // Check driver version
1018 checkDriverVersion();
1020 // Initialize the VR devices (even more important than the most important part of the client)
1021 nmsg = "Initializing VR devices...";
1022 ProgressBar.newMessage ( ClientCfg.buildLoadingString(nmsg) );
1023 initStereoDisplayDevice(); // VR_CONFIG
1025 // Create the driver (most important part of the client).
1026 nmsg = "Creating 3d driver...";
1027 ProgressBar.newMessage ( ClientCfg.buildLoadingString(nmsg) );
1029 UDriver::TDriver driver = UDriver::OpenGl;
1031 #ifdef NL_OS_WINDOWS
1032 uintptr_t icon = (uintptr_t)LoadIcon(HInstance, MAKEINTRESOURCE(IDI_MAIN_ICON));
1033 #else
1034 uintptr_t icon = 0;
1035 #endif // NL_OS_WINDOWS
1037 switch(ClientCfg.Driver3D)
1039 #ifdef NL_OS_WINDOWS
1040 case CClientConfig::Direct3D:
1041 driver = UDriver::Direct3d;
1042 break;
1043 #endif // NL_OS_WINDOWS
1044 case CClientConfig::DrvAuto:
1045 case CClientConfig::OpenGL:
1046 driver = UDriver::OpenGl;
1047 break;
1048 case CClientConfig::OpenGLES:
1049 driver = UDriver::OpenGlEs;
1050 break;
1051 default:
1052 break;
1055 Driver = UDriver::createDriver(icon, driver);
1057 if(Driver == NULL)
1059 ExitClientError (CI18N::get ("Can_t_load_the_display_driver").c_str ());
1060 // ExitClientError() call exit() so the code after is never called
1061 return;
1064 UDriver::CMode mode;
1065 // first run (no client.cfg)
1066 if (ClientCfg.Width == 0 || ClientCfg.Height == 0)
1068 if (Driver->getCurrentScreenMode(mode))
1070 // fullscreen, using monitor resolution
1071 mode.Windowed = false;
1073 ClientCfg.Windowed = mode.Windowed;
1074 ClientCfg.Width = mode.Width;
1075 ClientCfg.Height = mode.Height;
1076 ClientCfg.Depth = mode.Depth;
1077 ClientCfg.Frequency = mode.Frequency;
1079 else
1081 // fallback
1082 ClientCfg.Windowed = true;
1083 ClientCfg.Width = 1024;
1084 ClientCfg.Height = 768;
1087 // update client.cfg with detected resolution
1088 ClientCfg.writeBool("FullScreen", !ClientCfg.Windowed, true);
1089 ClientCfg.writeInt("Width", ClientCfg.Width, true);
1090 ClientCfg.writeInt("Height", ClientCfg.Height, true);
1091 ClientCfg.writeInt("Depth", ClientCfg.Depth, true);
1092 ClientCfg.writeInt("Frequency", ClientCfg.Frequency, true);
1094 ClientCfg.ConfigFile.save();
1096 else
1098 mode.Windowed = ClientCfg.Windowed;
1099 mode.Width = ClientCfg.Width;
1100 mode.Height = ClientCfg.Height;
1101 mode.Depth = ClientCfg.Depth;
1102 mode.Frequency = ClientCfg.Frequency;
1105 CLoginProgressPostThread::getInstance().step(CLoginStep(LoginStep_VideoModeSetup, "login_step_video_mode_setup"));
1107 FPU_CHECKER_ONCE
1109 // Check the driver is not is 16 bits
1110 checkDriverDepth ();
1112 // Disable Hardware Vertex Program.
1113 if(ClientCfg.DisableVtxProgram)
1114 Driver->disableHardwareVertexProgram();
1115 // Disable Hardware Vertex AGP.
1116 if(ClientCfg.DisableVtxAGP)
1117 Driver->disableHardwareVertexArrayAGP();
1118 // Disable Hardware Texture Shader.
1119 if(ClientCfg.DisableTextureShdr)
1120 Driver->disableHardwareTextureShader();
1122 if (StereoDisplay) // VR_CONFIG // VR_DRIVER
1124 // override mode TODO
1127 // Set the mode of the window.
1128 if (!Driver->setDisplay (mode, false))
1130 string msg;
1131 if (mode.Windowed)
1133 msg = CI18N::get ("can_t_create_a_window_display");
1135 else
1137 msg = CI18N::get ("can_t_create_a_fullscreen_display");
1139 msg += " (%dx%d %d ";
1140 msg += CI18N::get ("bits");
1141 msg += ")";
1142 ExitClientError (msg.c_str (), mode.Width, mode.Height, mode.Depth);
1143 // ExitClientError() call exit() so the code after is never called
1144 return;
1147 // Enable or disable VSync
1148 if (ClientCfg.WaitVBL)
1149 Driver->setSwapVBLInterval(1);
1150 else
1151 Driver->setSwapVBLInterval(0);
1153 // initialize system utils class
1154 CSystemUtils::init();
1155 CSystemUtils::setWindow(Driver->getDisplay());
1157 CLoginProgressPostThread::getInstance().step(CLoginStep(LoginStep_VideoModeSetupHighColor, "login_step_video_mode_setup_high_color"));
1159 #ifdef NL_OS_WINDOWS
1161 #ifdef RYZOM_BG_DOWNLOADER
1162 CBGDownloaderAccess::getInstance().init();
1163 #endif
1165 if (SlashScreen)
1166 DestroyWindow (SlashScreen);
1168 #endif // NL_OS_WINDOW
1170 // Set the title
1171 Driver->setWindowTitle(CI18N::get("TheSagaOfRyzom"));
1173 #if defined(NL_OS_UNIX) && !defined(NL_OS_MAC)
1174 // add all existing directory prefixes
1175 vector<string> directoryPrefixes;
1177 // user local directory prefix (~/.local)
1178 const char* homeDirectory = getenv("HOME");
1180 if (homeDirectory)
1181 directoryPrefixes.push_back(CPath::standardizePath(homeDirectory) + ".local");
1183 // system local directory prefix (/usr/local)
1184 directoryPrefixes.push_back("/usr/local");
1186 // system directory prefix (/usr)
1187 directoryPrefixes.push_back("/usr");
1189 // all supported icon sizes
1190 vector<uint> iconSizes;
1191 iconSizes.push_back(512);
1192 iconSizes.push_back(256);
1193 iconSizes.push_back(128);
1194 iconSizes.push_back(96);
1195 iconSizes.push_back(64);
1196 iconSizes.push_back(48);
1197 iconSizes.push_back(32);
1198 iconSizes.push_back(24);
1199 iconSizes.push_back(22);
1200 iconSizes.push_back(16);
1202 vector<CBitmap> bitmaps;
1204 // process all icon sizes
1205 for(size_t j = 0; j < iconSizes.size(); ++j)
1207 // process all directory prefixes
1208 for(size_t i = 0; i < directoryPrefixes.size(); ++i)
1210 uint size = iconSizes[j];
1212 // build directory where to look for icon
1213 std::string directory = toString("%s/share/icons/hicolor/%ux%u/apps", directoryPrefixes[i].c_str(), size, size);
1215 // if found, skip other directories for this icon size
1216 if (addRyzomIconBitmap(directory, bitmaps)) break;
1220 if (bitmaps.empty())
1222 // check if an icon is present in same directory as executable
1223 addRyzomIconBitmap(Args.getProgramPath(), bitmaps);
1226 if (bitmaps.empty())
1228 // check if an icon is present in current directory
1229 addRyzomIconBitmap(".", bitmaps);
1232 Driver->setWindowIcon(bitmaps);
1233 #endif
1235 sint32 posX = 0, posY = 0;
1237 if (ClientCfg.Windowed)
1239 // use position saved in config
1240 posX = ClientCfg.PositionX;
1241 posY = ClientCfg.PositionY;
1243 else
1245 // position is not saved in config so center the window
1246 UDriver::CMode tmp;
1247 if (Driver->getCurrentScreenMode(tmp))
1249 posX = (tmp.Width - Driver->getWindowWidth())/2;
1250 posY = (tmp.Height - Driver->getWindowHeight())/2;
1254 // Set the window position
1255 Driver->setWindowPos(posX, posY);
1257 // Show the window
1258 Driver->showWindow();
1260 // for background downloader : store this window handle in shared memory for later access
1261 // (we use SendMessage to communicate with the background downloader)
1263 // Enough AGP for vertices ?
1264 if (Driver->getAvailableVertexAGPMemory () == 0)
1267 std::string deviceName;
1268 uint64 driverVersion;
1269 CSystemInfo::getVideoInfo(deviceName, driverVersion);
1270 deviceName = NLMISC::toLowerAscii(deviceName);
1271 // for radeon 7200, patch because agp crash with agp with OpenGL -> don't display the message
1272 if (!(Driver->getNbTextureStages() <= 3 && strstr(deviceName.c_str(), "radeon")))
1274 if (ClientQuestion (CI18N::get ("agp_trouble")))
1276 openDoc ("client_troubles.html");
1277 extern void quitCrashReport ();
1278 quitCrashReport ();
1279 exit (EXIT_FAILURE);
1284 FPU_CHECKER_ONCE
1286 // Set the monitor color properties
1287 CMonitorColorProperties monitorColor;
1288 for (uint i=0; i<3; i++)
1290 monitorColor.Contrast[i] = ClientCfg.Contrast;
1291 monitorColor.Luminosity[i] = ClientCfg.Luminosity;
1292 monitorColor.Gamma[i] = ClientCfg.Gamma;
1294 if (!Driver->setMonitorColorProperties (monitorColor))
1296 nlwarning("init : setMonitorColorProperties fails");
1299 // The client require at least 2 textures.
1300 if(Driver->getNbTextureStages() < 2)
1301 throw Exception("Application require at least 2 textures stages !!");
1303 Driver->enableUsedTextureMemorySum(true);
1305 // Initialize the font manager.
1306 Driver->setFontManagerMaxMemory(2000000);
1308 // Init the DXTCCompression.
1309 Driver->forceDXTCCompression(ClientCfg.ForceDXTC);
1311 // Set the anisotropic filter
1312 Driver->setAnisotropicFilter(ClientCfg.AnisotropicFilter);
1314 // Divide the texture size.
1315 if (ClientCfg.DivideTextureSizeBy2)
1316 Driver->forceTextureResize(2);
1317 else
1318 Driver->forceTextureResize(1);
1320 // Create a generic material.
1321 GenericMat = Driver->createMaterial();
1322 if(GenericMat.empty())
1323 nlerror("init: Cannot Create the generic material.");
1326 // Create a text context. We need to put the full path because we not already add search path
1327 // resetTextContext ("bremenb.ttf", false);
1328 resetTextContext ("ryzom.ttf", false);
1331 CInterfaceManager::getInstance();
1332 CViewRenderer::getInstance()->setInterfaceScale(1.0f, 1024, 768);
1333 CViewRenderer::getInstance()->setBilinearFiltering(ClientCfg.BilinearUI);
1335 CWidgetManager::getInstance()->setWindowSnapInvert(ClientCfg.WindowSnapInvert);
1336 CWidgetManager::getInstance()->setWindowSnapDistance(ClientCfg.WindowSnapDistance);
1338 // Yoyo: initialize NOW the InputHandler for Event filtering.
1339 CInputHandlerManager *InputHandlerManager = CInputHandlerManager::getInstance();
1340 InputHandlerManager->addToServer (&Driver->EventServer);
1342 std::string filename = CPath::lookup( ClientCfg.XMLInputFile, false );
1343 if( !filename.empty() )
1344 InputHandlerManager->readInputConfigFile( filename );
1346 ProgressBar.setFontFactor(0.85f);
1348 nmsg = "Loading background...";
1349 ProgressBar.newMessage ( ClientCfg.buildLoadingString(nmsg) );
1351 // Choose a tips of the day
1352 selectTipsOfTheDay (rand());
1354 // Create the loading texture. We can't do that before because we need to add pre search path first and driver
1355 //UseEscapeDuringLoading = USE_ESCAPE_DURING_LOADING;
1356 UseEscapeDuringLoading = false;
1357 beginLoading (StartBackground); //put here intro Gameforge if wanted
1359 FPU_CHECKER_ONCE
1361 // Define the root path that contains all data needed for the application.
1362 nmsg = "Adding search paths...";
1363 ProgressBar.newMessage ( ClientCfg.buildLoadingString(nmsg) );
1365 if(!ClientCfg.TestBrowser)
1367 NLMISC::TTime initPaths = ryzomGetLocalTime ();
1368 addSearchPaths(ProgressBar);
1369 if (ClientCfg.UpdatePackedSheet)
1371 addPackedSheetUpdatePaths(ProgressBar);
1373 //nlinfo ("PROFILE: %d seconds for Add search paths Data", (uint32)(ryzomGetLocalTime ()-initPaths)/1000);
1376 // Initialize HTTP cache
1377 CHttpCache::getInstance()->setCacheIndex("cache/cache.index");
1378 CHttpCache::getInstance()->init();
1380 CStrictTransportSecurity::getInstance()->init("save/hsts-list.save");
1382 // Register the reflected classes
1383 registerInterfaceElements();
1385 // set driver used by bloom (must be called before init)
1386 CBloomEffect::getInstance().setDriver(Driver);
1388 // init bloom effect
1389 CBloomEffect::getInstance().init();
1391 if (StereoDisplay) // VR_CONFIG
1393 // Init stereo display resources
1394 StereoDisplay->setDriver(Driver); // VR_DRIVER
1398 H_AUTO(InitRZSound)
1400 // Init the sound manager
1401 nmsg = "Initializing sound manager...";
1402 ProgressBar.newMessage(ClientCfg.buildLoadingString(nmsg));
1403 if (ClientCfg.SoundOn)
1405 nlassert(!SoundMngr);
1406 SoundMngr = new CSoundManager(&ProgressBar);
1409 SoundMngr->init(&ProgressBar);
1411 catch(const Exception &e)
1413 nlwarning("init : Error when creating 'SoundMngr' : %s", e.what());
1414 delete SoundMngr;
1415 SoundMngr = NULL;
1418 // Play Music just after the SoundMngr is inited
1419 if (SoundMngr)
1421 // init the SoundMngr with backuped volume
1422 SoundMngr->setSFXVolume(ClientCfg.SoundSFXVolume);
1423 SoundMngr->setGameMusicVolume(ClientCfg.SoundGameMusicVolume);
1425 // Play the login screen music
1426 SoundMngr->playMusic(ClientCfg.StartMusic, 0, true, true, true);
1430 CPath::memoryCompress(); // Because sound calls addSearchPath
1433 nlinfo ("PROFILE: %d seconds for prelogInit", (uint32)(ryzomGetLocalTime ()-initStart)/1000);
1435 FPU_CHECKER_ONCE
1437 catch (const Exception &e)
1439 ExitClientError (e.what());
1443 void stopSoundMngr()
1445 if (SoundMngr)
1447 delete SoundMngr;
1448 SoundMngr = NULL;
1453 // ***************************************************************************
1454 void initBotObjectSelection()
1456 // Get the driver shape bank
1457 UShapeBank *shapeBank= Driver->getShapeBank();
1458 if(!shapeBank)
1459 return;
1461 // Parse all .creature
1462 const CSheetManager::TEntitySheetMap &sheets= SheetMngr.getSheets();
1463 CSheetManager::TEntitySheetMap::const_iterator it= sheets.begin();
1464 for(;it!=sheets.end();it++)
1466 CEntitySheet *entitySheet= it->second.EntitySheet;
1467 if(entitySheet->Type!=CEntitySheet::FAUNA)
1468 continue;
1469 const CCharacterSheet *sheet= dynamic_cast<const CCharacterSheet *>(entitySheet);
1470 if(sheet)
1472 // If the entity define no Skeleton, it is not skinned
1473 // thus we must force the shape to bkup the geometry in RAM, for fast selection
1474 if(sheet->IdSkelFilename==CStaticStringMapper::emptyId())
1476 // For all equipement (yoyo: Body is theorically the only one bound)
1477 std::vector<const CCharacterSheet::CEquipment*> equipList;
1478 sheet->getWholeEquipmentList(equipList);
1479 for(uint i=0;i<equipList.size();i++)
1481 string strShape= equipList[i]->getItem();
1482 // if some item bound
1483 if(!strShape.empty())
1485 // If this is a reference on an item
1486 string ext = CFile::getExtension(strShape);
1487 if((ext == "item") || (ext == "sitem"))
1489 // IS the item a valid one ?
1490 CSheetId itemId;
1491 if(itemId.buildSheetId(NLMISC::toLowerAscii(strShape)))
1493 // Get this item sheet ?
1494 CItemSheet *itemSheet= dynamic_cast<CItemSheet *>(SheetMngr.get(itemId));
1495 if(itemSheet)
1497 // and so get the actual shape name
1498 strShape= itemSheet->getShape();
1503 // If ok (after possible .sitem translation)
1504 if(!strShape.empty())
1506 shapeBank->buildSystemGeometryForshape(strShape);
1517 // ***************************************************************************
1518 //---------------------------------------------------
1519 // postlogInit :
1520 // Initialize the application after login
1521 // if the init fails, call nlerror
1522 //---------------------------------------------------
1523 void postlogInit()
1525 Driver->clearBuffers(CRGBA::Black);
1526 Driver->swapBuffers();
1527 CNiceInputAuto niceInputs;
1528 string nmsg;
1532 NLMISC::TTime initStart = ryzomGetLocalTime();
1533 NLMISC::TTime initLast = initStart;
1534 NLMISC::TTime initCurrent = initLast;
1536 H_AUTO(InitRZNetwk)
1537 // Initialize the Generic Message Header Manager.
1538 nmsg = "Initializing network...";
1539 ProgressBar.newMessage ( ClientCfg.buildLoadingString(nmsg) );
1541 std::string msgXMLPath = CPath::lookup("msg.xml");
1542 GenericMsgHeaderMngr.init(msgXMLPath);
1543 initializeNetwork();
1545 initLast = initCurrent;
1546 initCurrent = ryzomGetLocalTime();
1547 //nlinfo ("PROFILE: %d seconds (%d total) for Initializing network", (uint32)(initCurrent-initLast)/1000, (uint32)(initCurrent-initStart)/1000);
1551 H_AUTO(InitRZChat)
1553 // init the chat manager
1554 nmsg = "Initializing chat manager...";
1555 ProgressBar.newMessage ( ClientCfg.buildLoadingString(nmsg) );
1557 ChatMngr.init( CPath::lookup("chat_static.cdb") );
1559 initLast = initCurrent;
1560 initCurrent = ryzomGetLocalTime();
1561 //nlinfo ("PROFILE: %d seconds (%d total) for Initializing chat manager", (uint32)(initCurrent-initLast)/1000, (uint32)(initCurrent-initStart)/1000);
1565 H_AUTO(InitRZLigo)
1567 // Read the ligo primitive class file
1568 nmsg = "Initializing primitive classes...";
1569 ProgressBar.newMessage ( ClientCfg.buildLoadingString(nmsg) );
1571 if (!LigoConfig.readPrimitiveClass (ClientCfg.LigoPrimitiveClass.c_str(), false))
1573 nlwarning ("Can't load primitive class file %s", ClientCfg.LigoPrimitiveClass.c_str());
1576 initLast = initCurrent;
1577 initCurrent = ryzomGetLocalTime();
1578 //nlinfo ("PROFILE: %d seconds (%d total) for Initializing primitive classes", (uint32)(initCurrent-initLast)/1000, (uint32)(initCurrent-initStart)/1000);
1581 // set the primitive context
1582 CPrimitiveContext::instance().CurrentLigoConfig = &LigoConfig;
1585 H_AUTO(InitRZSound)
1587 if (!SoundMngr)
1589 // Init the sound manager
1590 nmsg = "Initializing sound manager...";
1591 ProgressBar.newMessage(ClientCfg.buildLoadingString(nmsg));
1592 if (ClientCfg.SoundOn)
1594 SoundMngr = new CSoundManager(&ProgressBar);
1597 SoundMngr->init(&ProgressBar);
1599 catch (const Exception &e)
1601 nlwarning("init : Error when creating 'SoundMngr' : %s", e.what());
1602 delete SoundMngr;
1603 SoundMngr = NULL;
1606 if (SoundMngr)
1608 // init the SoundMngr with backuped volume
1609 SoundMngr->setSFXVolume(ClientCfg.SoundSFXVolume);
1610 SoundMngr->setGameMusicVolume(ClientCfg.SoundGameMusicVolume);
1614 CPath::memoryCompress(); // Because sound calls addSearchPath
1619 H_AUTO(InitRZShIdI)
1621 nmsg = "Initializing sheets...";
1622 ProgressBar.newMessage ( ClientCfg.buildLoadingString(nmsg) );
1624 // Initialize Sheet IDs.
1625 CSheetId::init (ClientCfg.UpdatePackedSheet);
1627 // load packed sheets
1628 nmsg = "Loading sheets...";
1629 ProgressBar.newMessage ( ClientCfg.buildLoadingString(nmsg) );
1631 SheetMngr.setOutputDataPath("../../client/data");
1632 SheetMngr.load (ProgressBar, ClientCfg.UpdatePackedSheet, ClientCfg.NeedComputeVS, ClientCfg.DumpVSIndex);
1634 initLast = initCurrent;
1635 initCurrent = ryzomGetLocalTime();
1636 //nlinfo ("PROFILE: %d seconds (%d total) for Initializing sheets", (uint32)(initCurrent-initLast)/1000, (uint32)(initCurrent-initStart)/1000);
1640 nmsg = "Initializing bricks...";
1641 ProgressBar.newMessage ( ClientCfg.buildLoadingString(nmsg) );
1643 CSBrickManager::getInstance()->init(); // Must be done after sheet loading
1644 //STRING_MANAGER::CStringManagerClient::specialWordsMemoryCompress(); // Must be done after brick manager init
1646 initLast = initCurrent;
1647 initCurrent = ryzomGetLocalTime();
1648 //nlinfo ("PROFILE: %d seconds (%d total) for Initializing bricks", (uint32)(initCurrent-initLast)/1000, (uint32)(initCurrent-initStart)/1000);
1651 if (!ClientCfg.Light)
1653 H_AUTO(InitRZCh)
1655 nmsg = "Initializing Color Slot...";
1656 ProgressBar.newMessage ( ClientCfg.buildLoadingString(nmsg) );
1658 // Initialize the color slot manager
1659 initColorSlotManager();
1661 nmsg = "Initializing Gabarit Set...";
1662 ProgressBar.newMessage ( ClientCfg.buildLoadingString(nmsg) );
1664 // Initialize the set of gabarit
1665 GabaritSet.loadGabarits (ProgressBar);
1667 nmsg = "Initializing Hair Set...";
1668 ProgressBar.newMessage ( ClientCfg.buildLoadingString(nmsg) );
1670 // Initialize the hair sets
1671 HairSet.init (ProgressBar);
1673 nmsg = "Initializing Starting Role Set...";
1674 ProgressBar.newMessage ( ClientCfg.buildLoadingString(nmsg) );
1676 // Init all BotObjects for fast selection
1677 nmsg = "Initializing Bot Objects...";
1678 ProgressBar.newMessage ( ClientCfg.buildLoadingString(nmsg) );
1679 initBotObjectSelection();
1681 initLast = initCurrent;
1682 initCurrent = ryzomGetLocalTime();
1683 //nlinfo ("PROFILE: %d seconds (%d total) for Initializing Color Slot etc.", (uint32)(initCurrent-initLast)/1000, (uint32)(initCurrent-initStart)/1000);
1685 else
1687 // To have the same number of newMessage in client light
1688 nmsg.clear();
1689 ProgressBar.newMessage (nmsg);
1690 ProgressBar.newMessage (nmsg);
1691 ProgressBar.newMessage (nmsg);
1692 ProgressBar.newMessage (nmsg);
1693 ProgressBar.newMessage (nmsg);
1696 // Initialize MovieShooter
1698 nmsg = "Initializing Movie Shooter ...";
1699 ProgressBar.newMessage ( ClientCfg.buildLoadingString(nmsg) );
1700 if(ClientCfg.MovieShooterMemory>0)
1702 MovieShooter.init(ClientCfg.MovieShooterMemory);
1703 MovieShooter.setFrameSkip(ClientCfg.MovieShooterFrameSkip);
1706 initLast = initCurrent;
1707 initCurrent = ryzomGetLocalTime();
1708 //nlinfo ("PROFILE: %d seconds (%d total) for Initializing Movie Shooter", (uint32)(initCurrent-initLast)/1000, (uint32)(initCurrent-initStart)/1000);
1712 nmsg = "Initializing primitives...";
1713 ProgressBar.newMessage ( ClientCfg.buildLoadingString(nmsg) );
1715 // Register the ligo primitives for .primitive sheets
1716 NLLIGO::Register ();
1718 // Load PACS primitive
1719 initPrimitiveBlocks();
1721 initLast = initCurrent;
1722 initCurrent = ryzomGetLocalTime();
1723 //nlinfo ("PROFILE: %d seconds (%d total) for Initializing primitives", (uint32)(initCurrent-initLast)/1000, (uint32)(initCurrent-initStart)/1000);
1727 nmsg = "Executing cfg file start commands...";
1728 ProgressBar.newMessage ( ClientCfg.buildLoadingString(nmsg) );
1730 // Call the user commands from the config file if any
1731 CConfigFile::CVar *var;
1732 if ((var = ClientCfg.ConfigFile.getVarPtr ("StartCommands")) != NULL)
1734 for (uint i = 0; i < var->size(); i++)
1736 ICommand::execute (var->asString(i), *InfoLog);
1740 initLast = initCurrent;
1741 initCurrent = ryzomGetLocalTime();
1742 //nlinfo ("PROFILE: %d seconds (%d total) for Executing cfg file start commands", (uint32)(initCurrent-initLast)/1000, (uint32)(initCurrent-initStart)/1000);
1745 // Next step will be the connection with the server.
1746 nmsg = "Connecting...";
1747 ProgressBar.newMessage ( ClientCfg.buildLoadingString(nmsg) );
1749 nlinfo ("PROFILE: %d seconds for postlogInit", (uint32)(ryzomGetLocalTime ()-initStart)/1000);
1751 catch (const Exception &e)
1753 ExitClientError (e.what());
1755 }// init //