From 4d5c10f77528a840818511b33bc0fdfdb667de75 Mon Sep 17 00:00:00 2001 From: Adam Johnson Date: Fri, 31 Jul 2015 14:28:06 -0400 Subject: [PATCH 1/7] Move plClient init to a thread This means that most users should see the game window pop up immediately after pressing login instead of seeing "Starting URU... Please wait" --- Sources/Plasma/Apps/plClient/CMakeLists.txt | 6 +- Sources/Plasma/Apps/plClient/plClient.cpp | 62 +--- Sources/Plasma/Apps/plClient/plClient.h | 3 +- .../Plasma/Apps/plClient/plClientLoader.cpp | 145 ++++++++ Sources/Plasma/Apps/plClient/plClientLoader.h | 110 ++++++ Sources/Plasma/Apps/plClient/winmain.cpp | 351 +++++------------- Sources/Plasma/CoreLib/hsThread_Win.cpp | 2 +- 7 files changed, 362 insertions(+), 317 deletions(-) create mode 100644 Sources/Plasma/Apps/plClient/plClientLoader.cpp create mode 100644 Sources/Plasma/Apps/plClient/plClientLoader.h diff --git a/Sources/Plasma/Apps/plClient/CMakeLists.txt b/Sources/Plasma/Apps/plClient/CMakeLists.txt index 9c0f7e65..a23b1c99 100644 --- a/Sources/Plasma/Apps/plClient/CMakeLists.txt +++ b/Sources/Plasma/Apps/plClient/CMakeLists.txt @@ -39,17 +39,15 @@ endif(PYTHONINTERP_FOUND) set(plClient_HEADERS plClient.h plClientCreatable.h - #plClientKey.h + plClientLoader.h plClientUpdateFormat.h - #plPluginClient.h ) set(plClient_SOURCES pfAllCreatables.cpp plAllCreatables.cpp plClient.cpp - #plClientKey.cpp - #plPluginClient.cpp + plClientLoader.cpp pnAllCreatables.cpp winmain.cpp ) diff --git a/Sources/Plasma/Apps/plClient/plClient.cpp b/Sources/Plasma/Apps/plClient/plClient.cpp index c07695f5..49cc921b 100644 --- a/Sources/Plasma/Apps/plClient/plClient.cpp +++ b/Sources/Plasma/Apps/plClient/plClient.cpp @@ -799,14 +799,6 @@ bool plClient::MsgReceive(plMessage* msg) return true; } - //============================================================================ - // plNetCommAuthMsg - //============================================================================ - if (plNetCommAuthMsg * authCommMsg = plNetCommAuthMsg::ConvertNoRef(msg)) { - IHandleNetCommAuthMsg(authCommMsg); - return true; - } - //============================================================================ // plResPatcherMsg //============================================================================ @@ -1379,10 +1371,6 @@ bool plClient::StartInit() // local data of course). ((plResManager *)hsgResMgr::ResMgr())->VerifyPages(); - // the dx8 audio system MUST be initialized - // before the database is loaded - SetForegroundWindow(fWindowHndl); - plgAudioSys::Init(); gAudio = plgAudioSys::Sys(); @@ -1439,7 +1427,6 @@ bool plClient::StartInit() // // Init Net before loading things // - plgDispatch::Dispatch()->RegisterForExactType(plNetCommAuthMsg::Index(), GetKey()); plNetClientMgr::GetInstance()->Init(); plAgeLoader::GetInstance()->Init(); @@ -1460,8 +1447,6 @@ bool plClient::StartInit() plMouseDevice::Instance()->SetDisplayResolution((float)fPipeline->Width(), (float)fPipeline->Height()); plInputManager::SetRecenterMouse(false); - IPlayIntroMovie("avi/CyanWorlds.webm", 0.f, 0.f, 0.f, 1.f, 1.f, 0.75); - if(GetDone()) return false; plgDispatch::Dispatch()->RegisterForExactType(plMovieMsg::Index(), GetKey()); // create the listener for the audio system: @@ -1472,22 +1457,15 @@ bool plClient::StartInit() plgDispatch::Dispatch()->RegisterForExactType(plAudioSysMsg::Index(), pLMod->GetKey()); plSynchedObject::PushSynchDisabled(false); // enable dirty tracking + return true; +} - if (NetCommGetStartupAge()->ageDatasetName.CompareI("StartUp") == 0) - { - plNetCommAuthMsg * msg = new plNetCommAuthMsg(); - msg->result = kNetSuccess; - msg->param = nil; - msg->Send(); - } - - // 2nd half of plClient initialization occurs after - // all network events have completed. Async events: - // - // 1) Download secure files - // - // Continue plClient init via IOnAsyncInitComplete(). - +//============================================================================ +bool plClient::BeginGame() +{ + IPlayIntroMovie("avi/CyanWorlds.webm", 0.f, 0.f, 0.f, 1.f, 1.f, 0.75); + if (GetDone()) return false; + IPatchGlobalAgeFiles(); return true; } @@ -2290,27 +2268,3 @@ void plClient::IHandlePatcherMsg (plResPatcherMsg * msg) { IOnAsyncInitComplete(); } - -//============================================================================ -void plClient::IHandleNetCommAuthMsg (plNetCommAuthMsg * msg) { - - plgDispatch::Dispatch()->UnRegisterForExactType(plNetCommAuthMsg::Index(), GetKey()); - - if (IS_NET_ERROR(msg->result)) { - char str[1024]; - StrPrintf( - str, - arrsize(str), - // fmt - "Authentication failed: NetError %u, %S.\n" - ,// values - msg->result, - NetErrorToString(msg->result) - ); - plNetClientApp::GetInstance()->QueueDisableNet(true, str); - return; - } - - // Patch them global files! - IPatchGlobalAgeFiles(); -} diff --git a/Sources/Plasma/Apps/plClient/plClient.h b/Sources/Plasma/Apps/plClient/plClient.h index c81fa37b..485d5045 100644 --- a/Sources/Plasma/Apps/plClient/plClient.h +++ b/Sources/Plasma/Apps/plClient/plClient.h @@ -177,7 +177,6 @@ protected: void ICompleteInit (); void IOnAsyncInitComplete (); void IHandlePatcherMsg (plResPatcherMsg * msg); - void IHandleNetCommAuthMsg (plNetCommAuthMsg * msg); bool IHandleAgeLoaded2Msg (plAgeLoaded2Msg * msg); bool IFlushRenderRequests(); @@ -286,6 +285,8 @@ public: virtual void WindowActivate(bool active); virtual bool WindowActive() const { return fWindowActive; } + bool BeginGame(); + void FlashWindow(); void SetMessagePumpProc( plMessagePumpProc proc ) { fMessagePumpProc = proc; } void ResetDisplayDevice(int Width, int Height, int ColorDepth, bool Windowed, int NumAASamples, int MaxAnisotropicSamples, bool VSync = false); diff --git a/Sources/Plasma/Apps/plClient/plClientLoader.cpp b/Sources/Plasma/Apps/plClient/plClientLoader.cpp new file mode 100644 index 00000000..3be92717 --- /dev/null +++ b/Sources/Plasma/Apps/plClient/plClientLoader.cpp @@ -0,0 +1,145 @@ +/*==LICENSE==* + +CyanWorlds.com Engine - MMOG client, server and tools +Copyright (C) 2011 Cyan Worlds, Inc. + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU 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 General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . + +Additional permissions under GNU GPL version 3 section 7 + +If you modify this Program, or any covered work, by linking or +combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK, +NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent +JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK +(or a modified version of those libraries), +containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA, +PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG +JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the +licensors of this Program grant you additional +permission to convey the resulting work. Corresponding Source for a +non-source form of such a combination shall include the source code for +the parts of OpenSSL and IJG JPEG Library used as well as that of the covered +work. + +You can contact Cyan Worlds, Inc. by email legal@cyan.com +or by snail mail at: +Cyan Worlds, Inc. +14617 N Newport Hwy +Mead, WA 99021 + +*==LICENSE==*/ + +#include "plClientLoader.h" +#include "plClient.h" +#include "plFileSystem.h" +#include "plPipeline.h" + +#include "hsWindows.h" +#include + +#include "plClientResMgr/plClientResMgr.h" +#include "plNetClient/plNetClientMgr.h" +#include "plPhysX/plSimulationMgr.h" +#include "plResMgr/plResManager.h" + +static plFileName s_physXSetupExe = "PhysX_Setup.exe"; + +static bool InitPhysX() +{ +#ifdef HS_BUILD_FOR_WIN32 + plSimulationMgr::Init(); + if (!plSimulationMgr::GetInstance()) { + if (plFileInfo(s_physXSetupExe).Exists()) { + // launch the PhysX installer + SHELLEXECUTEINFOW info; + memset(&info, 0, sizeof(info)); + info.cbSize = sizeof(info); + info.lpFile = s_physXSetupExe.AsString().ToWchar(); + info.fMask = SEE_MASK_NOCLOSEPROCESS | SEE_MASK_NOASYNC; + ShellExecuteExW(&info); + + // wait for completion + WaitForSingleObject(info.hProcess, INFINITE); + + // cleanup + CloseHandle(info.hProcess); + } else { + hsMessageBox("You must install PhysX before you can play URU.", "Error", hsMessageBoxNormal, hsMessageBoxIconError); + return false; + } + } + if (plSimulationMgr::GetInstance()) { + plSimulationMgr::GetInstance()->Suspend(); + return true; + } else { + hsMessageBox("PhysX install failed. You will not be able to play URU.", "Error", hsMessageBoxNormal, hsMessageBoxIconError); + return false; + } +#else + return false; +#endif // HS_BUILD_FOR_WIN32 +} + +hsError plClientLoader::Run() +{ + plResManager *resMgr = new plResManager; + resMgr->SetDataPath("dat"); + hsgResMgr::Init(resMgr); + + if (!plFileInfo("resource.dat").Exists()) { + hsMessageBox("Required file 'resource.dat' not found.", "Error", hsMessageBoxNormal); + return false; + } + plClientResMgr::Instance().ILoadResources("resource.dat"); + + fClient = new plClient; + fClient->SetWindowHandle(fWindow); + if (!InitPhysX() || fClient->InitPipeline() || !fClient->StartInit()) { + fClient->SetDone(true); + return hsFail; + } + return hsOK; +} + +void plClientLoader::Start() +{ + fClient->ResizeDisplayDevice(fClient->GetPipeline()->Width(), fClient->GetPipeline()->Height(), !fClient->GetPipeline()->IsFullScreen()); + + // Show the client window + ShowWindow(fWindow, SW_SHOW); + BringWindowToTop(fWindow); + + // Now, show the intro video, patch the global ages, etc... + fClient->BeginGame(); +} + +// =================================================== +void plClientLoader::ShutdownStart() +{ + // Ensure that the client actually inited + hsThread::Stop(); + + // Now request the sane exit + fClient->SetDone(true); + if (plNetClientMgr* mgr = plNetClientMgr::GetInstance()) + mgr->QueueDisableNet(false, nullptr); +} + +void plClientLoader::ShutdownEnd() +{ + if (fClient) + fClient->Shutdown(); + hsAssert(hsgResMgr::ResMgr()->RefCnt() == 1, "resMgr has too many refs, expect mem leaks"); + hsgResMgr::Shutdown(); +} diff --git a/Sources/Plasma/Apps/plClient/plClientLoader.h b/Sources/Plasma/Apps/plClient/plClientLoader.h new file mode 100644 index 00000000..e0a5bf73 --- /dev/null +++ b/Sources/Plasma/Apps/plClient/plClientLoader.h @@ -0,0 +1,110 @@ +/*==LICENSE==* + +CyanWorlds.com Engine - MMOG client, server and tools +Copyright (C) 2011 Cyan Worlds, Inc. + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU 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 General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . + +Additional permissions under GNU GPL version 3 section 7 + +If you modify this Program, or any covered work, by linking or +combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK, +NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent +JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK +(or a modified version of those libraries), +containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA, +PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG +JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the +licensors of this Program grant you additional +permission to convey the resulting work. Corresponding Source for a +non-source form of such a combination shall include the source code for +the parts of OpenSSL and IJG JPEG Library used as well as that of the covered +work. + +You can contact Cyan Worlds, Inc. by email legal@cyan.com +or by snail mail at: +Cyan Worlds, Inc. +14617 N Newport Hwy +Mead, WA 99021 + +*==LICENSE==*/ + +#include "HeadSpin.h" +#include "hsThread.h" +#include "hsWindows.h" + +class plClientLoader : private hsThread +{ + class plClient* fClient; + HWND fWindow; + + virtual void OnQuit() + { + SetQuit(true); + } + + /** Does the heavy lifting of client init */ + virtual hsError Run(); + +public: + plClientLoader() : fClient(nullptr) { } + + /** + * Initializes the client asyncrhonouslynn including: loading the localization, + * registry, dispatcher, etc. + */ + void Init() + { + hsAssert(fClient == nullptr, "trying to init the client more than once?"); + hsThread::Start(); + } + + /** + * Returns whether or not the client init is done + */ + bool IsInited() const { return hsThread::GetQuit(); } + + /** + * Sets the client HWND + */ + void SetClientWindow(HWND hWnd) { fWindow = hWnd; } + + /** + * Initial shutdown request received from Windows (or something)... start tear down + */ + void ShutdownStart(); + + /** + * Window mess cleaned up, time to commit hara-kiri + */ + void ShutdownEnd(); + + /** + * Launches the client window and starts the game. + * This will block if the client is not initialized. + */ + void Start(); + + /** + * Waits for the client to finish initing + */ + void Wait() { hsThread::Stop(); } + + /** Returns the current plClient instance */ + plClient* operator ->() const { return fClient; } + + /** Returns whether or not the client is non-null */ + operator bool() const { return fClient != nullptr; } +}; + diff --git a/Sources/Plasma/Apps/plClient/winmain.cpp b/Sources/Plasma/Apps/plClient/winmain.cpp index af179d9a..00c03dcf 100644 --- a/Sources/Plasma/Apps/plClient/winmain.cpp +++ b/Sources/Plasma/Apps/plClient/winmain.cpp @@ -52,7 +52,7 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com #include "hsStream.h" #include "plCmdParser.h" #include "plClient.h" -#include "plClientResMgr/plClientResMgr.h" +#include "plClientLoader.h" #include "pfCrashHandler/plCrashCli.h" #include "plNetClient/plNetClientMgr.h" #include "plInputCore/plInputDevice.h" @@ -66,7 +66,6 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com #include "plStatusLog/plStatusLog.h" #include "plProduct.h" #include "plNetGameLib/plNetGameLib.h" -#include "plPhysX/plSimulationMgr.h" #include "res/resource.h" @@ -114,7 +113,7 @@ int gWinBorderDX = GetSystemMetrics( SM_CXSIZEFRAME ); int gWinBorderDY = GetSystemMetrics( SM_CYSIZEFRAME ); int gWinMenuDY = GetSystemMetrics( SM_CYCAPTION ); -plClient *gClient; +plClientLoader gClient; bool gPendingActivate = false; bool gPendingActivateFlag = false; @@ -143,11 +142,6 @@ static wchar_t s_patcherExeName[] = L"UruLauncher.exe"; #endif // PLASMA_EXTERNAL_RELEASE -//============================================================================ -// PhysX installer -//============================================================================ -static wchar_t s_physXSetupExeName[] = L"PhysX_Setup.exe"; - //============================================================================ // LoginDialogParam //============================================================================ @@ -355,15 +349,11 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) break; case WM_CLOSE: - gClient->SetDone(TRUE); - if (plNetClientMgr * mgr = plNetClientMgr::GetInstance()) - mgr->QueueDisableNet(false, nil); + gClient.ShutdownStart(); DestroyWindow(gClient->GetWindowHandle()); break; case WM_DESTROY: - gClient->SetDone(TRUE); - if (plNetClientMgr * mgr = plNetClientMgr::GetInstance()) - mgr->QueueDisableNet(false, nil); + gClient.ShutdownStart(); PostQuitMessage(0); break; } @@ -456,156 +446,6 @@ void DeInitNetClientComm() NetCommShutdown(); } -BOOL CALLBACK WaitingForPhysXDialogProc( HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam ) -{ - switch( uMsg ) - { - case WM_INITDIALOG: - ::SetDlgItemText( hwndDlg, IDC_STARTING_TEXT, "Waiting for PhysX install..."); - return true; - - } - return 0; -} - -bool InitPhysX() -{ - bool physXInstalled = false; - while (!physXInstalled) - { - plSimulationMgr::Init(); - if (!plSimulationMgr::GetInstance()) - { - int ret = hsMessageBox("PhysX is not installed, or an older version is installed.\nInstall new version? (Game will exit if you click \"No\")", - "Missing PhysX", hsMessageBoxYesNo); - if (ret == hsMBoxNo) // exit if no - return false; - - // launch the PhysX installer - SHELLEXECUTEINFOW info; - memset(&info, 0, sizeof(info)); - info.cbSize = sizeof(info); - info.lpFile = s_physXSetupExeName; - info.fMask = SEE_MASK_NOCLOSEPROCESS | SEE_MASK_NOASYNC; - ShellExecuteExW(&info); - - // let the user know what's going on - HWND waitingDialog = ::CreateDialog(gHInst, MAKEINTRESOURCE(IDD_LOADING), NULL, WaitingForPhysXDialogProc); - - // run a loop to wait for it to quit, pumping the windows message queue intermittently - DWORD waitRet = WaitForSingleObject(info.hProcess, 100); - MSG msg; - while (waitRet == WAIT_TIMEOUT) - { - if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) - { - TranslateMessage(&msg); - DispatchMessage(&msg); - } - waitRet = WaitForSingleObject(info.hProcess, 100); - } - - // cleanup - CloseHandle(info.hProcess); - ::DestroyWindow(waitingDialog); - } - else - { - plSimulationMgr::GetInstance()->Suspend(); - physXInstalled = true; - } - } - return true; -} - -bool InitClient( HWND hWnd ) -{ - plResManager *resMgr = new plResManager; - resMgr->SetDataPath("dat"); - hsgResMgr::Init(resMgr); - - if (!plFileInfo("resource.dat").Exists()) - { - hsMessageBox("Required file 'resource.dat' not found.", "Error", hsMessageBoxNormal); - return false; - } - plClientResMgr::Instance().ILoadResources("resource.dat"); - - gClient = new plClient; - if( gClient == nil ) - return false; - - if (!InitPhysX()) - return false; - - gClient->SetWindowHandle( hWnd ); - - if( gClient->InitPipeline() ) - gClient->SetDone(true); - else - { - gClient->ResizeDisplayDevice(gClient->GetPipeline()->Width(), gClient->GetPipeline()->Height(), !gClient->GetPipeline()->IsFullScreen()); - } - - if( gPendingActivate ) - { - // We need this because the window gets a WM_ACTIVATE before we get to this function, so - // the above flag lets us know that we need to fake a late activate msg to the client - gClient->WindowActivate( gPendingActivateFlag ); - } - - gClient->SetMessagePumpProc( PumpMessageQueueProc ); - - return true; -} - -// Initializes all that windows junk, creates class then shows main window -BOOL WinInit(HINSTANCE hInst, int nCmdShow) -{ - // Fill out WNDCLASS info - WNDCLASS wndClass; - wndClass.style = CS_DBLCLKS; // CS_HREDRAW | CS_VREDRAW; - wndClass.lpfnWndProc = WndProc; - wndClass.cbClsExtra = 0; - wndClass.cbWndExtra = 0; - wndClass.hInstance = hInst; - wndClass.hIcon = LoadIcon(hInst, MAKEINTRESOURCE(IDI_ICON_DIRT)); - - wndClass.hCursor = LoadCursor(NULL, IDC_ARROW); - wndClass.hbrBackground = (struct HBRUSH__*) (GetStockObject(BLACK_BRUSH)); - wndClass.lpszMenuName = CLASSNAME; - wndClass.lpszClassName = CLASSNAME; - - // can only run one at a time anyway, so just quit if another is running - if (!RegisterClass(&wndClass)) - return FALSE; - - // Create a window - HWND hWnd = CreateWindow( - CLASSNAME, plProduct::LongName().c_str(), - WS_OVERLAPPEDWINDOW, - 0, 0, - 800 + gWinBorderDX * 2, - 600 + gWinBorderDY * 2 + gWinMenuDY, - NULL, NULL, hInst, NULL - ); - - if( !InitClient( hWnd ) ) - return FALSE; - - // Return false if window creation failed - if (!gClient->GetWindowHandle()) - { - OutputDebugString("Create window failed\n"); - return FALSE; - } - else - { - OutputDebugString("Create window OK\n"); - } - return TRUE; -} - // // For error logging // @@ -1065,34 +905,34 @@ BOOL CALLBACK UruLoginDialogProc( HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM return FALSE; } -BOOL CALLBACK SplashDialogProc( HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam ) +BOOL CALLBACK SplashDialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { - switch( uMsg ) + switch (uMsg) { - case WM_INITDIALOG: - switch (plLocalization::GetLanguage()) - { - case plLocalization::kFrench: - ::SetDlgItemText( hwndDlg, IDC_STARTING_TEXT, "Démarrage d'URU. Veuillez patienter..."); - break; - case plLocalization::kGerman: - ::SetDlgItemText( hwndDlg, IDC_STARTING_TEXT, "Starte URU, bitte warten ..."); - break; - case plLocalization::kSpanish: - ::SetDlgItemText( hwndDlg, IDC_STARTING_TEXT, "Iniciando URU, por favor espera..."); - break; - case plLocalization::kItalian: - ::SetDlgItemText( hwndDlg, IDC_STARTING_TEXT, "Avvio di URU, attendere..."); - break; - // default is English - case plLocalization::kJapanese: - ::SetDlgItemText( hwndDlg, IDC_STARTING_TEXT, "..."); - break; - default: - ::SetDlgItemText( hwndDlg, IDC_STARTING_TEXT, "Starting URU. Please wait..."); - break; - } - return true; + case WM_INITDIALOG: + switch (plLocalization::GetLanguage()) + { + case plLocalization::kFrench: + ::SetDlgItemText(hwndDlg, IDC_STARTING_TEXT, "Démarrage d'URU. Veuillez patienter..."); + break; + case plLocalization::kGerman: + ::SetDlgItemText(hwndDlg, IDC_STARTING_TEXT, "Starte URU, bitte warten ..."); + break; + case plLocalization::kSpanish: + ::SetDlgItemText(hwndDlg, IDC_STARTING_TEXT, "Iniciando URU, por favor espera..."); + break; + case plLocalization::kItalian: + ::SetDlgItemText(hwndDlg, IDC_STARTING_TEXT, "Avvio di URU, attendere..."); + break; + // default is English + case plLocalization::kJapanese: + ::SetDlgItemText(hwndDlg, IDC_STARTING_TEXT, "..."); + break; + default: + ::SetDlgItemText(hwndDlg, IDC_STARTING_TEXT, "Starting URU. Please wait..."); + break; + } + return true; } return 0; @@ -1118,7 +958,7 @@ LONG WINAPI plCustomUnhandledExceptionFilter( struct _EXCEPTION_POINTERS *Except // Now, try to create a nice exception dialog after plCrashHandler is done. s_crash.WaitForHandle(); - HWND parentHwnd = (gClient == nil) ? GetActiveWindow() : gClient->GetWindowHandle(); + HWND parentHwnd = gClient ? gClient->GetWindowHandle() : GetActiveWindow(); DialogBoxParam(gHInst, MAKEINTRESOURCE(IDD_EXCEPTION), parentHwnd, ExceptionDialogProc, NULL); // Trickle up the handlers @@ -1129,6 +969,40 @@ LONG WINAPI plCustomUnhandledExceptionFilter( struct _EXCEPTION_POINTERS *Except #include "pfConsoleCore/pfConsoleEngine.h" PF_CONSOLE_LINK_ALL() +bool WinInit(HINSTANCE hInst) +{ + // Fill out WNDCLASS info + WNDCLASS wndClass; + wndClass.style = CS_DBLCLKS; // CS_HREDRAW | CS_VREDRAW; + wndClass.lpfnWndProc = WndProc; + wndClass.cbClsExtra = 0; + wndClass.cbWndExtra = 0; + wndClass.hInstance = hInst; + wndClass.hIcon = LoadIcon(hInst, MAKEINTRESOURCE(IDI_ICON_DIRT)); + + wndClass.hCursor = LoadCursor(NULL, IDC_ARROW); + wndClass.hbrBackground = (struct HBRUSH__*) (GetStockObject(BLACK_BRUSH)); + wndClass.lpszMenuName = CLASSNAME; + wndClass.lpszClassName = CLASSNAME; + + // can only run one at a time anyway, so just quit if another is running + if (!RegisterClass(&wndClass)) + return false; + + // Create a window + HWND hWnd = CreateWindow( + CLASSNAME, plProduct::LongName().c_str(), + WS_OVERLAPPEDWINDOW, + 0, 0, + 800 + gWinBorderDX * 2, + 600 + gWinBorderDY * 2 + gWinMenuDY, + NULL, NULL, hInst, NULL + ); + gClient.SetClientWindow(hWnd); + gClient.Init(); + return true; +} + #include "plResMgr/plVersion.h" int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpCmdLine, int nCmdShow) { @@ -1241,6 +1115,10 @@ int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpCmdLine, int nC } #endif + // Set up to log errors by using hsDebugMessage + DebugInit(); + DebugMsgF("Plasma 2.0.%i.%i - %s", PLASMA2_MAJOR_VERSION, PLASMA2_MINOR_VERSION, plProduct::ProductString().c_str()); + FILE *serverIniFile = plFileSystem::Open(serverIni, "rb"); if (serverIniFile) { @@ -1254,6 +1132,12 @@ int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpCmdLine, int nC return PARABLE_NORMAL_EXIT; } + // Begin initializing the client in the background + if (!WinInit(hInst)) { + hsMessageBox("Failed to initialize plClient", "Error", hsMessageBoxNormal); + return PARABLE_NORMAL_EXIT; + } + NetCliAuthAutoReconnectEnable(false); InitNetClientComm(); @@ -1299,96 +1183,49 @@ int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpCmdLine, int nC curl_global_cleanup(); if (needExit) { + gClient.ShutdownStart(); + gClient.ShutdownEnd(); DeInitNetClientComm(); return PARABLE_NORMAL_EXIT; } NetCliAuthAutoReconnectEnable(true); - // VERY VERY FIRST--throw up our splash screen - HWND splashDialog = ::CreateDialog( hInst, MAKEINTRESOURCE( IDD_LOADING ), NULL, SplashDialogProc ); - // Install our unhandled exception filter for trapping all those nasty crashes in release build #ifndef HS_DEBUGGING LPTOP_LEVEL_EXCEPTION_FILTER oldFilter; oldFilter = SetUnhandledExceptionFilter( plCustomUnhandledExceptionFilter ); #endif - // - // Set up to log errors by using hsDebugMessage - // - DebugInit(); - DebugMsgF("Plasma 2.0.%i.%i - %s", PLASMA2_MAJOR_VERSION, PLASMA2_MINOR_VERSION, plProduct::ProductString().c_str()); - - for (;;) { - // Create Window - if (!WinInit(hInst, nCmdShow) || gClient->GetDone()) - break; - - // Done with our splash now - ::DestroyWindow( splashDialog ); - - if (!gClient) - break; - - // Show the main window - ShowWindow(gClient->GetWindowHandle(), SW_SHOW); - - // Be really REALLY forceful about being in the front - BringWindowToTop( gClient->GetWindowHandle() ); - - // Update the window - UpdateWindow(gClient->GetWindowHandle()); + // We should quite frankly be done initing the client by now. But, if not, spawn the good old + // "Starting URU, please wait..." dialog (not so yay) + if (!gClient.IsInited()) { + HWND splashDialog = ::CreateDialog(hInst, MAKEINTRESOURCE(IDD_LOADING), NULL, SplashDialogProc); + gClient.Wait(); + ::DestroyWindow(splashDialog); + } - // - // Init Application here - // - if( !gClient->StartInit() ) - break; - - // I want it on top! I mean it! - BringWindowToTop( gClient->GetWindowHandle() ); + // Main loop + if (gClient && !gClient->GetDone()) { + gClient->SetMessagePumpProc(PumpMessageQueueProc); + gClient.Start(); - // initialize dinput here: - if (gClient && gClient->GetInputManager()) - gClient->GetInputManager()->InitDInput(hInst, (HWND)gClient->GetWindowHandle()); - - // Seriously! - BringWindowToTop( gClient->GetWindowHandle() ); - - // - // Main loop - // MSG msg; - do - { + do { gClient->MainLoop(); - - if( gClient->GetDone() ) + if (gClient->GetDone()) break; // Look for a message - while (PeekMessage( &msg, NULL, 0, 0, PM_REMOVE )) - { + while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { // Handle the message - TranslateMessage( &msg ); - DispatchMessage( &msg ); + TranslateMessage(&msg); + DispatchMessage(&msg); } } while (WM_QUIT != msg.message); - - break; } - // - // Cleanup - // - if (gClient) - { - gClient->Shutdown(); // shuts down PhysX for us - gClient = nil; - } - hsAssert(hsgResMgr::ResMgr()->RefCnt()==1, "resMgr has too many refs, expect mem leaks"); - hsgResMgr::Shutdown(); // deletes fResMgr + gClient.ShutdownEnd(); DeInitNetClientComm(); // Uninstall our unhandled exception filter, if we installed one diff --git a/Sources/Plasma/CoreLib/hsThread_Win.cpp b/Sources/Plasma/CoreLib/hsThread_Win.cpp index 014aa9f9..3be66009 100644 --- a/Sources/Plasma/CoreLib/hsThread_Win.cpp +++ b/Sources/Plasma/CoreLib/hsThread_Win.cpp @@ -67,8 +67,8 @@ static unsigned int __stdcall gEntryPointBT(void* param) WinThreadParam* wtp = (WinThreadParam*)param; unsigned int result = wtp->fThread->Run(); - ::ReleaseSemaphore(wtp->fQuitSemaH, 1, nil); // signal that we've quit wtp->fThread->OnQuit(); + ::ReleaseSemaphore(wtp->fQuitSemaH, 1, nil); // signal that we've quit delete wtp; return result; } From e1befa63f98d1ae33038f21615dd164df90ff105 Mon Sep 17 00:00:00 2001 From: Adam Johnson Date: Fri, 31 Jul 2015 15:25:12 -0400 Subject: [PATCH 2/7] Application window messages should start at WM_APP --- Sources/Plasma/Apps/plClient/winmain.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Sources/Plasma/Apps/plClient/winmain.cpp b/Sources/Plasma/Apps/plClient/winmain.cpp index 00c03dcf..c2b7c422 100644 --- a/Sources/Plasma/Apps/plClient/winmain.cpp +++ b/Sources/Plasma/Apps/plClient/winmain.cpp @@ -78,7 +78,7 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com #define TIMER_UNITS_PER_SEC (float)1e3 #define UPDATE_STATUSMSG_SECONDS 30 -#define WM_USER_SETSTATUSMSG WM_USER+1 +#define WM_APP_SETSTATUSMSG WM_APP+1 // // Globals @@ -704,7 +704,7 @@ static size_t CurlCallback(void *buffer, size_t size, size_t nmemb, void *param) strncpy(status, (const char *)buffer, std::min(size * nmemb, 256)); status[255] = 0; - PostMessage(hwnd, WM_USER_SETSTATUSMSG, 0, (LPARAM) status); + PostMessage(hwnd, WM_APP_SETSTATUSMSG, 0, (LPARAM) status); return size * nmemb; } @@ -731,7 +731,7 @@ void StatusCallback(void *param) curl_easy_setopt(hCurl, CURLOPT_WRITEDATA, param); if (!statusUrl.IsEmpty() && curl_easy_perform(hCurl) != 0) // only perform request if there's actually a URL set - PostMessage(hwnd, WM_USER_SETSTATUSMSG, 0, (LPARAM) curlError); + PostMessage(hwnd, WM_APP_SETSTATUSMSG, 0, (LPARAM) curlError); for(unsigned i = 0; i < UPDATE_STATUSMSG_SECONDS && s_loginDlgRunning; ++i) { @@ -787,7 +787,7 @@ BOOL CALLBACK UruLoginDialogProc( HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM return FALSE; } - case WM_USER_SETSTATUSMSG: + case WM_APP_SETSTATUSMSG: SendMessage(GetDlgItem(hwndDlg, IDC_STATUS_TEXT), WM_SETTEXT, 0, lParam); return TRUE; From e48a98bcf414b21dc671203db05fb6c1c1592777 Mon Sep 17 00:00:00 2001 From: Adam Johnson Date: Fri, 31 Jul 2015 16:07:03 -0400 Subject: [PATCH 3/7] Ensure the net client doesn't do evil stuff before we're launched --- Sources/Plasma/Apps/plClient/plClient.cpp | 3 ++- Sources/Plasma/PubUtilLib/plNetClient/plNetClientMgr.cpp | 1 - 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Sources/Plasma/Apps/plClient/plClient.cpp b/Sources/Plasma/Apps/plClient/plClient.cpp index 49cc921b..f134e84a 100644 --- a/Sources/Plasma/Apps/plClient/plClient.cpp +++ b/Sources/Plasma/Apps/plClient/plClient.cpp @@ -1427,7 +1427,7 @@ bool plClient::StartInit() // // Init Net before loading things // - plNetClientMgr::GetInstance()->Init(); + plNetClientMgr::GetInstance()->RegisterAs(kNetClientMgr_KEY); plAgeLoader::GetInstance()->Init(); plCmdIfaceModMsg* pModMsg2 = new plCmdIfaceModMsg; @@ -1463,6 +1463,7 @@ bool plClient::StartInit() //============================================================================ bool plClient::BeginGame() { + plNetClientMgr::GetInstance()->Init(); IPlayIntroMovie("avi/CyanWorlds.webm", 0.f, 0.f, 0.f, 1.f, 1.f, 0.75); if (GetDone()) return false; IPatchGlobalAgeFiles(); diff --git a/Sources/Plasma/PubUtilLib/plNetClient/plNetClientMgr.cpp b/Sources/Plasma/PubUtilLib/plNetClient/plNetClientMgr.cpp index 63509817..16e22721 100644 --- a/Sources/Plasma/PubUtilLib/plNetClient/plNetClientMgr.cpp +++ b/Sources/Plasma/PubUtilLib/plNetClient/plNetClientMgr.cpp @@ -341,7 +341,6 @@ int plNetClientMgr::Init() VaultInitialize(); - RegisterAs( kNetClientMgr_KEY ); IAddCloneRoom(); fNetGroups.Reset(); From f075496888669c8c3d8e45248a72e5f403960b72 Mon Sep 17 00:00:00 2001 From: Adam Johnson Date: Fri, 31 Jul 2015 22:30:01 -0400 Subject: [PATCH 4/7] Fix crashes related to dispatching messages from netcode The dispatcher may or may not be ready when these things happen. If it isn't... KABOOOOOOOOM --- .../plNetClient/plNetClientCommInterface.cpp | 1 + .../plNetClientComm/plNetClientComm.cpp | 22 +++++++++---------- .../plNetClientComm/plNetClientComm.h | 1 + 3 files changed, 13 insertions(+), 11 deletions(-) diff --git a/Sources/Plasma/PubUtilLib/plNetClient/plNetClientCommInterface.cpp b/Sources/Plasma/PubUtilLib/plNetClient/plNetClientCommInterface.cpp index 45aa2327..cd7396b7 100644 --- a/Sources/Plasma/PubUtilLib/plNetClient/plNetClientCommInterface.cpp +++ b/Sources/Plasma/PubUtilLib/plNetClient/plNetClientCommInterface.cpp @@ -65,6 +65,7 @@ int plNetClientCommMsgHandler::HandleMessage( plNetMessage* msg ) int plNetClientMgr::IInitNetClientComm() { NetCommActivatePostInitErrorHandler(); + NetCommActivateMsgDispatchers(); ASSERT(!GetFlagsBit(kNetClientCommInited)); fNetClientComm.SetDefaultHandler(&fNetClientCommMsgHandler); diff --git a/Sources/Plasma/PubUtilLib/plNetClientComm/plNetClientComm.cpp b/Sources/Plasma/PubUtilLib/plNetClientComm/plNetClientComm.cpp index 0ea74390..043086bc 100644 --- a/Sources/Plasma/PubUtilLib/plNetClientComm/plNetClientComm.cpp +++ b/Sources/Plasma/PubUtilLib/plNetClientComm/plNetClientComm.cpp @@ -741,10 +741,6 @@ void NetCommStartup () { NetClientInitialize(); NetClientSetErrorHandler(IPreInitNetErrorCallback); - NetCliGameSetRecvBufferHandler(INetBufferCallback); -// NetCliAuthSetRecvBufferHandler(INetBufferCallback); - NetCliAuthSetNotifyNewBuildHandler(INotifyNewBuildCallback); - NetCliAuthSetConnectCallback(INotifyAuthConnectedCallback); // Set startup age info memset(&s_startupAge, 0, sizeof(s_startupAge)); @@ -780,15 +776,10 @@ void NetCommEnableNet ( bool enabled, bool wait ) { - if (enabled) { + if (enabled) NetClientInitialize(); - NetClientSetErrorHandler(INetErrorCallback); - NetCliGameSetRecvBufferHandler(INetBufferCallback); -// NetCliAuthSetRecvBufferHandler(INetBufferCallback); - } - else { + else NetClientDestroy(wait); - } } //============================================================================ @@ -796,6 +787,15 @@ void NetCommActivatePostInitErrorHandler () { NetClientSetErrorHandler(INetErrorCallback); } +//============================================================================ +void NetCommActivateMsgDispatchers() { + NetClientSetErrorHandler(INetErrorCallback); + NetCliGameSetRecvBufferHandler(INetBufferCallback); +// NetCliAuthSetRecvBufferHandler(INetBufferCallback); + NetCliAuthSetNotifyNewBuildHandler(INotifyNewBuildCallback); + NetCliAuthSetConnectCallback(INotifyAuthConnectedCallback); +} + //============================================================================ void NetCommUpdate () { // plClient likes to recursively call us on occasion; debounce that crap. diff --git a/Sources/Plasma/PubUtilLib/plNetClientComm/plNetClientComm.h b/Sources/Plasma/PubUtilLib/plNetClientComm/plNetClientComm.h index 45aeb75d..2116ec87 100644 --- a/Sources/Plasma/PubUtilLib/plNetClientComm/plNetClientComm.h +++ b/Sources/Plasma/PubUtilLib/plNetClientComm/plNetClientComm.h @@ -136,6 +136,7 @@ void NetCommEnableNet ( bool wait ); void NetCommActivatePostInitErrorHandler(); +void NetCommActivateMsgDispatchers(); /***************************************************************************** From c97afc18a014dccf0c208c21a6dea825f34ceecd Mon Sep 17 00:00:00 2001 From: Adam Johnson Date: Sat, 1 Aug 2015 00:31:41 -0400 Subject: [PATCH 5/7] Fix crashes when changing graphics state --- Sources/Plasma/Apps/plClient/winmain.cpp | 2 ++ .../PubUtilLib/plPipeline/DX/plDXPipeline.cpp | 30 +++++++++---------- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/Sources/Plasma/Apps/plClient/winmain.cpp b/Sources/Plasma/Apps/plClient/winmain.cpp index c2b7c422..57e9877c 100644 --- a/Sources/Plasma/Apps/plClient/winmain.cpp +++ b/Sources/Plasma/Apps/plClient/winmain.cpp @@ -1207,6 +1207,8 @@ int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpCmdLine, int nC // Main loop if (gClient && !gClient->GetDone()) { + if (gPendingActivate) + gClient->WindowActivate(gPendingActivateFlag); gClient->SetMessagePumpProc(PumpMessageQueueProc); gClient.Start(); diff --git a/Sources/Plasma/PubUtilLib/plPipeline/DX/plDXPipeline.cpp b/Sources/Plasma/PubUtilLib/plPipeline/DX/plDXPipeline.cpp index 301ceb4f..779e19b5 100644 --- a/Sources/Plasma/PubUtilLib/plPipeline/DX/plDXPipeline.cpp +++ b/Sources/Plasma/PubUtilLib/plPipeline/DX/plDXPipeline.cpp @@ -2239,25 +2239,23 @@ bool plDXPipeline::IResetDevice() IFindDepthFormat(fSettings.fPresentParams); } HRESULT hr = fD3DDevice->Reset(&fSettings.fPresentParams); - int count = 0; - while( FAILED(hr) ) - { - if(count++ == 25) - { - IPrintDeviceInitError(); - IResetToDefaults(&fSettings.fPresentParams); + // The device is inited the first time on the client loader thread, but this is the main thread + // we expect to get one failure... So let's try recreating the device on the main thread. + if (FAILED(hr)) { + IReleaseDeviceObjects(); + for (int i = 0; true; ++i) { + if (!ICreateDeviceObjects()) + break; + ::Sleep(250); + // Old magic number from reset land + if (i == 25) { + IPrintDeviceInitError(); + IResetToDefaults(&fSettings.fPresentParams); + } } - // Still not ready? This is bad. - // Until we called Reset(), we could make any D3D call we wanted, - // and it would turn into a no-op. But once we call Reset(), until - // the device really is reset, anything but TestCoop/Reset/Release - // has just become illegal. We've already released everything, Reset - // just failed, not much to do but wait and try again. - ::Sleep(250); - hr = fD3DDevice->Reset(&fSettings.fPresentParams); } fSettings.fCurrFVFFormat = 0; - fSettings.fCurrVertexShader = NULL; + fSettings.fCurrVertexShader = nullptr; fManagedAlloced = false; ICreateDynDeviceObjects(); IInitDeviceState(); From d99922c2bb9d9c9eb0669d92a9c5a394dcfa95b0 Mon Sep 17 00:00:00 2001 From: Adam Johnson Date: Sat, 1 Aug 2015 13:12:30 -0400 Subject: [PATCH 6/7] Fix license block formatting --- Sources/Plasma/Apps/plClient/plClientLoader.cpp | 8 ++++---- Sources/Plasma/Apps/plClient/plClientLoader.h | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Sources/Plasma/Apps/plClient/plClientLoader.cpp b/Sources/Plasma/Apps/plClient/plClientLoader.cpp index 3be92717..43937471 100644 --- a/Sources/Plasma/Apps/plClient/plClientLoader.cpp +++ b/Sources/Plasma/Apps/plClient/plClientLoader.cpp @@ -33,10 +33,10 @@ the parts of OpenSSL and IJG JPEG Library used as well as that of the covered work. You can contact Cyan Worlds, Inc. by email legal@cyan.com -or by snail mail at: -Cyan Worlds, Inc. -14617 N Newport Hwy -Mead, WA 99021 + or by snail mail at: + Cyan Worlds, Inc. + 14617 N Newport Hwy + Mead, WA 99021 *==LICENSE==*/ diff --git a/Sources/Plasma/Apps/plClient/plClientLoader.h b/Sources/Plasma/Apps/plClient/plClientLoader.h index e0a5bf73..159f8456 100644 --- a/Sources/Plasma/Apps/plClient/plClientLoader.h +++ b/Sources/Plasma/Apps/plClient/plClientLoader.h @@ -33,10 +33,10 @@ the parts of OpenSSL and IJG JPEG Library used as well as that of the covered work. You can contact Cyan Worlds, Inc. by email legal@cyan.com -or by snail mail at: -Cyan Worlds, Inc. -14617 N Newport Hwy -Mead, WA 99021 + or by snail mail at: + Cyan Worlds, Inc. + 14617 N Newport Hwy + Mead, WA 99021 *==LICENSE==*/ From ee0cf4e0a9bc7cc114d67e3746a4444d85e730e0 Mon Sep 17 00:00:00 2001 From: Adam Johnson Date: Sat, 1 Aug 2015 14:15:55 -0400 Subject: [PATCH 7/7] Fix custom startup ages So, that net comm auth message was actually useful... Trololololo. Whatever. --- Sources/Plasma/Apps/plClient/plClient.cpp | 21 ++++++++++++++++++--- Sources/Plasma/Apps/plClient/plClient.h | 2 ++ 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/Sources/Plasma/Apps/plClient/plClient.cpp b/Sources/Plasma/Apps/plClient/plClient.cpp index f134e84a..9ff117ed 100644 --- a/Sources/Plasma/Apps/plClient/plClient.cpp +++ b/Sources/Plasma/Apps/plClient/plClient.cpp @@ -807,6 +807,17 @@ bool plClient::MsgReceive(plMessage* msg) return true; } + //============================================================================ + // plNetCommAuthMsg + //============================================================================ + if (plNetCommAuthMsg* authMsg = plNetCommAuthMsg::ConvertNoRef(msg)) { + plgDispatch::Dispatch()->UnRegisterForExactType(plNetCommAuthMsg::Index(), GetKey()); + if (IS_NET_SUCCESS(authMsg->result)) { + SetFlag(kFlagInitialAuthComplete); + IPatchGlobalAgeFiles(); + } + } + return hsKeyedObject::MsgReceive(msg); } @@ -1427,6 +1438,7 @@ bool plClient::StartInit() // // Init Net before loading things // + plgDispatch::Dispatch()->RegisterForExactType(plNetCommAuthMsg::Index(), GetKey()); plNetClientMgr::GetInstance()->RegisterAs(kNetClientMgr_KEY); plAgeLoader::GetInstance()->Init(); @@ -1465,6 +1477,7 @@ bool plClient::BeginGame() { plNetClientMgr::GetInstance()->Init(); IPlayIntroMovie("avi/CyanWorlds.webm", 0.f, 0.f, 0.f, 1.f, 1.f, 0.75); + SetFlag(kFlagIntroComplete); if (GetDone()) return false; IPatchGlobalAgeFiles(); return true; @@ -1473,10 +1486,12 @@ bool plClient::BeginGame() //============================================================================ void plClient::IPatchGlobalAgeFiles( void ) { - plgDispatch::Dispatch()->RegisterForExactType(plResPatcherMsg::Index(), GetKey()); + if (HasFlag(kFlagIntroComplete) && HasFlag(kFlagInitialAuthComplete)) { + plgDispatch::Dispatch()->RegisterForExactType(plResPatcherMsg::Index(), GetKey()); - plResPatcher* patcher = plResPatcher::GetInstance(); - patcher->Update(plManifest::EssentialGameManifests()); + plResPatcher* patcher = plResPatcher::GetInstance(); + patcher->Update(plManifest::EssentialGameManifests()); + } } void plClient::InitDLLs() diff --git a/Sources/Plasma/Apps/plClient/plClient.h b/Sources/Plasma/Apps/plClient/plClient.h index 485d5045..197cbbdf 100644 --- a/Sources/Plasma/Apps/plClient/plClient.h +++ b/Sources/Plasma/Apps/plClient/plClient.h @@ -248,6 +248,8 @@ public: kFlagDBGDisableRRequests, kFlagAsyncInitComplete, kFlagGlobalDataLoaded, + kFlagInitialAuthComplete, + kFlagIntroComplete, }; bool HasFlag(int f) const { return fFlags.IsBitSet(f); }