//============================================================================ static void FileSrvIpAddressCallback ( ENetError result, void * param, const wchar_t addr[] ) { NetCliGateKeeperDisconnect(); if (IS_NET_ERROR(result)) { plString msg = plString::Format("FileSrvIpAddressRequest failed: %S", NetErrorToString(result)); plStatusLog::AddLineS("patcher.log", msg.c_str()); s_patchResult = result; s_downloadComplete = true; } // Start connecting to the server const char* caddr = hsWStringToString(addr); NetCliFileStartConnect(&caddr, 1, true); delete[] caddr; PathGetProgramDirectory(s_newPatcherFile, arrsize(s_newPatcherFile)); GetTempFileNameW(s_newPatcherFile, kPatcherExeFilename, 0, s_newPatcherFile); plFileUtils::RemoveFile(s_newPatcherFile); NetCliFileManifestRequest(ManifestCallback, nil, s_manifest); }
//============================================================================ static void DownloadCallback ( ENetError result, void * param, const wchar_t filename[], hsStream * writer ) { if(IS_NET_ERROR(result)) { switch (result) { case kNetErrTimeout: writer->Rewind(); NetCliFileDownloadRequest(filename, writer, DownloadCallback, param); break; default: plString msg = plString::Format("Error getting patcher file: %S", NetErrorToString(result)); plStatusLog::AddLineS("patcher.log", msg.c_str()); if (IS_NET_SUCCESS(s_patchResult)) s_patchResult = result; break; } return; } writer->Close(); delete writer; AtomicAdd(&s_numFiles, -1); if(!s_numFiles) { s_downloadComplete = true; s_updated = true; } }
//============================================================================ static void CancelTrans_CS (NetTrans * trans, ENetError error) { ASSERT(IS_NET_ERROR(error)); if (trans->m_state != kTransStateComplete) { trans->m_result = error; trans->m_state = kTransStateComplete; } }
//============================================================================ static void ManifestCallback ( ENetError result, void * param, const wchar_t group[], const NetCliFileManifestEntry manifest[], unsigned entryCount ) { if(IS_NET_ERROR(result)) { switch (result) { case kNetErrTimeout: NetCliFileManifestRequest(ManifestCallback, nil, s_manifest); break; default: plString msg = plString::Format("Error getting patcher manifest: %S", NetErrorToString(result)); plStatusLog::AddLineS("patcher.log", msg.c_str()); if (IS_NET_SUCCESS(s_patchResult)) s_patchResult = result; break; } return; } #ifndef PLASMA_EXTERNAL_RELEASE if (entryCount == 0) { // dataserver does not contain a patcher s_downloadComplete = true; return; } #endif char ansi[MAX_PATH]; // MD5 check current patcher against value in manifest ASSERT(entryCount == 1); wchar_t curPatcherFile[MAX_PATH]; PathGetProgramName(curPatcherFile, arrsize(curPatcherFile)); StrToAnsi(ansi, curPatcherFile, arrsize(ansi)); if (!MD5Check(ansi, manifest[0].md5)) { // MessageBox(GetTopWindow(nil), "MD5 failed", "Msg", MB_OK); SelfPatcherStream::totalBytes += manifest[0].zipSize; AtomicAdd(&s_numFiles, 1); SetText("Downloading new patcher..."); StrToAnsi(ansi, s_newPatcherFile, arrsize(ansi)); SelfPatcherStream * stream = new SelfPatcherStream; if (!stream->Open(ansi, "wb")) ErrorAssert(__LINE__, __FILE__, "Failed to create file: %s, errno: %u", ansi, errno); NetCliFileDownloadRequest(manifest[0].downloadName, stream, DownloadCallback, nil); } else { s_downloadComplete = true; } }
//============================================================================ void AgeVaultDownloadCallback ( ENetError result, void * param ) { plNCAgeJoiner * joiner = (plNCAgeJoiner *)param; if (IS_NET_ERROR(result)) { joiner->Complete(false, "Failed to download age vault"); } else { // vault downloaded. start loading age data LogMsg(kLogPerf, L"AgeJoiner: Next:kLoadAge (vault downloaded)"); joiner->nextOp = plNCAgeJoiner::kLoadAge; } }
//============================================================================ bool DownloadRequestTrans::Recv ( const uint8_t msg[], unsigned bytes ) { m_timeoutAtMs = hsTimer::GetMilliSeconds<uint32_t>() + NetTransGetTimeoutMs(); // Reset the timeout counter const File2Cli_FileDownloadReply & reply = *(const File2Cli_FileDownloadReply *) msg; uint32_t byteCount = reply.byteCount; const uint8_t* data = reply.fileData; // tell the server we got the data Cli2File_FileDownloadChunkAck fileAck; fileAck.messageId = kCli2File_FileDownloadChunkAck; fileAck.transId = reply.transId; fileAck.messageBytes = sizeof(fileAck); fileAck.readerId = reply.readerId; m_conn->Send(&fileAck, fileAck.messageBytes); if (IS_NET_ERROR(reply.result)) { // we have a problem... indicate we are done and abort m_result = reply.result; m_state = kTransStateComplete; return true; } // we have data to write, so queue it for write in the main thread (we're // currently in a net recv thread) if (byteCount > 0) { RcvdFileDownloadChunkTrans * writeTrans = new RcvdFileDownloadChunkTrans; writeTrans->writer = m_writer; writeTrans->bytes = byteCount; writeTrans->data = (uint8_t *)malloc(byteCount); memcpy(writeTrans->data, data, byteCount); NetTransSend(writeTrans); } m_totalBytesReceived += byteCount; if (m_totalBytesReceived >= reply.totalFileSize) { // all bytes received, mark as complete m_result = reply.result; m_state = kTransStateComplete; } return true; }
//============================================================================ bool BuildIdRequestTrans::Recv ( const uint8_t msg[], unsigned bytes ) { const File2Cli_BuildIdReply & reply = *(const File2Cli_BuildIdReply *) msg; if (IS_NET_ERROR(reply.result)) { // we have a problem... m_result = reply.result; m_state = kTransStateComplete; return true; } m_buildId = reply.buildId; // mark as complete m_result = reply.result; m_state = kTransStateComplete; return true; }
// // MsgReceive handler for plasma messages // bool plNetClientMgr::MsgReceive( plMessage* msg ) { if (plNetLinkingMgr::GetInstance()->MsgReceive( msg )) return true; plEvalMsg* evalMsg = plEvalMsg::ConvertNoRef(msg); if (evalMsg) { IPlaybackMsgs(); if ( GetFlagsBit( kNeedToSendAgeLoadedMsg ) ) { SetFlagsBit( kNeedToSendAgeLoadedMsg, false ); plAgeLoader::GetInstance()->NotifyAgeLoaded( true ); } if ( GetFlagsBit( kNeedToSendInitialAgeStateLoadedMsg ) ) { SetFlagsBit(kNeedToSendInitialAgeStateLoadedMsg, false); plInitialAgeStateLoadedMsg* m = new plInitialAgeStateLoadedMsg; m->Send(); } return true; } plGenRefMsg* ref = plGenRefMsg::ConvertNoRef(msg); if (ref) { if( ref->fType == kVaultImage ) { // Ignore, we just use it for reffing, don't care about the actual pointer return true; } hsAssert(ref->fType==kAgeSDLHook, "unknown ref msg context"); if (ref->GetContext()==plRefMsg::kOnCreate) { hsAssert(fAgeSDLObjectKey==nil, "already have a ref to age sdl hook"); fAgeSDLObjectKey = ref->GetRef()->GetKey(); DebugMsg("Age SDL hook object created, uoid=%s", fAgeSDLObjectKey->GetUoid().StringIze().c_str()); } else { fAgeSDLObjectKey=nil; DebugMsg("Age SDL hook object destroyed"); } return true; } if (plNetClientMgrMsg * ncmMsg = plNetClientMgrMsg::ConvertNoRef(msg)) { if (ncmMsg->type == plNetClientMgrMsg::kCmdDisableNet) { SetFlagsBit(kDisableOnNextUpdate); hsRefCnt_SafeUnRef(fDisableMsg); fDisableMsg = ncmMsg; fDisableMsg->Ref(); } return true; } if (plNetCommAuthMsg * authMsg = plNetCommAuthMsg::ConvertNoRef(msg)) { if (IS_NET_ERROR(authMsg->result)) { char str[256]; StrPrintf(str, arrsize(str), "Authentication failed: %S", NetErrorToString(authMsg->result)); QueueDisableNet(true, str); return false; // @@@ TODO: Handle this failure better } return true; } if (plNetCommActivePlayerMsg * activePlrMsg = plNetCommActivePlayerMsg::ConvertNoRef(msg)) { if (IS_NET_ERROR(activePlrMsg->result)) { char str[256]; StrPrintf(str, arrsize(str), "SetActivePlayer failed: %S", NetErrorToString(activePlrMsg->result)); QueueDisableNet(true, str); return false; // @@@ TODO: Handle this failure better. } return true; } plPlayerPageMsg *playerPageMsg = plPlayerPageMsg::ConvertNoRef(msg); if(playerPageMsg) { IHandlePlayerPageMsg(playerPageMsg); return true; // handled } plLoadCloneMsg* pCloneMsg = plLoadCloneMsg::ConvertNoRef(msg); if(pCloneMsg) { ILoadClone(pCloneMsg); return true; // handled } // player is petitioning a CCR plCCRPetitionMsg* petMsg=plCCRPetitionMsg::ConvertNoRef(msg); if (petMsg) { ISendCCRPetition(petMsg); return true; } // a remote CCR is turning invisible plCCRInvisibleMsg* invisMsg=plCCRInvisibleMsg::ConvertNoRef(msg); if (invisMsg) { LogMsg(kLogDebug, "plNetClientMgr::MsgReceive - Got plCCRInvisibleMsg"); MakeCCRInvisible(invisMsg->fAvKey, invisMsg->fInvisLevel); return true; } plCCRBanLinkingMsg* banLinking = plCCRBanLinkingMsg::ConvertNoRef(msg); if (banLinking) { DebugMsg("Setting BanLinking to %d", banLinking->fBan); SetFlagsBit(kBanLinking, banLinking->fBan); return true; } plCCRSilencePlayerMsg* silence = plCCRSilencePlayerMsg::ConvertNoRef(msg); if (silence) { DebugMsg("Setting Silence to %d", silence->fSilence); SetFlagsBit(kSilencePlayer, silence->fSilence); return true; } plNetVoiceListMsg* voxList = plNetVoiceListMsg::ConvertNoRef(msg); if (voxList) { IHandleNetVoiceListMsg(voxList); return true; } plSynchEnableMsg* synchEnable = plSynchEnableMsg::ConvertNoRef(msg); if (synchEnable) { if (synchEnable->fPush) { plSynchedObject::PushSynchDisabled(!synchEnable->fEnable); } else { plSynchedObject::PopSynchDisabled(); } return true; } plClientMsg* clientMsg = plClientMsg::ConvertNoRef(msg); if (clientMsg && clientMsg->GetClientMsgFlag()==plClientMsg::kInitComplete) { // add 1 debug object for age sdl if (plNetObjectDebugger::GetInstance()) { plNetObjectDebugger::GetInstance()->RemoveDebugObject("AgeSDLHook"); plNetObjectDebugger::GetInstance()->AddDebugObject("AgeSDLHook"); } // if we're linking to startup we don't need (or want) a player set plString ageName = NetCommGetStartupAge()->ageDatasetName; if (ageName.IsEmpty()) ageName = "StartUp"; if (ageName.CompareI("StartUp") == 0) NetCommSetActivePlayer(0, nullptr); plAgeLinkStruct link; link.GetAgeInfo()->SetAgeFilename(NetCommGetStartupAge()->ageDatasetName); link.SetLinkingRules(plNetCommon::LinkingRules::kOriginalBook); plNetLinkingMgr::GetInstance()->LinkToAge(&link); return true; } return plNetClientApp::MsgReceive(msg); }
BOOL CALLBACK UruLoginDialogProc( HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam ) { static LoginDialogParam* pLoginParam; static bool showAuthFailed = false; switch( uMsg ) { case WM_INITDIALOG: { s_loginDlgRunning = true; _beginthread(StatusCallback, 0, hwndDlg); pLoginParam = (LoginDialogParam*)lParam; SetWindowText(hwndDlg, "Login"); SendMessage(hwndDlg, WM_SETICON, ICON_BIG, (LPARAM)LoadIcon(gHInst, MAKEINTRESOURCE(IDI_ICON_DIRT))); EnableWindow(GetDlgItem(hwndDlg, IDOK), FALSE); SetDlgItemText(hwndDlg, IDC_URULOGIN_USERNAME, pLoginParam->username); CheckDlgButton(hwndDlg, IDC_URULOGIN_REMEMBERPASS, pLoginParam->remember ? BST_CHECKED : BST_UNCHECKED); if (pLoginParam->remember) SetDlgItemText(hwndDlg, IDC_URULOGIN_PASSWORD, FAKE_PASS_STRING); SetFocus(GetDlgItem(hwndDlg, pLoginParam->focus)); if (IS_NET_ERROR(pLoginParam->authError)) { showAuthFailed = true; } SendMessage(GetDlgItem(hwndDlg, IDC_PRODUCTSTRING), WM_SETTEXT, 0, (LPARAM)plProduct::ProductString().c_str()); for (int i = 0; i < plLocalization::GetNumLocales(); i++) { SendMessage(GetDlgItem(hwndDlg, IDC_LANGUAGE), CB_ADDSTRING, 0, (LPARAM)plLocalization::GetLanguageName((plLocalization::Language)i)); } SendMessage(GetDlgItem(hwndDlg, IDC_LANGUAGE), CB_SETCURSEL, (WPARAM)plLocalization::GetLanguage(), 0); SetTimer(hwndDlg, AUTH_LOGIN_TIMER, 10, NULL); return FALSE; } case WM_USER_SETSTATUSMSG: SendMessage(GetDlgItem(hwndDlg, IDC_STATUS_TEXT), WM_SETTEXT, 0, lParam); return TRUE; case WM_DESTROY: { s_loginDlgRunning = false; s_statusEvent.Wait(); KillTimer(hwndDlg, AUTH_LOGIN_TIMER); return TRUE; } case WM_NCHITTEST: { SetWindowLongPtr(hwndDlg, DWL_MSGRESULT, (LONG_PTR)HTCAPTION); return TRUE; } case WM_PAINT: { if (showAuthFailed) { SetTimer(hwndDlg, AUTH_FAILED_TIMER, 10, NULL); showAuthFailed = false; } return FALSE; } case WM_COMMAND: { if (HIWORD(wParam) == BN_CLICKED && (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)) { bool ok = (LOWORD(wParam) == IDOK); if (ok) { char password[kMaxPasswordLength]; GetDlgItemText(hwndDlg, IDC_URULOGIN_USERNAME, pLoginParam->username, kMaxAccountNameLength); GetDlgItemText(hwndDlg, IDC_URULOGIN_PASSWORD, password, kMaxPasswordLength); pLoginParam->remember = (IsDlgButtonChecked(hwndDlg, IDC_URULOGIN_REMEMBERPASS) == BST_CHECKED); plLocalization::Language new_language = (plLocalization::Language)SendMessage(GetDlgItem(hwndDlg, IDC_LANGUAGE), CB_GETCURSEL, 0, 0L); plLocalization::SetLanguage(new_language); SaveUserPass (pLoginParam, password); // Welcome to HACKland, population: Branan // The code to write general.ini really doesn't belong here, but it works... for now. // When general.ini gets expanded, this will need to find a proper home somewhere. { plFileName gipath = plFileName::Join(plFileSystem::GetInitPath(), "general.ini"); plString ini_str = plFormat("App.SetLanguage {}\n", plLocalization::GetLanguageName(new_language)); hsStream* gini = plEncryptedStream::OpenEncryptedFileWrite(gipath); gini->WriteString(ini_str); gini->Close(); delete gini; } memset(&pLoginParam->authError, 0, sizeof(pLoginParam->authError)); bool cancelled = AuthenticateNetClientComm(&pLoginParam->authError, hwndDlg); if (IS_NET_SUCCESS(pLoginParam->authError) && !cancelled) EndDialog(hwndDlg, ok); else { if (!cancelled) ::DialogBoxParam(gHInst, MAKEINTRESOURCE( IDD_AUTHFAILED ), hwndDlg, AuthFailedDialogProc, (LPARAM)pLoginParam); else { NetCommDisconnect(); } } } else EndDialog(hwndDlg, ok); return TRUE; } else if (HIWORD(wParam) == EN_CHANGE && LOWORD(wParam) == IDC_URULOGIN_USERNAME) { char username[kMaxAccountNameLength]; GetDlgItemText(hwndDlg, IDC_URULOGIN_USERNAME, username, kMaxAccountNameLength); if (StrLen(username) == 0) EnableWindow(GetDlgItem(hwndDlg, IDOK), FALSE); else EnableWindow(GetDlgItem(hwndDlg, IDOK), TRUE); return TRUE; } else if (HIWORD(wParam) == BN_CLICKED && LOWORD(wParam) == IDC_URULOGIN_NEWACCTLINK) { plString signupurl = GetServerSignupUrl(); ShellExecuteW(NULL, L"open", signupurl.ToWchar(), NULL, NULL, SW_SHOWNORMAL); return TRUE; } break; } case WM_TIMER: { switch(wParam) { case AUTH_FAILED_TIMER: KillTimer(hwndDlg, AUTH_FAILED_TIMER); ::DialogBoxParam(gHInst, MAKEINTRESOURCE( IDD_AUTHFAILED ), hwndDlg, AuthFailedDialogProc, (LPARAM)pLoginParam); return TRUE; case AUTH_LOGIN_TIMER: NetCommUpdate(); return TRUE; } return FALSE; } } return FALSE; }
int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpCmdLine, int nCmdShow) { PF_CONSOLE_INIT_ALL() // Set global handle gHInst = hInst; CCmdParser cmdParser(s_cmdLineArgs, arrsize(s_cmdLineArgs)); cmdParser.Parse(); bool doIntroDialogs = true; #ifndef PLASMA_EXTERNAL_RELEASE if (cmdParser.IsSpecified(kArgSkipLoginDialog)) doIntroDialogs = false; if (cmdParser.IsSpecified(kArgLocalData)) { gDataServerLocal = true; gSkipPreload = true; } if (cmdParser.IsSpecified(kArgSkipPreload)) gSkipPreload = true; #endif plFileName serverIni = "server.ini"; if (cmdParser.IsSpecified(kArgServerIni)) serverIni = plString::FromWchar(cmdParser.GetString(kArgServerIni)); // check to see if we were launched from the patcher bool eventExists = false; // we check to see if the event exists that the patcher should have created HANDLE hPatcherEvent = CreateEventW(nil, TRUE, FALSE, L"UruPatcherEvent"); if (hPatcherEvent != NULL) { // successfully created it, check to see if it was already created if (GetLastError() == ERROR_ALREADY_EXISTS) { // it already existed, so the patcher is waiting, signal it so the patcher can die SetEvent(hPatcherEvent); eventExists = true; } } #ifdef PLASMA_EXTERNAL_RELEASE // if the client was started directly, run the patcher, and shutdown STARTUPINFOW si; PROCESS_INFORMATION pi; memset(&si, 0, sizeof(si)); memset(&pi, 0, sizeof(pi)); si.cb = sizeof(si); const char** addrs; if (!eventExists) // if it is missing, assume patcher wasn't launched { plStringStream cmdLine; GetAuthSrvHostnames(&addrs); if (strlen(addrs[0])) cmdLine << " /AuthSrv=" << addrs[0]; GetFileSrvHostnames(&addrs); if (strlen(addrs[0])) cmdLine << " /FileSrv=" << addrs[0]; GetGateKeeperSrvHostnames(&addrs); if (strlen(addrs[0])) cmdLine << " /GateKeeperSrv=" << addrs[0]; if(!CreateProcessW(s_patcherExeName, (LPWSTR)cmdLine.GetString().ToUtf16().GetData(), NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi)) { hsMessageBox("Failed to launch patcher", "Error", hsMessageBoxNormal); } CloseHandle( pi.hThread ); CloseHandle( pi.hProcess ); return PARABLE_NORMAL_EXIT; } #endif // Load an optional general.ini plFileName gipath = plFileName::Join(plFileSystem::GetInitPath(), "general.ini"); FILE *generalini = plFileSystem::Open(gipath, "rb"); if (generalini) { fclose(generalini); pfConsoleEngine tempConsole; tempConsole.ExecuteFile(gipath); } #ifdef PLASMA_EXTERNAL_RELEASE // If another instance is running, exit. We'll automatically release our // lock on the mutex when our process exits HANDLE hOneInstance = CreateMutex(nil, FALSE, "UruExplorer"); if (WaitForSingleObject(hOneInstance,0) != WAIT_OBJECT_0) { switch (plLocalization::GetLanguage()) { case plLocalization::kFrench: hsMessageBox("Une autre copie d'URU est déjà en cours d'exécution", "Erreur", hsMessageBoxNormal); break; case plLocalization::kGerman: hsMessageBox("URU wird bereits in einer anderen Instanz ausgeführt", "Fehler", hsMessageBoxNormal); break; case plLocalization::kSpanish: hsMessageBox("En estos momentos se está ejecutando otra copia de URU", "Error", hsMessageBoxNormal); break; case plLocalization::kItalian: hsMessageBox("Un'altra copia di URU è già aperta", "Errore", hsMessageBoxNormal); break; // default is English default: hsMessageBox("Another copy of URU is already running", "Error", hsMessageBoxNormal); break; } return PARABLE_NORMAL_EXIT; } #endif FILE *serverIniFile = plFileSystem::Open(serverIni, "rb"); if (serverIniFile) { fclose(serverIniFile); pfConsoleEngine tempConsole; tempConsole.ExecuteFile(serverIni); } else { hsMessageBox("No server.ini file found. Please check your URU installation.", "Error", hsMessageBoxNormal); return PARABLE_NORMAL_EXIT; } NetCliAuthAutoReconnectEnable(false); NetCommSetReadIniAccountInfo(!doIntroDialogs); InitNetClientComm(); curl_global_init(CURL_GLOBAL_ALL); bool needExit = false; LoginDialogParam loginParam; memset(&loginParam, 0, sizeof(loginParam)); LoadUserPass(&loginParam); if (!doIntroDialogs && loginParam.remember) { ENetError auth; NetCommSetAccountUsernamePassword(loginParam.username, loginParam.namePassHash); bool cancelled = AuthenticateNetClientComm(&auth, NULL); if (IS_NET_ERROR(auth) || cancelled) { doIntroDialogs = true; loginParam.authError = auth; if (cancelled) { NetCommDisconnect(); } } } if (doIntroDialogs) { needExit = ::DialogBoxParam( hInst, MAKEINTRESOURCE( IDD_URULOGIN_MAIN ), NULL, UruLoginDialogProc, (LPARAM)&loginParam ) <= 0; } if (doIntroDialogs && !needExit) { HINSTANCE hRichEdDll = LoadLibrary("RICHED20.DLL"); INT_PTR val = ::DialogBoxParam( hInst, MAKEINTRESOURCE( IDD_URULOGIN_EULA ), NULL, UruTOSDialogProc, (LPARAM)hInst); FreeLibrary(hRichEdDll); if (val <= 0) { DWORD error = GetLastError(); needExit = true; } } curl_global_cleanup(); if (needExit) { 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() ); // // Main loop // MSG msg; do { gClient->MainLoop(); if( gClient->GetDone() ) break; // Look for a message while (PeekMessage( &msg, NULL, 0, 0, PM_REMOVE )) { // Handle the message 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 DeInitNetClientComm(); // Uninstall our unhandled exception filter, if we installed one #ifndef HS_DEBUGGING SetUnhandledExceptionFilter( oldFilter ); #endif // Exit WinMain and terminate the app.... return PARABLE_NORMAL_EXIT; }
//============================================================================ bool plNCAgeJoiner::MsgReceive (plMessage * msg) { plNetClientMgr * nc = plNetClientMgr::GetInstance(); plAvatarMgr * am = plAvatarMgr::GetInstance(); plAgeLoader * al = plAgeLoader::GetInstance(); //======================================================================== // Finished updating the age from FileSrv //======================================================================== if (plResPatcherMsg * resMsg = plResPatcherMsg::ConvertNoRef(msg)) { if (resMsg->Success()) { nc->ResetServerTimeOffset(); NetCommLinkToAge( age, this ); LogMsg(kLogPerf, L"AgeJoiner: Next:kNoOp (age updated)"); } else Complete(false, resMsg->GetError()); return true; } //======================================================================== // Connected to age instance //======================================================================== if (plNetCommLinkToAgeMsg * linkToAgeMsg = plNetCommLinkToAgeMsg::ConvertNoRef(msg)) { if (IS_NET_ERROR(linkToAgeMsg->result)) { Complete(false, "LinkToAge failed"); } else if (unsigned ageVaultId = NetCommGetAge()->ageVaultId) { // Download the age vault VaultDownload( L"AgeJoin", ageVaultId, AgeVaultDownloadCallback, this, nil, // FVaultDownloadProgressCallback this ); } else { // not vault to downloaded, just start loading age data LogMsg(kLogPerf, L"AgeJoiner: Next:kLoadAge (no vault)"); nextOp = kLoadAge; } return true; } //======================================================================== // All age data paged in //======================================================================== if (plAgeLoaded2Msg * ageLoaded2Msg = plAgeLoaded2Msg::ConvertNoRef(msg)) { // Exec custom age settings al->ExecPendingAgeFniFiles(); al->ExecPendingAgeCsvFiles(); LogMsg(kLogPerf, L"AgeJoiner: Next:kLoadPlayer"); nextOp = kLoadPlayer; return true; } //======================================================================== // Local avatar loaded //======================================================================== plPlayerPageMsg * playerPageMsg = plPlayerPageMsg::ConvertNoRef(msg); if (playerPageMsg && !playerPageMsg->fUnload && playerPageMsg->fPlayer && playerPageMsg->fLocallyOriginated) { if (NetCommNeedToLoadAvatar()) NetCommSetAvatarLoaded(); LogMsg(kLogPerf, L"AgeJoiner: Next:kPropagatePlayer"); nextOp = kPropagatePlayer; return false; // NetClientMgr must also handle this message } //======================================================================== // Received all SDL states //======================================================================== plNetClientMgrMsg * netClientMgrMsg = plNetClientMgrMsg::ConvertNoRef(msg); if (netClientMgrMsg && netClientMgrMsg->type == plNetClientMgrMsg::kNotifyRcvdAllSDLStates) { LogMsg(kLogPerf, L"AgeJoiner: Next:kEnableClickables"); nextOp = kDestroyProgressBar; return true; } //======================================================================== // Done loading all states. Time to link in! //======================================================================== plInitialAgeStateLoadedMsg * stateMsg = plInitialAgeStateLoadedMsg::ConvertNoRef(msg); if(stateMsg) { plNetObjectDebugger::GetInstance()->LogMsg("OnServerInitComplete"); nc->SetFlagsBit(plNetClientApp::kLoadingInitialAgeState, false); const plArmatureMod *avMod = plAvatarMgr::GetInstance()->GetLocalAvatar(); plLinkEffectsTriggerMsg* lem = new plLinkEffectsTriggerMsg(); lem->SetLeavingAge(false); // linking in lem->SetLinkKey(nc->GetLocalPlayerKey()); plKey animKey = avMod->GetLinkInAnimKey(); lem->SetLinkInAnimKey(animKey); // indicate if we are invisible if (avMod && avMod->IsInStealthMode() && avMod->GetTarget(0)) lem->SetInvisLevel(avMod->GetStealthLevel()); lem->SetBCastFlag(plMessage::kNetPropagate); lem->MuteLinkSfx(muteLinkSfx); lem->AddReceiver(hsgResMgr::ResMgr()->FindKey(plUoid(kLinkEffectsMgr_KEY))); lem->AddReceiver(hsgResMgr::ResMgr()->FindKey(plUoid(kClient_KEY))); lem->Send(); Complete(true, "Age joined"); return true; } return false; }
//============================================================================ bool ManifestRequestTrans::Recv ( const uint8_t msg[], unsigned bytes ) { m_timeoutAtMs = hsTimer::GetMilliSeconds<uint32_t>() + NetTransGetTimeoutMs(); // Reset the timeout counter const File2Cli_ManifestReply & reply = *(const File2Cli_ManifestReply *) msg; uint32_t numFiles = reply.numFiles; uint32_t wchar_tCount = reply.wchar_tCount; const wchar_t* curChar = reply.manifestData; // the pointer is not yet dereferenced here! // tell the server we got the data Cli2File_ManifestEntryAck manifestAck; manifestAck.messageId = kCli2File_ManifestEntryAck; manifestAck.transId = reply.transId; manifestAck.messageBytes = sizeof(manifestAck); manifestAck.readerId = reply.readerId; m_conn->Send(&manifestAck, manifestAck.messageBytes); // if wchar_tCount is 2 or less, the data only contains the terminator "\0\0" and we // don't need to convert anything (and we are done) if ((IS_NET_ERROR(reply.result)) || (wchar_tCount <= 2)) { // we have a problem... or we have nothing to so, so we're done m_result = reply.result; m_state = kTransStateComplete; return true; } if (numFiles > m_manifest.Count()) m_manifest.SetCount(numFiles); // reserve the space ahead of time // manifestData format: "clientFile\0downloadFile\0md5\0filesize\0zipsize\0flags\0...\0\0" bool done = false; while (!done) { if (wchar_tCount == 0) { done = true; break; } // copy the data over to our array (m_numEntriesReceived is the current index) NetCliFileManifestEntry& entry = m_manifest[m_numEntriesReceived]; // -------------------------------------------------------------------- // read in the clientFilename unsigned filenameLen = 0; ReadStringFromMsg(curChar, entry.clientName, &filenameLen); curChar += filenameLen; // advance the pointer wchar_tCount -= filenameLen; // keep track of the amount remaining if ((*curChar != L'\0') || (wchar_tCount <= 0)) return false; // something is screwy, abort and disconnect // point it at the downloadFile curChar++; wchar_tCount--; // -------------------------------------------------------------------- // read in the downloadFilename filenameLen = 0; ReadStringFromMsg(curChar, entry.downloadName, &filenameLen); curChar += filenameLen; // advance the pointer wchar_tCount -= filenameLen; // keep track of the amount remaining if ((*curChar != L'\0') || (wchar_tCount <= 0)) return false; // something is screwy, abort and disconnect // point it at the md5 curChar++; wchar_tCount--; // -------------------------------------------------------------------- // read in the md5 filenameLen = 32; ReadStringFromMsg(curChar, entry.md5, &filenameLen); curChar += filenameLen; // advance the pointer wchar_tCount -= filenameLen; // keep track of the amount remaining if ((*curChar != L'\0') || (wchar_tCount <= 0)) return false; // something is screwy, abort and disconnect // point it at the md5 for compressed files curChar++; wchar_tCount--; // -------------------------------------------------------------------- // read in the md5 for compressed files filenameLen = 32; ReadStringFromMsg(curChar, entry.md5compressed, &filenameLen); curChar += filenameLen; // advance the pointer wchar_tCount -= filenameLen; // keep track of the amount remaining if ((*curChar != L'\0') || (wchar_tCount <= 0)) return false; // something is screwy, abort and disconnect // point it at the first part of the filesize value (format: 0xHHHHLLLL) curChar++; wchar_tCount--; // -------------------------------------------------------------------- if (wchar_tCount < 2) // we have to have 2 chars for the size return false; // screwy data ReadUnsignedFromMsg(curChar, &entry.fileSize); curChar += 2; wchar_tCount -= 2; if ((*curChar != L'\0') || (wchar_tCount <= 0)) return false; // screwy data // point it at the first part of the zipsize value (format: 0xHHHHLLLL) curChar++; wchar_tCount--; // -------------------------------------------------------------------- if (wchar_tCount < 2) // we have to have 2 chars for the size return false; // screwy data ReadUnsignedFromMsg(curChar, &entry.zipSize); curChar += 2; wchar_tCount -= 2; if ((*curChar != L'\0') || (wchar_tCount <= 0)) return false; // screwy data // point it at the first part of the flags value (format: 0xHHHHLLLL) curChar++; wchar_tCount--; // -------------------------------------------------------------------- if (wchar_tCount < 2) // we have to have 2 chars for the size return false; // screwy data ReadUnsignedFromMsg(curChar, &entry.flags); curChar += 2; wchar_tCount -= 2; if ((*curChar != L'\0') || (wchar_tCount <= 0)) return false; // screwy data // -------------------------------------------------------------------- // point it at either the second part of the terminator, or the next filename curChar++; wchar_tCount--; // do sanity checking if (*curChar == L'\0') { // we hit the terminator if (wchar_tCount != 1) return false; // invalid data, we shouldn't have any more done = true; // we're done } else if (wchar_tCount < 14) // we must have at least three 1-char strings, three nulls, three 32-bit ints, and 2-char terminator left (3+3+6+2) return false; // screwy data // increment entries received m_numEntriesReceived++; if ((m_numEntriesReceived >= numFiles) && !done) { // too much data, abort return false; } } // check for completion if (m_numEntriesReceived >= numFiles) { // all entires received, mark as complete m_result = reply.result; m_state = kTransStateComplete; } return true; }
//============================================================================ bool plNCAgeJoiner::MsgReceive (plMessage * msg) { plNetClientMgr * nc = plNetClientMgr::GetInstance(); plAvatarMgr * am = plAvatarMgr::GetInstance(); plAgeLoader * al = plAgeLoader::GetInstance(); //======================================================================== // Finished updating the age from FileSrv //======================================================================== if (plResPatcherMsg * resMsg = plResPatcherMsg::ConvertNoRef(msg)) { if (resMsg->Success()) { nc->ResetServerTimeOffset(); NetCommLinkToAge( age, this ); LogMsg(kLogPerf, L"AgeJoiner: Next:kNoOp (age updated)"); } else Complete(false, resMsg->GetError()); return true; } //======================================================================== // Connected to age instance //======================================================================== if (plNetCommLinkToAgeMsg * linkToAgeMsg = plNetCommLinkToAgeMsg::ConvertNoRef(msg)) { if (IS_NET_ERROR(linkToAgeMsg->result)) { Complete(false, "LinkToAge failed"); } else if (unsigned ageVaultId = NetCommGetAge()->ageVaultId) { // Download the age vault VaultDownload( L"AgeJoin", ageVaultId, AgeVaultDownloadCallback, this, nil, // FVaultDownloadProgressCallback this ); } else { // not vault to downloaded, just start loading age data LogMsg(kLogPerf, L"AgeJoiner: Next:kLoadAge (no vault)"); nextOp = kLoadAge; } return true; } //======================================================================== // All age data paged in //======================================================================== if (plAgeLoaded2Msg * ageLoaded2Msg = plAgeLoaded2Msg::ConvertNoRef(msg)) { // Exec custom age settings al->ExecPendingAgeFniFiles(); al->ExecPendingAgeCsvFiles(); LogMsg(kLogPerf, L"AgeJoiner: Next:kLoadPlayer"); nextOp = kLoadPlayer; return true; } //======================================================================== // Local avatar loaded //======================================================================== plPlayerPageMsg * playerPageMsg = plPlayerPageMsg::ConvertNoRef(msg); if (playerPageMsg && !playerPageMsg->fUnload && playerPageMsg->fPlayer && playerPageMsg->fLocallyOriginated) { if (NetCommNeedToLoadAvatar()) NetCommSetAvatarLoaded(); LogMsg(kLogPerf, L"AgeJoiner: Next:kPropagatePlayer"); nextOp = kPropagatePlayer; return false; // NetClientMgr must also handle this message } //======================================================================== // Received all SDL states //======================================================================== plNetClientMgrMsg * netClientMgrMsg = plNetClientMgrMsg::ConvertNoRef(msg); if (netClientMgrMsg && netClientMgrMsg->type == plNetClientMgrMsg::kNotifyRcvdAllSDLStates) { LogMsg(kLogPerf, L"AgeJoiner: Next:kEnableClickables"); nextOp = kDestroyProgressBar; return true; } return false; }