khanat-opennel-code/code/ryzom/client/src/init.cpp
2016-06-07 13:21:45 +02:00

1715 lines
47 KiB
C++

// Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
// Copyright (C) 2010 Winch Gate Property Limited
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "stdpch.h"
//////////////
// INCLUDES //
//////////////
// Misc.
#include "nel/misc/debug.h"
#include "nel/misc/displayer.h"
#include "nel/misc/path.h"
#include "nel/misc/i18n.h"
#include "nel/misc/log.h"
#include "nel/misc/sheet_id.h"
#include "nel/misc/report.h"
#include "nel/misc/class_registry.h"
#include "nel/misc/system_info.h"
#include "nel/misc/block_memory.h"
#include "nel/misc/system_utils.h"
#include "nel/misc/cmd_args.h"
// 3D Interface.
#include "nel/3d/bloom_effect.h"
#include "nel/3d/u_driver.h"
#include "nel/3d/u_text_context.h"
#include "nel/3d/u_shape_bank.h"
#include "nel/3d/stereo_hmd.h"
// Net.
#include "nel/net/email.h"
// Ligo.
#include "nel/ligo/ligo_config.h"
// Std.
#include <fstream>
#include <sstream>
// Client
#include "init.h"
#include "input.h"
#include "client_cfg.h" // Configuration of the client.
#include "actions_client.h"
#include "color_slot_manager.h"
#include "movie_shooter.h"
#include "continent_manager.h"
#include "interface_v3/animal_position_state.h"
//#include "osd_client.h"
#include "debug_client.h"
#include "ingame_database_manager.h"
#include "client_chat_manager.h"
#include "interface_v3/input_handler_manager.h"
#include "interface_v3/interface_manager.h"
//#include "crtdbg.h"
#include "sound_manager.h"
#include "net_manager.h"
#include "sheet_manager.h"
#include "interface_v3/sbrick_manager.h"
#include "nel/gui/widget_manager.h"
//
#include "gabarit.h"
#include "hair_set.h"
//#include "starting_roles.h"
#include "init_main_loop.h"
#include "resource.h"
#include "time_client.h"
#include "pacs_client.h"
#include "interface_v3/music_player.h"
#include "input.h"
#include "interface_v3/add_on_manager.h"
#include "bg_downloader_access.h"
#include "user_agent.h"
#include "nel/misc/check_fpu.h"
#include "login_progress_post_thread.h"
#include "browse_faq.h"
// XMLLib
#include <libxml/xmlmemory.h>
#ifdef NL_OS_WINDOWS
#include <windows.h>
extern HINSTANCE HInstance;
extern HWND SlashScreen;
#endif // NL_OS_WINDOWS
#ifdef NL_OS_MAC
#include <stdio.h>
#include <sys/resource.h>
#include "nel/misc/dynloadlib.h"
#endif
#include "app_bundle_utils.h"
#include <new>
///////////
// USING //
///////////
using namespace NLMISC;
using namespace NLNET;
using namespace NL3D;
using namespace NLLIGO;
using namespace std;
// NVIDIA recommanded drivers
#define NVIDIA_RECOMMANDED_DRIVERS UINT64_CONSTANT(0x0006000e000a1820)
#define NVIDIA_RECOMMANDED_DRIVERS_STRING_TEST "nvidia"
#define NVIDIA_RECOMMANDED_DRIVERS_STRING_NTEST "go"
#define NVIDIA_RECOMMANDED_DRIVERS_VENDOR "NVIDIA"
#define NVIDIA_RECOMMANDED_DRIVERS_URL "http://www.nvidia.com/drivers"
// ATI recommanded drivers
#define ATI_RECOMMANDED_DRIVERS UINT64_CONSTANT(0x0006000e000a191e)
#define ATI_RECOMMANDED_DRIVERS_STRING_TEST "radeon"
#define ATI_RECOMMANDED_DRIVERS_VENDOR "ATI Technologies Inc."
#define ATI_RECOMMANDED_DRIVERS_URL "http://www.ati.com/support/driver.html"
// ProgressBar steps in init / connection phase
#define BAR_STEP_INIT_CONNECTION 17
/////////////
// GLOBALS //
/////////////
// Ligo primitive class
CLigoConfig LigoConfig;
CClientChatManager ChatMngr;
bool LastScreenSaverEnabled = false;
extern void registerInterfaceElements();
extern CContinentManager ContinentMngr;
// Tips of the day count
#define RZ_NUM_TIPS 17
ucstring TipsOfTheDay;
uint TipsOfTheDayIndex;
// includes for following register classes
#include "entities.h"
#include "character_cl.h"
#include "player_cl.h"
#include "user_entity.h"
#include "fx_cl.h"
#include "item_cl.h"
///////////////
// FUNCTIONS //
///////////////
// ***************************************************************************
// XML allocator functions
// Due to Bug #906, we disable the stl xml allocation
/*
static volatile bool XmlAllocUsesSTL = true;
static std::allocator<uint8> xmlStlAlloc;
void XmlFree4NeL (void *ptr)
{
// if (XmlAllocUsesSTL)
{
int size = *(((int *) ptr) - 1);
xmlStlAlloc.deallocate((uint8 *) ptr - sizeof(int), size + sizeof(int));
}
// else
// {
// MemoryDeallocate (ptr);
// }
}
void *XmlMalloc4NeL (size_t size)
{
// if (XmlAllocUsesSTL)
{
int *newB = (int *) xmlStlAlloc.allocate(size + sizeof(int));
*newB = (int)size;
return (void *) (newB + 1);
}
// else
// {
// return MemoryAllocate(size);
// }
}
void *XmlRealloc4NeL (void *ptr, size_t size)
{
// if (XmlAllocUsesSTL)
{
if (ptr == NULL) return XmlMalloc4NeL(size);
int oldSize = *(((int *) ptr) - 1);
if (oldSize == (int) size) return ptr;
void *newB = XmlMalloc4NeL(size);
memcpy(newB, ptr, std::min(oldSize, (int) size));
XmlFree4NeL(ptr);
return newB;
}
// else
// {
// // Get the block size
// return MemoryReallocate (ptr, size);
// }
}
char *XmlStrdup4NeL (const char *str)
{
nlassert (str);
char *newStr;
// if (XmlAllocUsesSTL)
{
newStr = (char *) XmlMalloc4NeL(strlen (str)+1);
}
// else
// {
// newStr = (char*)MemoryAllocate(strlen (str)+1);
// }
strcpy (newStr, str);
return newStr;
}
*/
#ifdef NL_OS_WINDOWS
static ucstring CurrentErrorMessage;
static INT_PTR CALLBACK ExitClientErrorDialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM /* lParam */)
{
switch(uMsg)
{
case WM_INITDIALOG:
{
if (CI18N::hasTranslation("TheSagaOfRyzom"))
{
SetWindowTextW(hwndDlg, (WCHAR*)CI18N::get ("TheSagaOfRyzom").c_str ());
}
SetDlgItemTextW(hwndDlg, IDC_ERROR_MSG_TEXT, (WCHAR*) CurrentErrorMessage.c_str ());
if (CI18N::hasTranslation("uiRyzomErrorMsgBoxExit"))
{
SetDlgItemTextW(hwndDlg, IDOK, (WCHAR*)CI18N::get ("uiRyzomErrorMsgBoxExit").c_str ());
}
if (CI18N::hasTranslation("uiRyzomErrorMsgBoxHelp"))
{
SetDlgItemTextW(hwndDlg, IDC_RYZOM_ERROR_HELP, (WCHAR*)CI18N::get ("uiRyzomErrorMsgBoxHelp").c_str ());
}
RECT rect;
RECT rectDesktop;
GetWindowRect (hwndDlg, &rect);
GetWindowRect (GetDesktopWindow (), &rectDesktop);
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);
HICON exitClientDlgIcon = LoadIcon(HInstance, MAKEINTRESOURCE(IDI_MAIN_ICON));
::SendMessageA(hwndDlg, WM_SETICON, (WPARAM) ICON_BIG, (LPARAM) exitClientDlgIcon);
}
break;
case WM_COMMAND:
switch(LOWORD(wParam))
{
case IDOK:
EndDialog(hwndDlg, IDOK);
break;
case IDC_RYZOM_ERROR_HELP:
{
if (Driver)
{
HWND wnd = Driver->getDisplay();
ShowWindow(wnd, SW_MINIMIZE);
}
browseFAQ(ClientCfg.ConfigFile);
EndDialog(hwndDlg, IDOK);
}
break;
}
break;
case WM_CLOSE:
EndDialog(hwndDlg, IDOK);
break;
}
return FALSE;
}
#endif
// Use this function to return an error to the final user and exit the client
void ExitClientError (const char *format, ...)
{
char *str;
NLMISC_CONVERT_VARGS (str, format, 256/*NLMISC::MaxCStringSize*/);
// Driver ?
if (Driver)
{
Driver->release();
}
#ifdef NL_OS_WINDOWS
CurrentErrorMessage.fromUtf8(str);
DialogBox(HInstance, MAKEINTRESOURCE(IDD_ERROR_HELP_MESSAGE_BOX), NULL, ExitClientErrorDialogProc);
/*
ucstring ucstr;
ucstr.fromUtf8 (str);
MessageBoxW (NULL, (WCHAR*)ucstr.c_str(), (WCHAR*)CI18N::get ("TheSagaOfRyzom").c_str (), MB_OK|MB_ICONERROR);
*/
#else
fprintf (stderr, "%s\n", str);
#endif
// Exit
extern void quitCrashReport ();
quitCrashReport ();
NLMISC::NL3D_BlockMemoryAssertOnPurge = false; // at this point some object may remain allocated
// so don't want to fire an assert here
exit (EXIT_FAILURE);
}
// Use this function to return an information to the final user
void ClientInfo (const ucstring &message)
{
#ifdef NL_OS_WINDOWS
MessageBoxW (NULL, (WCHAR*)message.c_str(), (WCHAR*)CI18N::get ("TheSagaOfRyzom").c_str (), MB_OK|MB_ICONINFORMATION);
#endif
}
// Use this function to ask a question to the final user
bool ClientQuestion (const ucstring &message)
{
#ifdef NL_OS_WINDOWS
return MessageBoxW (NULL, (WCHAR*)message.c_str(), (WCHAR*)CI18N::get ("TheSagaOfRyzom").c_str (), MB_YESNO|MB_ICONQUESTION) != IDNO;
#else
return false;
#endif
}
void selectTipsOfTheDay (uint /* tips */)
{
/* todo tips of the day uncomment
tips %= RZ_NUM_TIPS;
TipsOfTheDayIndex = tips;
ucstring title = CI18N::get ("uiTipsTitle");
title += toString (tips+1);
title += " : ";
TipsOfTheDay = title+CI18N::get ("uiTips"+toString (tips));*/
// todo tips of the day remove
//trap TipsOfTheDay = CI18N::get ("uiMessageOfTheDay");
TipsOfTheDay = ""; //trap
}
// ***************************************************************************
// For nel memory
void outOfMemory()
{
nlstopex (("OUT OF MEMORY"));
}
uint64 Debug_OldCPUMask = 0;
uint64 Debug_NewCPUMask = 0;
// For multi cpu, active only one CPU for the main thread
void setCPUMask(uint64 userCPUMask)
{
uint64 cpuMask = IProcess::getCurrentProcess()->getCPUMask();
Debug_OldCPUMask = cpuMask;
// if user CPU mask is valid
if (cpuMask & userCPUMask)
{
// use it
IProcess::getCurrentProcess ()->setCPUMask(cpuMask & userCPUMask);
}
else
{
// else get first available CPU
// get the processor to allow process
uint i = 0;
while ((i < 64) && ((cpuMask & (UINT64_CONSTANT(1) << i)) == 0))
i++;
// Set the CPU mask
if (i < 64)
{
IProcess::getCurrentProcess ()->setCPUMask(UINT64_CONSTANT(1) << i);
}
}
// check
cpuMask = IProcess::getCurrentProcess ()->getCPUMask();
Debug_NewCPUMask = cpuMask;
}
void displayCPUInfo()
{
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"));
}
string getVersionString (uint64 version)
{
return toString ("%u.%u.%u.%u", (unsigned int) (version >> 48), (unsigned int) ((version >> 32) & 0xffff), (unsigned int) ((version >> 16) & 0xffff), (unsigned int) (version & 0xffff));
}
string getSystemInformation()
{
string s;
s += "Memory: " + bytesToHumanReadable(CSystemInfo::availablePhysicalMemory()) + "/" + bytesToHumanReadable(CSystemInfo::totalPhysicalMemory()) + "\n";
s += "Process Virtual Memory: " + bytesToHumanReadable(CSystemInfo::virtualMemory()) + "\n";
s += "OS: " + CSystemInfo::getOS() + "\n";
s += "Processor: " + CSystemInfo::getProc() + "\n";
s += toString("CPUID: %x\n", CSystemInfo::getCPUID());
s += toString("HT: %s\n", CSystemInfo::hasHyperThreading()?"YES":"NO");
s += toString("CpuMask: %x\n", IProcess::getCurrentProcess ()->getCPUMask());
if(Driver)
s += "NeL3D: " + string(Driver->getVideocardInformation()) + "\n";
else
s += "NeL3D: No driver\n";
// More display info
string deviceName;
uint64 driverVersion;
if (CSystemInfo::getVideoInfo (deviceName, driverVersion))
{
s += "3DCard: ";
s += deviceName;
s += ", version ";
s += getVersionString (driverVersion) + "\n";
}
if (SoundMngr && SoundMngr->getMixer())
SoundMngr->getMixer()->writeProfile (s);
else
s += "No sound\n";
return s;
}
static string crashCallback()
{
string s = getDebugInformation();
s += getSystemInformation();
#ifdef NL_OS_WINDOWS
if (Driver)
{
NL3D::UDriver::CMode mode;
Driver->getCurrentScreenMode(mode);
if (!mode.Windowed)
{
HWND wnd = Driver->getDisplay();
ShowWindow(wnd, SW_MINIMIZE);
}
}
#endif
return s;
}
void checkDriverVersion()
{
string deviceName;
uint64 driverVersion;
if (CSystemInfo::getVideoInfo (deviceName, driverVersion))
{
static uint64 driversVersion[]=
{
NVIDIA_RECOMMANDED_DRIVERS,
ATI_RECOMMANDED_DRIVERS
};
static const char *driversTest[]=
{
NVIDIA_RECOMMANDED_DRIVERS_STRING_TEST,
ATI_RECOMMANDED_DRIVERS_STRING_TEST
};
static const char *driversNTest[]=
{
NVIDIA_RECOMMANDED_DRIVERS_STRING_NTEST,
NULL
};
static const char *driversURL[]=
{
NVIDIA_RECOMMANDED_DRIVERS_URL,
ATI_RECOMMANDED_DRIVERS_URL
};
static const char *driversVendor[]=
{
NVIDIA_RECOMMANDED_DRIVERS_VENDOR,
ATI_RECOMMANDED_DRIVERS_VENDOR,
};
uint i;
for (i=0; i< sizeofarray(driversVersion); i++)
{
string lwr = toLower(deviceName);
if ((lwr.find (driversTest[i])!=string::npos) && (driversNTest[i]==NULL || lwr.find (driversNTest[i])==string::npos))
{
if (driverVersion < driversVersion[i])
{
ucstring message = CI18N::get ("uiUpdateDisplayDriversNotUpToDate") + "\n\n";
// message += CI18N::get ("uiUpdateDisplayDriversVendor") + driversVendor[i] + "\n";
message += CI18N::get ("uiUpdateDisplayDriversCard") + deviceName + "\n";
message += CI18N::get ("uiUpdateDisplayDriversCurrent") + getVersionString (driverVersion) + "\n";
message += CI18N::get ("uiUpdateDisplayDriversRecommanded") + getVersionString (driversVersion[i]) + "\n\n";
message += CI18N::get ("uiUpdateDisplayDrivers") + "\n";
if (ClientQuestion (message))
{
openURL(driversURL[i]);
extern void quitCrashReport ();
quitCrashReport ();
exit (EXIT_FAILURE);
}
}
break;
}
}
if (i==sizeof (driversVersion)/sizeof(uint))
nlwarning ("Unknown video card : %s", deviceName.c_str());
}
else
nlwarning ("Can't check video driver version");
}
void checkDriverDepth ()
{
// Check desktop is in 32 bit else no window mode allowed.
if (ClientCfg.Windowed)
{
nlassert (Driver);
UDriver::CMode mode;
Driver->getCurrentScreenMode(mode);
#ifdef NL_OS_WINDOWS
if (mode.Depth != 32)
#else
if (mode.Depth != 16 && mode.Depth != 24 && mode.Depth != 32)
#endif
ExitClientError (CI18N::get ("uiDesktopNotIn32").toUtf8().c_str ());
}
}
void listStereoDisplayDevices(std::vector<NL3D::CStereoDeviceInfo> &devices)
{
bool cache = VRDeviceCache.empty();
nldebug("VR [C]: List devices");
if (cache)
{
VRDeviceCache.push_back(std::pair<std::string, std::string>("Auto", "0"));
}
IStereoDisplay::listDevices(devices);
for (std::vector<NL3D::CStereoDeviceInfo>::iterator it(devices.begin()), end(devices.end()); it != end; ++it)
{
std::stringstream name;
name << IStereoDisplay::getLibraryName(it->Library) << " - " << it->Manufacturer << " - " << it->ProductName;
std::stringstream fullname;
fullname << std::string("[") << name.str() << "] [" << it->Serial << "]";
nlinfo("VR [C]: Stereo Display: %s", name.str().c_str());
if (cache)
{
VRDeviceCache.push_back(std::pair<std::string, std::string>(name.str(), it->Serial)); // VR_CONFIG
}
}
}
void cacheStereoDisplayDevices() // VR_CONFIG
{
if (VRDeviceCache.empty())
{
std::vector<NL3D::CStereoDeviceInfo> devices;
listStereoDisplayDevices(devices);
}
}
void initStereoDisplayDevice()
{
if (ClientCfg.VREnable)
{
// VR_CONFIG
nldebug("VR [C]: Enabled");
std::vector<NL3D::CStereoDeviceInfo> devices;
listStereoDisplayDevices(devices);
CStereoDeviceInfo *deviceInfo = NULL;
if (ClientCfg.VRDisplayDevice == std::string("Auto"))
{
for (std::vector<NL3D::CStereoDeviceInfo>::iterator it(devices.begin()), end(devices.end()); it != end; ++it)
{
if ((*it).AllowAuto)
{
deviceInfo = &(*it);
break;
}
}
}
else
{
for (std::vector<NL3D::CStereoDeviceInfo>::iterator it(devices.begin()), end(devices.end()); it != end; ++it)
{
std::stringstream name;
name << IStereoDisplay::getLibraryName(it->Library) << " - " << it->Manufacturer << " - " << it->ProductName;
if (name.str() == ClientCfg.VRDisplayDevice)
deviceInfo = &(*it);
if (ClientCfg.VRDisplayDeviceId == it->Serial)
break;
}
}
if (deviceInfo)
{
nlinfo("VR [C]: Create VR stereo display device");
StereoDisplay = IStereoDisplay::createDevice(*deviceInfo);
if (StereoDisplay)
{
if (deviceInfo->Class == CStereoDeviceInfo::StereoHMD)
{
nlinfo("VR [C]: Stereo display device is a HMD");
StereoHMD = static_cast<IStereoHMD *>(StereoDisplay);
}
if (Driver) // VR_DRIVER
{
StereoDisplay->setDriver(Driver);
}
}
}
}
else
{
nldebug("VR [C]: NOT Enabled");
}
IStereoDisplay::releaseUnusedLibraries();
}
// we want to get executable directory
extern NLMISC::CCmdArgs Args;
static void addPaths(IProgressCallback &progress, const std::vector<std::string> &paths, bool recurse)
{
// all prefixes for paths
std::vector<std::string> directoryPrefixes;
// current directory has priority everywhere
directoryPrefixes.push_back(CPath::standardizePath(CPath::getCurrentPath()));
// startup directory
directoryPrefixes.push_back(Args.getStartupPath());
#if defined(NL_OS_WINDOWS)
// check in same directory as executable
directoryPrefixes.push_back(Args.getProgramPath());
#elif defined(NL_OS_MAC)
// check in bundle (Installer)
directoryPrefixes.push_back(getAppBundlePath() + "/Contents/Resources/");
// check in same directory as bundle (Steam)
directoryPrefixes.push_back(CPath::makePathAbsolute(getAppBundlePath() + "/..", ".", true));
#elif defined(NL_OS_UNIX)
// check in same directory as executable
directoryPrefixes.push_back(Args.getProgramPath());
// check in installed directory
if (CFile::isDirectory(getRyzomSharePrefix())) directoryPrefixes.push_back(CPath::standardizePath(getRyzomSharePrefix()));
#endif
std::map<std::string, sint> directoriesToProcess;
// first pass, build a map with all existing directories to process in second pass
for (uint j = 0; j < directoryPrefixes.size(); j++)
{
std::string directoryPrefix = directoryPrefixes[j];
for (uint i = 0; i < paths.size(); i++)
{
std::string directory = NLMISC::expandEnvironmentVariables(paths[i]);
// only prepend prefix if path is relative
if (!directory.empty() && !directoryPrefix.empty() && !CPath::isAbsolutePath(directory))
directory = directoryPrefix + directory;
// only process existing directories
if (CFile::isExists(directory))
directoriesToProcess[directory] = 1;
}
}
uint total = (uint)directoriesToProcess.size();
uint current = 0, next = 0;
std::map<std::string, sint>::const_iterator it = directoriesToProcess.begin(), iend = directoriesToProcess.end();
// second pass, add search paths
while (it != iend)
{
// update next progress value
++next;
progress.progress((float)current/(float)total);
progress.pushCropedValues((float)current/(float)total, (float)next/(float)total);
// next is current value
current = next;
CPath::addSearchPath(it->first, recurse, false, &progress);
progress.popCropedValues();
++it;
}
}
void addSearchPaths(IProgressCallback &progress)
{
// Add search path of UI addon. Allow only a subset of files.
// Must do it first because take precedence other standard files
InterfaceAddOnManager.addSearchFiles("uiaddon", "*.xml;*.lua;*.tga", "login_*.xml;out_v2_*.xml", &progress);
// Add Standard search paths
{
H_AUTO(InitRZAddSearchPath2)
addPaths(progress, ClientCfg.DataPath, true);
CPath::loadRemappedFiles("remap_files.csv");
}
addPaths(progress, ClientCfg.DataPathNoRecurse, false);
}
void addPreDataPaths(NLMISC::IProgressCallback &progress)
{
NLMISC::TTime initPaths = ryzomGetLocalTime ();
H_AUTO(InitRZAddSearchPaths);
addPaths(progress, ClientCfg.PreDataPath, true);
//nlinfo ("PROFILE: %d seconds for Add search paths Predata", (uint32)(ryzomGetLocalTime ()-initPaths)/1000);
}
static void addPackedSheetUpdatePaths(NLMISC::IProgressCallback &progress)
{
for(uint i = 0; i < ClientCfg.UpdatePackedSheetPath.size(); i++)
{
progress.progress((float)i/(float)ClientCfg.UpdatePackedSheetPath.size());
progress.pushCropedValues ((float)i/(float)ClientCfg.UpdatePackedSheetPath.size(), (float)(i+1)/(float)ClientCfg.UpdatePackedSheetPath.size());
CPath::addSearchPath(NLMISC::expandEnvironmentVariables(ClientCfg.UpdatePackedSheetPath[i]), true, false, &progress);
progress.popCropedValues();
}
}
#if defined(NL_OS_UNIX) && !defined(NL_OS_MAC)
static bool addRyzomIconBitmap(const std::string &directory, vector<CBitmap> &bitmaps)
{
if (CFile::isDirectory(directory))
{
// build filename from directory and default ryzom client icon name
std::string filename = NLMISC::toString("%s/%s.png", directory.c_str(), getRyzomClientIcon().c_str());
if (CFile::fileExists(filename))
{
CIFile file;
if (file.open(filename))
{
CBitmap bitmap;
if (bitmap.load(file))
{
bitmaps.push_back(bitmap);
return true;
}
}
}
}
return false;
}
#endif
//---------------------------------------------------
// initLog :
// Initialize the client.log file
//---------------------------------------------------
void initLog()
{
// Add a displayer for Debug Infos.
createDebug();
// Client.Log displayer
nlassert( !ErrorLog->getDisplayer("CLIENT.LOG") );
CFileDisplayer *ClientLogDisplayer = new CFileDisplayer(getLogDirectory() + "client.log", true, "CLIENT.LOG");
DebugLog->addDisplayer (ClientLogDisplayer);
InfoLog->addDisplayer (ClientLogDisplayer);
WarningLog->addDisplayer (ClientLogDisplayer);
ErrorLog->addDisplayer (ClientLogDisplayer);
AssertLog->addDisplayer (ClientLogDisplayer);
// Display the client version.
nlinfo("RYZOM VERSION: %s", getDebugVersion().c_str());
nlinfo("Memory: %s/%s", bytesToHumanReadable(CSystemInfo::availablePhysicalMemory()).c_str(), bytesToHumanReadable(CSystemInfo::totalPhysicalMemory()).c_str());
nlinfo("OS: %s", CSystemInfo::getOS().c_str());
nlinfo("Processor: %s", CSystemInfo::getProc().c_str());
#ifdef NL_OS_MAC
struct rlimit rlp, rlp2, rlp3;
getrlimit(RLIMIT_NOFILE, &rlp);
rlim_t value = 1024;
rlp2.rlim_cur = std::min(value, rlp.rlim_max);
rlp2.rlim_max = rlp.rlim_max;
if (setrlimit(RLIMIT_NOFILE, &rlp2))
{
if (errno == EINVAL)
{
nlwarning("Unable to set rlimit with error: the specified limit is invalid");
}
else if (errno == EPERM)
{
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");
}
else
{
nlwarning("Unable to set rlimit with error: unknown error");
}
}
getrlimit(RLIMIT_NOFILE, &rlp3);
nlinfo("rlimit before %llu %llu", (uint64)rlp.rlim_cur, (uint64)rlp.rlim_max);
nlinfo("rlimit after %llu %llu", (uint64)rlp3.rlim_cur, (uint64)rlp3.rlim_max);
// add the bundle's plugins path as library search path (for nel drivers)
if (CFile::isExists(getAppBundlePath() + "/Contents/PlugIns/nel"))
{
CLibrary::addLibPath(getAppBundlePath() + "/Contents/PlugIns/nel/");
}
#endif
}
//---------------------------------------------------
// prelogInit :
// Initialize the application before login
// if the init fails, call nlerror
//---------------------------------------------------
void prelogInit()
{
try
{
H_AUTO ( RZ_Client_Init );
// Assert if no more memory
set_new_handler(outOfMemory);
NLMISC_REGISTER_CLASS(CStage);
NLMISC_REGISTER_CLASS(CStageSet);
NLMISC_REGISTER_CLASS(CEntityManager);
NLMISC_REGISTER_CLASS(CCharacterCL);
NLMISC_REGISTER_CLASS(CPlayerCL);
NLMISC_REGISTER_CLASS(CUserEntity);
NLMISC_REGISTER_CLASS(CFxCL);
NLMISC_REGISTER_CLASS(CItemCL);
NLMISC_REGISTER_CLASS(CNamedEntityPositionState);
NLMISC_REGISTER_CLASS(CAnimalPositionState);
// Progress bar for init() and connection()
ProgressBar.reset (BAR_STEP_INIT_CONNECTION);
// save screen saver state and disable it
LastScreenSaverEnabled = CSystemUtils::isScreensaverEnabled();
if (LastScreenSaverEnabled)
CSystemUtils::enableScreensaver(false);
// Random init
srand ((uint)CTime::getLocalTime());
// Set FPU exceptions
#ifdef NL_OS_WINDOWS
_control87 (_EM_INVALID|_EM_DENORMAL/*|_EM_ZERODIVIDE|_EM_OVERFLOW*/|_EM_UNDERFLOW|_EM_INEXACT, _MCW_EM);
#endif // NL_OS_WINDOWS
FPU_CHECKER_ONCE
NLMISC::TTime initStart = ryzomGetLocalTime ();
// _CrtSetDbgFlag( _CRTDBG_CHECK_CRT_DF );
// Init XML Lib allocator
// Due to Bug #906, we disable the stl xml allocation
// nlverify (xmlMemSetup (XmlFree4NeL, XmlMalloc4NeL, XmlRealloc4NeL, XmlStrdup4NeL) == 0);
// Init the debug memory
initDebugMemory();
// Load the application configuration.
ucstring nmsg("Loading config file...");
ProgressBar.newMessage (nmsg);
ClientCfg.init(ConfigFileName);
CLoginProgressPostThread::getInstance().init(ClientCfg.ConfigFile);
sint cpuMask;
if (ClientCfg.CPUMask < 1)
{
CTime::CTimerInfo timerInfo;
NLMISC::CTime::probeTimerInfo(timerInfo);
cpuMask = timerInfo.RequiresSingleCore ? 1:0;
}
else
{
cpuMask = ClientCfg.CPUMask;
}
if (cpuMask) setCPUMask(cpuMask);
setCrashCallback(crashCallback);
// Display Some Info On CPU
displayCPUInfo();
FPU_CHECKER_ONCE
// create the save dir.
if (!CFile::isExists("save")) CFile::createDirectory("save");
// create the user dir.
if (!CFile::isExists("user")) CFile::createDirectory("user");
#if !FINAL_VERSION
// 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
//ICommand::execute("iFileAccessLogStart",*NLMISC::InfoLog);
#endif
// check "BuildName" in ClientCfg
//nlassert(!ClientCfg.BuildName.empty()); // TMP comment by nico do not commit
// Start memory allocation log
// if (ClientCfg.LogMemoryAllocation)
// NLMEMORY::StartAllocationLog ("alloc.memlog", ClientCfg.LogMemoryAllocationSize);
// Remap tga files on dds files.
CPath::remapExtension ("dds", "tga", true);
CPath::remapExtension ("dds", "png", true);
CPath::remapExtension ("png", "tga", true);
FPU_CHECKER_ONCE
addPreDataPaths(ProgressBar);
FPU_CHECKER_ONCE
{
H_AUTO(InitRZUIStr)
FPU_CHECKER_ONCE
// Set the data path for the localisation.
const ucstring nmsg("Loading I18N...");
ProgressBar.newMessage ( nmsg );
FPU_CHECKER_ONCE
STRING_MANAGER::CLoadProxy loadProxy;
CI18N::setLoadProxy(&loadProxy);
CI18N::load(ClientCfg.LanguageCode);
CI18N::setLoadProxy(NULL);
FPU_CHECKER_ONCE
// Yoyo: Append the skills and Bricks to the I18N
STRING_MANAGER::CStringManagerClient::initI18NSpecialWords(ClientCfg.LanguageCode);
FPU_CHECKER_ONCE
}
FPU_CHECKER_ONCE
// Check driver version
checkDriverVersion();
// Initialize the VR devices (even more important than the most important part of the client)
nmsg = "Initializing VR devices...";
ProgressBar.newMessage ( ClientCfg.buildLoadingString(nmsg) );
initStereoDisplayDevice(); // VR_CONFIG
// Create the driver (most important part of the client).
nmsg = "Creating 3d driver...";
ProgressBar.newMessage ( ClientCfg.buildLoadingString(nmsg) );
UDriver::TDriver driver = UDriver::OpenGl;
#ifdef NL_OS_WINDOWS
uintptr_t icon = (uintptr_t)LoadIcon(HInstance, MAKEINTRESOURCE(IDI_MAIN_ICON));
#else
uintptr_t icon = 0;
#endif // NL_OS_WINDOWS
switch(ClientCfg.Driver3D)
{
#ifdef NL_OS_WINDOWS
case CClientConfig::Direct3D:
driver = UDriver::Direct3d;
break;
#endif // NL_OS_WINDOWS
case CClientConfig::DrvAuto:
case CClientConfig::OpenGL:
driver = UDriver::OpenGl;
break;
case CClientConfig::OpenGLES:
driver = UDriver::OpenGlEs;
break;
default:
break;
}
Driver = UDriver::createDriver(icon, driver);
if(Driver == NULL)
{
ExitClientError (CI18N::get ("Can_t_load_the_display_driver").toUtf8().c_str ());
// ExitClientError() call exit() so the code after is never called
return;
}
// used to determine screen default resolution
if (ClientCfg.Width < 800 || ClientCfg.Height < 600)
{
UDriver::CMode mode;
CConfigFile::CVar *varPtr = NULL;
if (!ClientCfg.Windowed && Driver->getCurrentScreenMode(mode))
{
ClientCfg.Width = mode.Width;
ClientCfg.Height = mode.Height;
ClientCfg.Depth = mode.Depth;
ClientCfg.Frequency = mode.Frequency;
// update client.cfg with detected depth and frequency
varPtr = ClientCfg.ConfigFile.getVarPtr("Depth");
if(varPtr)
varPtr->forceAsInt(ClientCfg.Depth);
varPtr = ClientCfg.ConfigFile.getVarPtr("Frequency");
if(varPtr)
varPtr->forceAsInt(ClientCfg.Frequency);
}
else
{
ClientCfg.Width = 1024;
ClientCfg.Height = 768;
}
// update client.cfg with detected resolution
varPtr = ClientCfg.ConfigFile.getVarPtr("Width");
if(varPtr)
varPtr->forceAsInt(ClientCfg.Width);
varPtr = ClientCfg.ConfigFile.getVarPtr("Height");
if(varPtr)
varPtr->forceAsInt(ClientCfg.Height);
}
CLoginProgressPostThread::getInstance().step(CLoginStep(LoginStep_VideoModeSetup, "login_step_video_mode_setup"));
FPU_CHECKER_ONCE
// Check the driver is not is 16 bits
checkDriverDepth ();
UDriver::CMode mode;
bool forceWindowed1024x768 = true;
if (Driver->getCurrentScreenMode(mode))
{
// if screen mode lower than 1024x768, use same mode in fullscreen
if (mode.Width <= 1024 && mode.Height <= 768)
{
mode.Windowed = false;
forceWindowed1024x768 = false;
}
}
if (forceWindowed1024x768)
{
mode.Width = 1024;
mode.Height = 768;
mode.Windowed = true;
}
// Disable Hardware Vertex Program.
if(ClientCfg.DisableVtxProgram)
Driver->disableHardwareVertexProgram();
// Disable Hardware Vertex AGP.
if(ClientCfg.DisableVtxAGP)
Driver->disableHardwareVertexArrayAGP();
// Disable Hardware Texture Shader.
if(ClientCfg.DisableTextureShdr)
Driver->disableHardwareTextureShader();
if (StereoDisplay) // VR_CONFIG // VR_DRIVER
{
// override mode TODO
}
// Set the mode of the window.
if (!Driver->setDisplay (mode, false))
{
string msg;
if (mode.Windowed)
{
msg = CI18N::get ("can_t_create_a_window_display").toUtf8();
}
else
{
msg = CI18N::get ("can_t_create_a_fullscreen_display").toUtf8();
}
msg += " (%dx%d %d ";
msg += CI18N::get ("bits").toUtf8 ();
msg += ")";
ExitClientError (msg.c_str (), mode.Width, mode.Height, mode.Depth);
// ExitClientError() call exit() so the code after is never called
return;
}
// Enable or disable VSync
if (ClientCfg.WaitVBL)
Driver->setSwapVBLInterval(1);
else
Driver->setSwapVBLInterval(0);
// initialize system utils class
CSystemUtils::init();
CSystemUtils::setWindow(Driver->getDisplay());
CLoginProgressPostThread::getInstance().step(CLoginStep(LoginStep_VideoModeSetupHighColor, "login_step_video_mode_setup_high_color"));
#ifdef NL_OS_WINDOWS
CBGDownloaderAccess::getInstance().init();
if (SlashScreen)
DestroyWindow (SlashScreen);
#endif // NL_OS_WINDOW
// Set the title
Driver->setWindowTitle(CI18N::get("TheSagaOfRyzom"));
#if defined(NL_OS_UNIX) && !defined(NL_OS_MAC)
// add all existing directory prefixes
vector<string> directoryPrefixes;
// user local directory prefix (~/.local)
const char* homeDirectory = getenv("HOME");
if (homeDirectory)
directoryPrefixes.push_back(CPath::standardizePath(homeDirectory) + ".local");
// system local directory prefix (/usr/local)
directoryPrefixes.push_back("/usr/local");
// system directory prefix (/usr)
directoryPrefixes.push_back("/usr");
// all supported icon sizes
vector<uint> iconSizes;
iconSizes.push_back(512);
iconSizes.push_back(256);
iconSizes.push_back(128);
iconSizes.push_back(96);
iconSizes.push_back(64);
iconSizes.push_back(48);
iconSizes.push_back(32);
iconSizes.push_back(24);
iconSizes.push_back(22);
iconSizes.push_back(16);
vector<CBitmap> bitmaps;
// process all icon sizes
for(size_t j = 0; j < iconSizes.size(); ++j)
{
// process all directory prefixes
for(size_t i = 0; i < directoryPrefixes.size(); ++i)
{
uint size = iconSizes[j];
// build directory where to look for icon
std::string directory = toString("%s/share/icons/hicolor/%ux%u/apps", directoryPrefixes[i].c_str(), size, size);
// if found, skip other directories for this icon size
if (addRyzomIconBitmap(directory, bitmaps)) break;
}
}
if (bitmaps.empty())
{
// check if an icon is present in current directory
addRyzomIconBitmap(".", bitmaps);
}
Driver->setWindowIcon(bitmaps);
#endif
sint32 posX = 0, posY = 0;
if (ClientCfg.Windowed)
{
// use position saved in config
posX = ClientCfg.PositionX;
posY = ClientCfg.PositionY;
}
else
{
// position is not saved in config so center the window
if (Driver->getCurrentScreenMode(mode))
{
posX = (mode.Width - Driver->getWindowWidth())/2;
posY = (mode.Height - Driver->getWindowHeight())/2;
}
}
// Set the window position
Driver->setWindowPos(posX, posY);
// Show the window
Driver->showWindow();
// for background downloader : store this window handle in shared memory for later access
// (we use SendMessage to communicate with the background downloader)
// Enough AGP for vertices ?
if (Driver->getAvailableVertexAGPMemory () == 0)
{
/*
std::string deviceName;
uint64 driverVersion;
CSystemInfo::getVideoInfo(deviceName, driverVersion);
deviceName = NLMISC::toLower(deviceName);
// for radeon 7200, patch because agp crash with agp with OpenGL -> don't display the message
if (!(Driver->getNbTextureStages() <= 3 && strstr(deviceName.c_str(), "radeon")))
{*/
if (ClientQuestion (CI18N::get ("agp_trouble")))
{
openDoc ("client_troubles.html");
extern void quitCrashReport ();
quitCrashReport ();
exit (EXIT_FAILURE);
}
//}
}
FPU_CHECKER_ONCE
// Set the monitor color properties
CMonitorColorProperties monitorColor;
for (uint i=0; i<3; i++)
{
monitorColor.Contrast[i] = ClientCfg.Contrast;
monitorColor.Luminosity[i] = ClientCfg.Luminosity;
monitorColor.Gamma[i] = ClientCfg.Gamma;
}
if (!Driver->setMonitorColorProperties (monitorColor))
{
nlwarning("init : setMonitorColorProperties fails");
}
// The client require at least 2 textures.
if(Driver->getNbTextureStages() < 2)
throw Exception("Application require at least 2 textures stages !!");
Driver->enableUsedTextureMemorySum(true);
// Initialize the font manager.
Driver->setFontManagerMaxMemory(2000000);
// Init the DXTCCompression.
Driver->forceDXTCCompression(ClientCfg.ForceDXTC);
// Set the anisotropic filter
Driver->setAnisotropicFilter(ClientCfg.AnisotropicFilter);
// Divide the texture size.
if (ClientCfg.DivideTextureSizeBy2)
Driver->forceTextureResize(2);
else
Driver->forceTextureResize(1);
// Create a generic material.
GenericMat = Driver->createMaterial();
if(GenericMat.empty())
nlerror("init: Cannot Create the generic material.");
// Create a text context. We need to put the full path because we not already add search path
// resetTextContext ("bremenb.ttf", false);
resetTextContext ("ryzom.ttf", false);
CInterfaceManager::getInstance();
// Yoyo: initialize NOW the InputHandler for Event filtering.
CInputHandlerManager *InputHandlerManager = CInputHandlerManager::getInstance();
InputHandlerManager->addToServer (&Driver->EventServer);
std::string filename = CPath::lookup( ClientCfg.XMLInputFile, false );
if( !filename.empty() )
InputHandlerManager->readInputConfigFile( filename );
ProgressBar.setFontFactor(0.85f);
nmsg = "Loading background...";
ProgressBar.newMessage ( ClientCfg.buildLoadingString(nmsg) );
// Choose a tips of the day
selectTipsOfTheDay (rand());
// Create the loading texture. We can't do that before because we need to add pre search path first and driver
//UseEscapeDuringLoading = USE_ESCAPE_DURING_LOADING;
UseEscapeDuringLoading = false;
beginLoading (StartBackground); //put here intro Gameforge if wanted
FPU_CHECKER_ONCE
// Define the root path that contains all data needed for the application.
nmsg = "Adding search paths...";
ProgressBar.newMessage ( ClientCfg.buildLoadingString(nmsg) );
if(!ClientCfg.TestBrowser)
{
NLMISC::TTime initPaths = ryzomGetLocalTime ();
addSearchPaths(ProgressBar);
if (ClientCfg.UpdatePackedSheet)
{
addPackedSheetUpdatePaths(ProgressBar);
}
//nlinfo ("PROFILE: %d seconds for Add search paths Data", (uint32)(ryzomGetLocalTime ()-initPaths)/1000);
}
// Register the reflected classes
registerInterfaceElements();
// set driver used by bloom (must be called before init)
CBloomEffect::getInstance().setDriver(Driver);
// init bloom effect
CBloomEffect::getInstance().init();
if (StereoDisplay) // VR_CONFIG
{
// Init stereo display resources
StereoDisplay->setDriver(Driver); // VR_DRIVER
}
nlinfo ("PROFILE: %d seconds for prelogInit", (uint32)(ryzomGetLocalTime ()-initStart)/1000);
FPU_CHECKER_ONCE
}
catch (const Exception &e)
{
ExitClientError (e.what());
}
}
// ***************************************************************************
void initBotObjectSelection()
{
// Get the driver shape bank
UShapeBank *shapeBank= Driver->getShapeBank();
if(!shapeBank)
return;
// Parse all .creature
const CSheetManager::TEntitySheetMap &sheets= SheetMngr.getSheets();
CSheetManager::TEntitySheetMap::const_iterator it= sheets.begin();
for(;it!=sheets.end();it++)
{
CEntitySheet *entitySheet= it->second.EntitySheet;
if(entitySheet->Type!=CEntitySheet::FAUNA)
continue;
const CCharacterSheet *sheet= dynamic_cast<const CCharacterSheet *>(entitySheet);
if(sheet)
{
// If the entity define no Skeleton, it is not skinned
// thus we must force the shape to bkup the geometry in RAM, for fast selection
if(sheet->IdSkelFilename==CStaticStringMapper::emptyId())
{
// For all equipement (yoyo: Body is theorically the only one bound)
std::vector<const CCharacterSheet::CEquipment*> equipList;
sheet->getWholeEquipmentList(equipList);
for(uint i=0;i<equipList.size();i++)
{
string strShape= equipList[i]->getItem();
// if some item bound
if(!strShape.empty())
{
// If this is a reference on an item
string ext = CFile::getExtension(strShape);
if((ext == "item") || (ext == "sitem"))
{
// IS the item a valid one ?
CSheetId itemId;
if(itemId.buildSheetId(NLMISC::toLower(strShape)))
{
// Get this item sheet ?
CItemSheet *itemSheet= dynamic_cast<CItemSheet *>(SheetMngr.get(itemId));
if(itemSheet)
{
// and so get the actual shape name
strShape= itemSheet->getShape();
}
}
}
// If ok (after possible .sitem translation)
if(!strShape.empty())
{
shapeBank->buildSystemGeometryForshape(strShape);
}
}
}
}
}
}
}
// ***************************************************************************
//---------------------------------------------------
// postlogInit :
// Initialize the application after login
// if the init fails, call nlerror
//---------------------------------------------------
void postlogInit()
{
Driver->clearBuffers(CRGBA::Black);
Driver->swapBuffers();
CNiceInputAuto niceInputs;
ucstring nmsg;
try
{
NLMISC::TTime initStart = ryzomGetLocalTime();
NLMISC::TTime initLast = initStart;
NLMISC::TTime initCurrent = initLast;
{
H_AUTO(InitRZNetwk)
// Initialize the Generic Message Header Manager.
nmsg = "Initializing network...";
ProgressBar.newMessage ( ClientCfg.buildLoadingString(nmsg) );
std::string msgXMLPath = CPath::lookup("msg.xml");
GenericMsgHeaderMngr.init(msgXMLPath);
initializeNetwork();
initLast = initCurrent;
initCurrent = ryzomGetLocalTime();
//nlinfo ("PROFILE: %d seconds (%d total) for Initializing network", (uint32)(initCurrent-initLast)/1000, (uint32)(initCurrent-initStart)/1000);
}
{
H_AUTO(InitRZChat)
// init the chat manager
nmsg = "Initializing chat manager...";
ProgressBar.newMessage ( ClientCfg.buildLoadingString(nmsg) );
ChatMngr.init( CPath::lookup("chat_static.cdb") );
initLast = initCurrent;
initCurrent = ryzomGetLocalTime();
//nlinfo ("PROFILE: %d seconds (%d total) for Initializing chat manager", (uint32)(initCurrent-initLast)/1000, (uint32)(initCurrent-initStart)/1000);
}
{
H_AUTO(InitRZLigo)
// Read the ligo primitive class file
nmsg = "Initializing primitive classes...";
ProgressBar.newMessage ( ClientCfg.buildLoadingString(nmsg) );
if (!LigoConfig.readPrimitiveClass (ClientCfg.LigoPrimitiveClass.c_str(), false))
{
nlwarning ("Can't load primitive class file %s", ClientCfg.LigoPrimitiveClass.c_str());
}
initLast = initCurrent;
initCurrent = ryzomGetLocalTime();
//nlinfo ("PROFILE: %d seconds (%d total) for Initializing primitive classes", (uint32)(initCurrent-initLast)/1000, (uint32)(initCurrent-initStart)/1000);
}
// set the primitive context
CPrimitiveContext::instance().CurrentLigoConfig = &LigoConfig;
{
H_AUTO(InitRZShIdI)
nmsg = "Initializing sheets...";
ProgressBar.newMessage ( ClientCfg.buildLoadingString(nmsg) );
// Initialize Sheet IDs.
CSheetId::init (ClientCfg.UpdatePackedSheet);
initLast = initCurrent;
initCurrent = ryzomGetLocalTime();
}
{
H_AUTO(InitRZSound)
// Init the sound manager
nmsg = "Initializing sound manager...";
ProgressBar.newMessage ( ClientCfg.buildLoadingString(nmsg) );
if(ClientCfg.SoundOn)
{
SoundMngr = new CSoundManager(&ProgressBar);
try
{
SoundMngr->init(&ProgressBar);
}
catch(const Exception &e)
{
nlwarning("init : Error when creating 'SoundMngr' : %s", e.what());
delete SoundMngr;
SoundMngr = NULL;
}
// Play Music just after the SoundMngr is inited
if(SoundMngr)
{
// init the SoundMngr with backuped volume
SoundMngr->setSFXVolume(ClientCfg.SoundSFXVolume);
SoundMngr->setGameMusicVolume(ClientCfg.SoundGameMusicVolume);
// no fadein, and not async because don't work well because of loading in the main thread
// Force use GameMusic volume
const uint fadeInTime= 500;
SoundMngr->playMusic(ClientCfg.SoundOutGameMusic, fadeInTime, false, true, true);
// Because of blocking loading, force the fadeIn
TTime t0= ryzomGetLocalTime();
TTime t1;
while((t1=ryzomGetLocalTime())<t0+fadeInTime)
{
//ProgressBar.progress(1.f);
SoundMngr->updateAudioMixerOnly();
}
}
}
CPath::memoryCompress(); // Because sound call addSearchPath
initLast = initCurrent;
initCurrent = ryzomGetLocalTime();
//nlinfo ("PROFILE: %d seconds (%d total) for Initializing sound manager", (uint32)(initCurrent-initLast)/1000, (uint32)(initCurrent-initStart)/1000);
}
{
H_AUTO(InitRZSheetL)
// load packed sheets
nmsg = "Loading sheets...";
ProgressBar.newMessage ( ClientCfg.buildLoadingString(nmsg) );
SheetMngr.setOutputDataPath("../../client/data");
SheetMngr.load (ProgressBar, ClientCfg.UpdatePackedSheet, ClientCfg.NeedComputeVS, ClientCfg.DumpVSIndex);
initLast = initCurrent;
initCurrent = ryzomGetLocalTime();
//nlinfo ("PROFILE: %d seconds (%d total) for Initializing sheets", (uint32)(initCurrent-initLast)/1000, (uint32)(initCurrent-initStart)/1000);
}
{
nmsg = "Initializing bricks...";
ProgressBar.newMessage ( ClientCfg.buildLoadingString(nmsg) );
CSBrickManager::getInstance()->init(); // Must be done after sheet loading
//STRING_MANAGER::CStringManagerClient::specialWordsMemoryCompress(); // Must be done after brick manager init
initLast = initCurrent;
initCurrent = ryzomGetLocalTime();
//nlinfo ("PROFILE: %d seconds (%d total) for Initializing bricks", (uint32)(initCurrent-initLast)/1000, (uint32)(initCurrent-initStart)/1000);
}
if (!ClientCfg.Light)
{
H_AUTO(InitRZCh)
nmsg = "Initializing Color Slot...";
ProgressBar.newMessage ( ClientCfg.buildLoadingString(nmsg) );
// Initialize the color slot manager
initColorSlotManager();
nmsg = "Initializing Gabarit Set...";
ProgressBar.newMessage ( ClientCfg.buildLoadingString(nmsg) );
// Initialize the set of gabarit
GabaritSet.loadGabarits (ProgressBar);
nmsg = "Initializing Hair Set...";
ProgressBar.newMessage ( ClientCfg.buildLoadingString(nmsg) );
// Initialize the hair sets
HairSet.init (ProgressBar);
nmsg = "Initializing Starting Role Set...";
ProgressBar.newMessage ( ClientCfg.buildLoadingString(nmsg) );
// Init all BotObjects for fast selection
nmsg = "Initializing Bot Objects...";
ProgressBar.newMessage ( ClientCfg.buildLoadingString(nmsg) );
initBotObjectSelection();
initLast = initCurrent;
initCurrent = ryzomGetLocalTime();
//nlinfo ("PROFILE: %d seconds (%d total) for Initializing Color Slot etc.", (uint32)(initCurrent-initLast)/1000, (uint32)(initCurrent-initStart)/1000);
}
else
{
// To have the same number of newMessage in client light
nmsg = "";
ProgressBar.newMessage (nmsg);
ProgressBar.newMessage (nmsg);
ProgressBar.newMessage (nmsg);
ProgressBar.newMessage (nmsg);
ProgressBar.newMessage (nmsg);
}
// Initialize MovieShooter
{
nmsg = "Initializing Movie Shooter ...";
ProgressBar.newMessage ( ClientCfg.buildLoadingString(nmsg) );
if(ClientCfg.MovieShooterMemory>0)
{
MovieShooter.init(ClientCfg.MovieShooterMemory);
MovieShooter.setFrameSkip(ClientCfg.MovieShooterFrameSkip);
}
initLast = initCurrent;
initCurrent = ryzomGetLocalTime();
//nlinfo ("PROFILE: %d seconds (%d total) for Initializing Movie Shooter", (uint32)(initCurrent-initLast)/1000, (uint32)(initCurrent-initStart)/1000);
}
{
nmsg = "Initializing primitives...";
ProgressBar.newMessage ( ClientCfg.buildLoadingString(nmsg) );
// Register the ligo primitives for .primitive sheets
NLLIGO::Register ();
// Load PACS primitive
initPrimitiveBlocks();
initLast = initCurrent;
initCurrent = ryzomGetLocalTime();
//nlinfo ("PROFILE: %d seconds (%d total) for Initializing primitives", (uint32)(initCurrent-initLast)/1000, (uint32)(initCurrent-initStart)/1000);
}
{
nmsg = "Executing cfg file start commands...";
ProgressBar.newMessage ( ClientCfg.buildLoadingString(nmsg) );
// Call the user commands from the config file if any
CConfigFile::CVar *var;
if ((var = ClientCfg.ConfigFile.getVarPtr ("StartCommands")) != NULL)
{
for (uint i = 0; i < var->size(); i++)
{
ICommand::execute (var->asString(i), *InfoLog);
}
}
initLast = initCurrent;
initCurrent = ryzomGetLocalTime();
//nlinfo ("PROFILE: %d seconds (%d total) for Executing cfg file start commands", (uint32)(initCurrent-initLast)/1000, (uint32)(initCurrent-initStart)/1000);
}
// Next step will be the connection with the server.
nmsg = "Connecting...";
ProgressBar.newMessage ( ClientCfg.buildLoadingString(nmsg) );
nlinfo ("PROFILE: %d seconds for postlogInit", (uint32)(ryzomGetLocalTime ()-initStart)/1000);
}
catch (const Exception &e)
{
ExitClientError (e.what());
}
}// init //