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;
}