Browse Source

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"
Adam Johnson 10 years ago
parent
commit
4d5c10f775
  1. 6
      Sources/Plasma/Apps/plClient/CMakeLists.txt
  2. 62
      Sources/Plasma/Apps/plClient/plClient.cpp
  3. 3
      Sources/Plasma/Apps/plClient/plClient.h
  4. 145
      Sources/Plasma/Apps/plClient/plClientLoader.cpp
  5. 110
      Sources/Plasma/Apps/plClient/plClientLoader.h
  6. 315
      Sources/Plasma/Apps/plClient/winmain.cpp
  7. 2
      Sources/Plasma/CoreLib/hsThread_Win.cpp

6
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
)

62
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();
}

3
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);

145
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 <http://www.gnu.org/licenses/>.
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 <shellapi.h>
#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();
}

110
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 <http://www.gnu.org/licenses/>.
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; }
};

315
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,31 +905,31 @@ 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...");
::SetDlgItemText(hwndDlg, IDC_STARTING_TEXT, "Démarrage d'URU. Veuillez patienter...");
break;
case plLocalization::kGerman:
::SetDlgItemText( hwndDlg, IDC_STARTING_TEXT, "Starte URU, bitte warten ...");
::SetDlgItemText(hwndDlg, IDC_STARTING_TEXT, "Starte URU, bitte warten ...");
break;
case plLocalization::kSpanish:
::SetDlgItemText( hwndDlg, IDC_STARTING_TEXT, "Iniciando URU, por favor espera...");
::SetDlgItemText(hwndDlg, IDC_STARTING_TEXT, "Iniciando URU, por favor espera...");
break;
case plLocalization::kItalian:
::SetDlgItemText( hwndDlg, IDC_STARTING_TEXT, "Avvio di URU, attendere...");
::SetDlgItemText(hwndDlg, IDC_STARTING_TEXT, "Avvio di URU, attendere...");
break;
// default is English
case plLocalization::kJapanese:
::SetDlgItemText( hwndDlg, IDC_STARTING_TEXT, "...");
::SetDlgItemText(hwndDlg, IDC_STARTING_TEXT, "...");
break;
default:
::SetDlgItemText( hwndDlg, IDC_STARTING_TEXT, "Starting URU. Please wait...");
::SetDlgItemText(hwndDlg, IDC_STARTING_TEXT, "Starting URU. Please wait...");
break;
}
return true;
@ -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());
//
// 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() );
// 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);
}
//
// Main loop
//
if (gClient && !gClient->GetDone()) {
gClient->SetMessagePumpProc(PumpMessageQueueProc);
gClient.Start();
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

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

Loading…
Cancel
Save