diff --git a/Sources/Plasma/Apps/plClient/CMakeLists.txt b/Sources/Plasma/Apps/plClient/CMakeLists.txt
index a23b1c99..9c0f7e65 100644
--- a/Sources/Plasma/Apps/plClient/CMakeLists.txt
+++ b/Sources/Plasma/Apps/plClient/CMakeLists.txt
@@ -39,15 +39,17 @@ endif(PYTHONINTERP_FOUND)
set(plClient_HEADERS
plClient.h
plClientCreatable.h
- plClientLoader.h
+ #plClientKey.h
plClientUpdateFormat.h
+ #plPluginClient.h
)
set(plClient_SOURCES
pfAllCreatables.cpp
plAllCreatables.cpp
plClient.cpp
- plClientLoader.cpp
+ #plClientKey.cpp
+ #plPluginClient.cpp
pnAllCreatables.cpp
winmain.cpp
)
diff --git a/Sources/Plasma/Apps/plClient/plClient.cpp b/Sources/Plasma/Apps/plClient/plClient.cpp
index 069a0ff9..c07695f5 100644
--- a/Sources/Plasma/Apps/plClient/plClient.cpp
+++ b/Sources/Plasma/Apps/plClient/plClient.cpp
@@ -800,20 +800,18 @@ bool plClient::MsgReceive(plMessage* msg)
}
//============================================================================
- // plResPatcherMsg
+ // plNetCommAuthMsg
//============================================================================
- if (plResPatcherMsg * resMsg = plResPatcherMsg::ConvertNoRef(msg)) {
- IHandlePatcherMsg(resMsg);
+ if (plNetCommAuthMsg * authCommMsg = plNetCommAuthMsg::ConvertNoRef(msg)) {
+ IHandleNetCommAuthMsg(authCommMsg);
return true;
}
//============================================================================
- // plNetCommAuthMsg
+ // plResPatcherMsg
//============================================================================
- if (plNetCommAuthMsg* authMsg = plNetCommAuthMsg::ConvertNoRef(msg)) {
- plgDispatch::Dispatch()->UnRegisterForExactType(plNetCommAuthMsg::Index(), GetKey());
- if (IS_NET_SUCCESS(authMsg->result))
- IPatchGlobalAgeFiles();
+ if (plResPatcherMsg * resMsg = plResPatcherMsg::ConvertNoRef(msg)) {
+ IHandlePatcherMsg(resMsg);
return true;
}
@@ -1381,6 +1379,10 @@ 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();
@@ -1438,7 +1440,7 @@ bool plClient::StartInit()
// Init Net before loading things
//
plgDispatch::Dispatch()->RegisterForExactType(plNetCommAuthMsg::Index(), GetKey());
- plNetClientMgr::GetInstance()->RegisterAs(kNetClientMgr_KEY);
+ plNetClientMgr::GetInstance()->Init();
plAgeLoader::GetInstance()->Init();
plCmdIfaceModMsg* pModMsg2 = new plCmdIfaceModMsg;
@@ -1458,6 +1460,8 @@ 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:
@@ -1468,22 +1472,22 @@ bool plClient::StartInit()
plgDispatch::Dispatch()->RegisterForExactType(plAudioSysMsg::Index(), pLMod->GetKey());
plSynchedObject::PushSynchDisabled(false); // enable dirty tracking
- return true;
-}
-//============================================================================
-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;
- if (NetCommGetStartupAge()->ageDatasetName.CompareI("StartUp") == 0) {
- // This is needed because there is no auth step in this case
- plNetCommAuthMsg* msg = new plNetCommAuthMsg();
- msg->result = kNetSuccess;
- msg->param = nullptr;
+ 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().
+
return true;
}
@@ -2286,3 +2290,27 @@ 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 485d5045..c81fa37b 100644
--- a/Sources/Plasma/Apps/plClient/plClient.h
+++ b/Sources/Plasma/Apps/plClient/plClient.h
@@ -177,6 +177,7 @@ protected:
void ICompleteInit ();
void IOnAsyncInitComplete ();
void IHandlePatcherMsg (plResPatcherMsg * msg);
+ void IHandleNetCommAuthMsg (plNetCommAuthMsg * msg);
bool IHandleAgeLoaded2Msg (plAgeLoaded2Msg * msg);
bool IFlushRenderRequests();
@@ -285,8 +286,6 @@ 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
deleted file mode 100644
index 43937471..00000000
--- a/Sources/Plasma/Apps/plClient/plClientLoader.cpp
+++ /dev/null
@@ -1,145 +0,0 @@
-/*==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
deleted file mode 100644
index 159f8456..00000000
--- a/Sources/Plasma/Apps/plClient/plClientLoader.h
+++ /dev/null
@@ -1,110 +0,0 @@
-/*==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 57e9877c..af179d9a 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 "plClientLoader.h"
+#include "plClientResMgr/plClientResMgr.h"
#include "pfCrashHandler/plCrashCli.h"
#include "plNetClient/plNetClientMgr.h"
#include "plInputCore/plInputDevice.h"
@@ -66,6 +66,7 @@ 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"
@@ -78,7 +79,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_APP_SETSTATUSMSG WM_APP+1
+#define WM_USER_SETSTATUSMSG WM_USER+1
//
// Globals
@@ -113,7 +114,7 @@ int gWinBorderDX = GetSystemMetrics( SM_CXSIZEFRAME );
int gWinBorderDY = GetSystemMetrics( SM_CYSIZEFRAME );
int gWinMenuDY = GetSystemMetrics( SM_CYCAPTION );
-plClientLoader gClient;
+plClient *gClient;
bool gPendingActivate = false;
bool gPendingActivateFlag = false;
@@ -142,6 +143,11 @@ static wchar_t s_patcherExeName[] = L"UruLauncher.exe";
#endif // PLASMA_EXTERNAL_RELEASE
+//============================================================================
+// PhysX installer
+//============================================================================
+static wchar_t s_physXSetupExeName[] = L"PhysX_Setup.exe";
+
//============================================================================
// LoginDialogParam
//============================================================================
@@ -349,11 +355,15 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
break;
case WM_CLOSE:
- gClient.ShutdownStart();
+ gClient->SetDone(TRUE);
+ if (plNetClientMgr * mgr = plNetClientMgr::GetInstance())
+ mgr->QueueDisableNet(false, nil);
DestroyWindow(gClient->GetWindowHandle());
break;
case WM_DESTROY:
- gClient.ShutdownStart();
+ gClient->SetDone(TRUE);
+ if (plNetClientMgr * mgr = plNetClientMgr::GetInstance())
+ mgr->QueueDisableNet(false, nil);
PostQuitMessage(0);
break;
}
@@ -446,6 +456,156 @@ 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
//
@@ -704,7 +864,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_APP_SETSTATUSMSG, 0, (LPARAM) status);
+ PostMessage(hwnd, WM_USER_SETSTATUSMSG, 0, (LPARAM) status);
return size * nmemb;
}
@@ -731,7 +891,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_APP_SETSTATUSMSG, 0, (LPARAM) curlError);
+ PostMessage(hwnd, WM_USER_SETSTATUSMSG, 0, (LPARAM) curlError);
for(unsigned i = 0; i < UPDATE_STATUSMSG_SECONDS && s_loginDlgRunning; ++i)
{
@@ -787,7 +947,7 @@ BOOL CALLBACK UruLoginDialogProc( HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM
return FALSE;
}
- case WM_APP_SETSTATUSMSG:
+ case WM_USER_SETSTATUSMSG:
SendMessage(GetDlgItem(hwndDlg, IDC_STATUS_TEXT), WM_SETTEXT, 0, lParam);
return TRUE;
@@ -905,34 +1065,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;
@@ -958,7 +1118,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 ? gClient->GetWindowHandle() : GetActiveWindow();
+ HWND parentHwnd = (gClient == nil) ? GetActiveWindow() : gClient->GetWindowHandle();
DialogBoxParam(gHInst, MAKEINTRESOURCE(IDD_EXCEPTION), parentHwnd, ExceptionDialogProc, NULL);
// Trickle up the handlers
@@ -969,40 +1129,6 @@ 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)
{
@@ -1115,10 +1241,6 @@ 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)
{
@@ -1132,12 +1254,6 @@ 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();
@@ -1183,51 +1299,96 @@ 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
- // 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);
- }
+ //
+ // 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());
- // Main loop
- if (gClient && !gClient->GetDone()) {
- if (gPendingActivate)
- gClient->WindowActivate(gPendingActivateFlag);
- gClient->SetMessagePumpProc(PumpMessageQueueProc);
- gClient.Start();
+ 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());
+
+ //
+ // Init Application here
+ //
+ if( !gClient->StartInit() )
+ break;
+
+ // I want it on top! I mean it!
+ BringWindowToTop( gClient->GetWindowHandle() );
+ // 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;
}
- gClient.ShutdownEnd();
+ //
+ // 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
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 3be66009..014aa9f9 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();
- wtp->fThread->OnQuit();
::ReleaseSemaphore(wtp->fQuitSemaH, 1, nil); // signal that we've quit
+ wtp->fThread->OnQuit();
delete wtp;
return result;
}
diff --git a/Sources/Plasma/PubUtilLib/plNetClient/plNetClientCommInterface.cpp b/Sources/Plasma/PubUtilLib/plNetClient/plNetClientCommInterface.cpp
index cd7396b7..45aa2327 100644
--- a/Sources/Plasma/PubUtilLib/plNetClient/plNetClientCommInterface.cpp
+++ b/Sources/Plasma/PubUtilLib/plNetClient/plNetClientCommInterface.cpp
@@ -65,7 +65,6 @@ int plNetClientCommMsgHandler::HandleMessage( plNetMessage* msg )
int plNetClientMgr::IInitNetClientComm()
{
NetCommActivatePostInitErrorHandler();
- NetCommActivateMsgDispatchers();
ASSERT(!GetFlagsBit(kNetClientCommInited));
fNetClientComm.SetDefaultHandler(&fNetClientCommMsgHandler);
diff --git a/Sources/Plasma/PubUtilLib/plNetClient/plNetClientMgr.cpp b/Sources/Plasma/PubUtilLib/plNetClient/plNetClientMgr.cpp
index 16e22721..63509817 100644
--- a/Sources/Plasma/PubUtilLib/plNetClient/plNetClientMgr.cpp
+++ b/Sources/Plasma/PubUtilLib/plNetClient/plNetClientMgr.cpp
@@ -341,6 +341,7 @@ int plNetClientMgr::Init()
VaultInitialize();
+ RegisterAs( kNetClientMgr_KEY );
IAddCloneRoom();
fNetGroups.Reset();
diff --git a/Sources/Plasma/PubUtilLib/plNetClientComm/plNetClientComm.cpp b/Sources/Plasma/PubUtilLib/plNetClientComm/plNetClientComm.cpp
index 043086bc..0ea74390 100644
--- a/Sources/Plasma/PubUtilLib/plNetClientComm/plNetClientComm.cpp
+++ b/Sources/Plasma/PubUtilLib/plNetClientComm/plNetClientComm.cpp
@@ -741,6 +741,10 @@ void NetCommStartup () {
NetClientInitialize();
NetClientSetErrorHandler(IPreInitNetErrorCallback);
+ NetCliGameSetRecvBufferHandler(INetBufferCallback);
+// NetCliAuthSetRecvBufferHandler(INetBufferCallback);
+ NetCliAuthSetNotifyNewBuildHandler(INotifyNewBuildCallback);
+ NetCliAuthSetConnectCallback(INotifyAuthConnectedCallback);
// Set startup age info
memset(&s_startupAge, 0, sizeof(s_startupAge));
@@ -776,10 +780,15 @@ void NetCommEnableNet (
bool enabled,
bool wait
) {
- if (enabled)
+ if (enabled) {
NetClientInitialize();
- else
+ NetClientSetErrorHandler(INetErrorCallback);
+ NetCliGameSetRecvBufferHandler(INetBufferCallback);
+// NetCliAuthSetRecvBufferHandler(INetBufferCallback);
+ }
+ else {
NetClientDestroy(wait);
+ }
}
//============================================================================
@@ -787,15 +796,6 @@ 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 2116ec87..45aeb75d 100644
--- a/Sources/Plasma/PubUtilLib/plNetClientComm/plNetClientComm.h
+++ b/Sources/Plasma/PubUtilLib/plNetClientComm/plNetClientComm.h
@@ -136,7 +136,6 @@ void NetCommEnableNet (
bool wait
);
void NetCommActivatePostInitErrorHandler();
-void NetCommActivateMsgDispatchers();
/*****************************************************************************
diff --git a/Sources/Plasma/PubUtilLib/plPipeline/DX/plDXPipeline.cpp b/Sources/Plasma/PubUtilLib/plPipeline/DX/plDXPipeline.cpp
index 779e19b5..301ceb4f 100644
--- a/Sources/Plasma/PubUtilLib/plPipeline/DX/plDXPipeline.cpp
+++ b/Sources/Plasma/PubUtilLib/plPipeline/DX/plDXPipeline.cpp
@@ -2239,23 +2239,25 @@ bool plDXPipeline::IResetDevice()
IFindDepthFormat(fSettings.fPresentParams);
}
HRESULT hr = fD3DDevice->Reset(&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);
- }
+ int count = 0;
+ while( FAILED(hr) )
+ {
+ if(count++ == 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 = nullptr;
+ fSettings.fCurrVertexShader = NULL;
fManagedAlloced = false;
ICreateDynDeviceObjects();
IInitDeviceState();