546799874e
--HG-- branch : gui-refactoring
1459 lines
43 KiB
C++
1459 lines
43 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"
|
|
// 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"
|
|
// Net.
|
|
#include "nel/net/email.h"
|
|
// Ligo.
|
|
#include "nel/ligo/ligo_config.h"
|
|
|
|
// Std.
|
|
#include <fstream>
|
|
// Game Share
|
|
#include "game_share/ryzom_version.h"
|
|
// 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 "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 "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
|
|
|
|
#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;
|
|
|
|
CMsgBoxDisplayer MsgBoxError;
|
|
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));
|
|
::SendMessage(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"));
|
|
}
|
|
|
|
// For multi cpu, active only one CPU for the main thread
|
|
uint64 Debug_OldCPUMask= 0;
|
|
uint64 Debug_NewCPUMask= 0;
|
|
void setCPUMask ()
|
|
{
|
|
uint64 cpuMask = IProcess::getCurrentProcess ()->getCPUMask();
|
|
Debug_OldCPUMask= cpuMask;
|
|
|
|
// get the processor to allow process
|
|
uint i = 0;
|
|
while ((i<64) && ((cpuMask&(SINT64_CONSTANT(1)<<i)) == 0))
|
|
i++;
|
|
|
|
// Set the CPU mask
|
|
if (i<64)
|
|
{
|
|
IProcess::getCurrentProcess ()->setCPUMask(1<<i);
|
|
//IThread::getCurrentThread ()->setCPUMask (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 = deviceName;
|
|
strlwr(lwr);
|
|
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 checkNoATIOpenGL()
|
|
{
|
|
string deviceName;
|
|
uint64 driverVersion;
|
|
if (CSystemInfo::getVideoInfo (deviceName, driverVersion))
|
|
{
|
|
string lwr = deviceName;
|
|
strlwr(lwr);
|
|
if (lwr.find (ATI_RECOMMANDED_DRIVERS_STRING_TEST)!=string::npos && ClientCfg.Driver3D==CClientConfig::OpenGL)
|
|
{
|
|
// special case for radeon 7500 or less : doesn't issue message since doesn't work with Direct3D for now
|
|
if (!(strstr(lwr.c_str() , "radeon 7000") || strstr(lwr.c_str() , "radeon 7200") || strstr(lwr.c_str() , "radeon 7500")))
|
|
{
|
|
ucstring message= CI18N::get("uiUseATID3D");
|
|
if (ClientQuestion (message))
|
|
{
|
|
ClientCfg.Driver3D= CClientConfig::DrvAuto;
|
|
ClientCfg.writeString("Driver3D", "Auto");
|
|
ClientCfg.ConfigFile.save();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
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 ());
|
|
}
|
|
}
|
|
|
|
static std::string replaceApplicationDirToken(const std::string &dir)
|
|
{
|
|
|
|
#ifdef NL_OS_MAC
|
|
// if client_default.cfg is not in current directory, and it's not an absolute path, use application default directory
|
|
if (!CFile::isExists("client_default.cfg") && dir.size()>0 && dir[0]!='/')
|
|
{
|
|
return getAppBundlePath() + "/Contents/Resources/" + dir;
|
|
}
|
|
#else
|
|
static const std::string token = "<ApplicationDir>";
|
|
std::string::size_type pos = dir.find(token);
|
|
if (pos != std::string::npos)
|
|
return dir.substr(0, pos) + getAppBundlePath() + dir.substr(pos + token.length());
|
|
#endif
|
|
|
|
// preDataPath = getAppBundlePath() + "/Contents/Resources/" + preDataPath;
|
|
|
|
return dir;
|
|
}
|
|
|
|
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)
|
|
for (uint i = 0; i < ClientCfg.DataPath.size(); i++)
|
|
{
|
|
progress.progress ((float)i/(float)ClientCfg.DataPath.size());
|
|
progress.pushCropedValues ((float)i/(float)ClientCfg.DataPath.size(), (float)(i+1)/(float)ClientCfg.DataPath.size());
|
|
|
|
CPath::addSearchPath(replaceApplicationDirToken(ClientCfg.DataPath[i]), true, false, &progress);
|
|
|
|
progress.popCropedValues ();
|
|
}
|
|
|
|
CPath::loadRemappedFiles("remap_files.csv");
|
|
}
|
|
for (uint i = 0; i < ClientCfg.DataPathNoRecurse.size(); i++)
|
|
{
|
|
progress.progress ((float)i/(float)ClientCfg.DataPathNoRecurse.size());
|
|
progress.pushCropedValues ((float)i/(float)ClientCfg.DataPathNoRecurse.size(), (float)(i+1)/(float)ClientCfg.DataPathNoRecurse.size());
|
|
|
|
CPath::addSearchPath(replaceApplicationDirToken(ClientCfg.DataPathNoRecurse[i]), false, false, &progress);
|
|
|
|
progress.popCropedValues ();
|
|
}
|
|
}
|
|
|
|
|
|
void addPreDataPaths(NLMISC::IProgressCallback &progress)
|
|
{
|
|
NLMISC::TTime initPaths = ryzomGetLocalTime ();
|
|
H_AUTO(InitRZAddSearchPaths)
|
|
for (uint i = 0; i < ClientCfg.PreDataPath.size(); i++)
|
|
{
|
|
progress.progress ((float)i/(float)ClientCfg.PreDataPath.size());
|
|
progress.pushCropedValues ((float)i/(float)ClientCfg.PreDataPath.size(), (float)(i+1)/(float)ClientCfg.PreDataPath.size());
|
|
|
|
CPath::addSearchPath(replaceApplicationDirToken(ClientCfg.PreDataPath[i]), true, false, &progress);
|
|
|
|
progress.popCropedValues ();
|
|
}
|
|
//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(replaceApplicationDirToken(ClientCfg.UpdatePackedSheetPath[i]), true, false, &progress);
|
|
progress.popCropedValues();
|
|
}
|
|
}
|
|
|
|
//---------------------------------------------------
|
|
// prelogInit :
|
|
// Initialize the application before login
|
|
// if the init fails, call nlerror
|
|
//---------------------------------------------------
|
|
void prelogInit()
|
|
{
|
|
try
|
|
{
|
|
// Assert if no more memory
|
|
// NLMEMORY::SetOutOfMemoryHook(outOfMemory);
|
|
|
|
// Progress bar for init() and connection()
|
|
ProgressBar.reset (BAR_STEP_INIT_CONNECTION);
|
|
|
|
set_new_handler(outOfMemory);
|
|
|
|
// 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
|
|
|
|
setCPUMask();
|
|
|
|
FPU_CHECKER_ONCE
|
|
|
|
NLMISC::TTime initStart = ryzomGetLocalTime ();
|
|
|
|
H_AUTO ( RZ_Client_Init );
|
|
|
|
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);
|
|
|
|
// _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();
|
|
|
|
// 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);
|
|
|
|
setCrashCallback(crashCallback);
|
|
|
|
// Display Some Info On CPU
|
|
displayCPUInfo();
|
|
|
|
// Display the client version.
|
|
#if FINAL_VERSION
|
|
nlinfo("RYZOM VERSION : FV %s ("__DATE__" "__TIME__")", RYZOM_VERSION);
|
|
#else
|
|
nlinfo("RYZOM VERSION : DEV %s ("__DATE__" "__TIME__")", RYZOM_VERSION);
|
|
#endif
|
|
|
|
FPU_CHECKER_ONCE
|
|
|
|
// Set default email value for reporting error
|
|
setReportEmailFunction ((void*)sendEmail);
|
|
setDefaultEmailParams ("smtp.nevrax.com", "", "ryzombug@nevrax.com");
|
|
|
|
// 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
|
|
|
|
// Load the application configuration.
|
|
ucstring nmsg("Loading config file...");
|
|
ProgressBar.newMessage (nmsg);
|
|
|
|
ClientCfg.init(ConfigFileName);
|
|
|
|
CLoginProgressPostThread::getInstance().init(ClientCfg.ConfigFile);
|
|
|
|
// tmp for patcher debug
|
|
extern void tmpFlagMainlandPatchCategories(NLMISC::CConfigFile &cf);
|
|
extern void tmpFlagRemovedPatchCategories(NLMISC::CConfigFile &cf);
|
|
tmpFlagMainlandPatchCategories(ClientCfg.ConfigFile);
|
|
tmpFlagRemovedPatchCategories(ClientCfg.ConfigFile);
|
|
|
|
|
|
// 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
|
|
|
|
uint i;
|
|
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();
|
|
|
|
// Check ATI not in OpenGL
|
|
checkNoATIOpenGL();
|
|
// Create the driver (most important part of the client).
|
|
nmsg = "Creating 3d driver...";
|
|
ProgressBar.newMessage ( ClientCfg.buildLoadingString(nmsg) );
|
|
|
|
bool direct3D = false;
|
|
|
|
#ifdef NL_OS_WINDOWS
|
|
switch(ClientCfg.Driver3D)
|
|
{
|
|
case CClientConfig::DrvAuto:
|
|
{
|
|
// Fallback to D3D for card other than nVidia
|
|
std::string deviceName;
|
|
uint64 drvVersion;
|
|
CSystemInfo::getVideoInfo( deviceName, drvVersion);
|
|
strlwr(deviceName);
|
|
direct3D = strstr(deviceName.c_str(), NVIDIA_RECOMMANDED_DRIVERS_STRING_TEST) == NULL;
|
|
}
|
|
break;
|
|
case CClientConfig::OpenGL:
|
|
direct3D = false;
|
|
break;
|
|
case CClientConfig::Direct3D:
|
|
direct3D = true;
|
|
break;
|
|
}
|
|
Driver = UDriver::createDriver ((uint)LoadIcon (HInstance, MAKEINTRESOURCE(IDI_MAIN_ICON)), direct3D);
|
|
|
|
#else // NL_OS_WINDOWS
|
|
Driver = UDriver::createDriver ();
|
|
#endif // NL_OS_WINDOWS
|
|
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;
|
|
}
|
|
|
|
CLoginProgressPostThread::getInstance().step(CLoginStep(LoginStep_VideoModeSetup, "login_step_video_mode_setup"));
|
|
|
|
FPU_CHECKER_ONCE
|
|
|
|
// Check the driver is not is 16 bits
|
|
checkDriverDepth ();
|
|
|
|
// For login phase, MUST be in windowed
|
|
UDriver::CMode mode;
|
|
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();
|
|
|
|
// Enable or disable VSync
|
|
if(ClientCfg.WaitVBL)
|
|
Driver->setSwapVBLInterval(1);
|
|
else
|
|
Driver->setSwapVBLInterval(0);
|
|
|
|
// 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;
|
|
}
|
|
|
|
// 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 icons
|
|
vector<string> filenames;
|
|
filenames.push_back("/usr/share/icons/hicolor/128x128/apps/ryzom.png");
|
|
filenames.push_back("/usr/share/icons/hicolor/48x48/apps/ryzom.png");
|
|
filenames.push_back("/usr/share/icons/hicolor/32x32/apps/ryzom.png");
|
|
filenames.push_back("/usr/share/icons/hicolor/24x24/apps/ryzom.png");
|
|
filenames.push_back("/usr/share/icons/hicolor/22x22/apps/ryzom.png");
|
|
filenames.push_back("/usr/share/icons/hicolor/16x16/apps/ryzom.png");
|
|
filenames.push_back("/usr/share/pixmaps/ryzom.png");
|
|
|
|
// check if an icon is present in registered paths
|
|
if(CPath::exists("ryzom.png"))
|
|
filenames.push_back(CPath::lookup("ryzom.png"));
|
|
|
|
vector<CBitmap> bitmaps;
|
|
|
|
for(size_t i = 0; i < filenames.size(); ++i)
|
|
{
|
|
CIFile file;
|
|
|
|
if (CFile::fileExists(filenames[i]) && file.open(filenames[i]))
|
|
{
|
|
CBitmap bitmap;
|
|
if (bitmap.load(file))
|
|
bitmaps.push_back(bitmap);
|
|
}
|
|
}
|
|
|
|
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
|
|
|
|
// Test mouse & keyboard low-level mode, if DisableDirectInput not set.
|
|
// In case of failure, exit the client.
|
|
// In case of success, set it back to normal mode, to provide for the user
|
|
// the ability to manually set the firewall's permissions when the client connects.
|
|
// The low-level mode will actually be set when "launching" (after loading).
|
|
if (!ClientCfg.DisableDirectInput)
|
|
{
|
|
// Test mouse and set back to normal mode
|
|
if (!Driver->enableLowLevelMouse (true, ClientCfg.HardwareCursor))
|
|
{
|
|
ExitClientError (CI18N::get ("can_t_initialise_the_mouse").toUtf8 ().c_str ());
|
|
// ExitClientError() call exit() so the code after is never called
|
|
return;
|
|
}
|
|
Driver->enableLowLevelMouse (false, ClientCfg.HardwareCursor);
|
|
|
|
// Test keyboard and set back to normal mode
|
|
// NB : keyboard will be initialized later now
|
|
/*if (!Driver->enableLowLevelKeyboard (true))
|
|
{
|
|
ExitClientError (CI18N::get ("can_t_initialise_the_keyboard").toUtf8 ().c_str ());
|
|
// ExitClientError() call exit() so the code after is never called
|
|
return;
|
|
}
|
|
Driver->enableLowLevelKeyboard (false);
|
|
*/
|
|
}
|
|
|
|
// Set the monitor color properties
|
|
CMonitorColorProperties monitorColor;
|
|
for (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);
|
|
|
|
// 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.");
|
|
|
|
// 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 );
|
|
|
|
// 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::create( Driver, TextContext );
|
|
|
|
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(!direct3D);
|
|
|
|
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::strlwr(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(InitRZSound)
|
|
|
|
// Init the sound manager
|
|
nmsg = "Initializing sound manager...";
|
|
ProgressBar.newMessage ( ClientCfg.buildLoadingString(nmsg) );
|
|
if(ClientCfg.SoundOn)
|
|
{
|
|
// tmp fix : it seems that, at this point, if the bg downloader window has focus and
|
|
// not the Ryzom one, then sound init fails
|
|
#ifdef NL_OS_WINDOWS
|
|
HWND hWnd = Driver->getDisplay ();
|
|
nlassert (hWnd);
|
|
ShowWindow(hWnd, SW_RESTORE);
|
|
SetForegroundWindow(hWnd);
|
|
#endif
|
|
SoundMngr = new CSoundManager(&ProgressBar);
|
|
try
|
|
{
|
|
SoundMngr->init(&ProgressBar);
|
|
}
|
|
catch(const Exception &e)
|
|
{
|
|
nlwarning("init : Error when creating 'SoundMngr' : %s", e.what());
|
|
// leak the alocated sound manager...
|
|
SoundMngr = 0;
|
|
}
|
|
|
|
// 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(InitRZShIdI)
|
|
|
|
nmsg = "Initializing sheets...";
|
|
ProgressBar.newMessage ( ClientCfg.buildLoadingString(nmsg) );
|
|
|
|
// Initialize Sheet IDs.
|
|
CSheetId::init (ClientCfg.UpdatePackedSheet);
|
|
|
|
// 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 //
|