2127 lines
65 KiB
C++
2127 lines
65 KiB
C++
|
/*
|
||
|
** Command & Conquer Renegade(tm)
|
||
|
** Copyright 2025 Electronic Arts 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/>.
|
||
|
*/
|
||
|
|
||
|
/***********************************************************************************************
|
||
|
*** Confidential - Westwood Studios ***
|
||
|
***********************************************************************************************
|
||
|
* *
|
||
|
* Project Name : Commando *
|
||
|
* *
|
||
|
* $Archive:: /Commando/Code/Commando/wolgmode.cpp $*
|
||
|
* *
|
||
|
* $Author:: Steve_t $*
|
||
|
* *
|
||
|
* $Modtime:: 10/19/02 12:51p $*
|
||
|
* *
|
||
|
* $Revision:: 124 $*
|
||
|
* *
|
||
|
*---------------------------------------------------------------------------------------------*
|
||
|
* Functions: *
|
||
|
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||
|
|
||
|
#include "WOLGMode.h"
|
||
|
#include "GameData.h"
|
||
|
#include "GameChanList.h"
|
||
|
#include "GameChannel.h"
|
||
|
#include "GameInitMgr.h"
|
||
|
#include "WOLChatMgr.h"
|
||
|
#include "WOLBuddyMgr.h"
|
||
|
#include "WOLQuickMatch.h"
|
||
|
#include "WOLGameInfo.h"
|
||
|
#include "DlgWOLWait.h"
|
||
|
#include "DlgMessageBox.h"
|
||
|
#include "_globals.h"
|
||
|
#include "colors.h"
|
||
|
#include "cNetwork.h"
|
||
|
#include "GameResSend.h"
|
||
|
#include "PlayerManager.h"
|
||
|
#include "MessageWindow.h"
|
||
|
#include "natter.h"
|
||
|
#include "WWProfile.h"
|
||
|
#include "BandwidthCheck.h"
|
||
|
#include "WOLLoginProfile.h"
|
||
|
#include "DlgDownload.h"
|
||
|
#include "AutoStart.h"
|
||
|
#include "cpudetect.h"
|
||
|
#include "dx8wrapper.h"
|
||
|
#include "systeminfolog.h"
|
||
|
#include "registry.h"
|
||
|
#include "init.h"
|
||
|
#include "debug.h"
|
||
|
#include <WWOnline\WOLString.h>
|
||
|
#include <WWOnline\WOLProduct.h>
|
||
|
#include <WWOnline\WOLSession.h>
|
||
|
#include <WWOnline\WOLChannel.h>
|
||
|
#include <WWOnline\WaitCondition.h>
|
||
|
#include <WWOnline\WOLGame.h>
|
||
|
#include <WWOnline\WOLGameOptions.h>
|
||
|
#include <WWOnline\WOLPageMsg.h>
|
||
|
#include <WWOnline\WOLLadder.h>
|
||
|
#include <WWOnline\WOLConnect.h>
|
||
|
#include <WWOnline\WOLServer.h>
|
||
|
#include <WWOnline\PingProfile.h>
|
||
|
#include <WWAudio\WWAudio.h>
|
||
|
#include <WWLib\RealCRC.h>
|
||
|
#include "String_IDs.h"
|
||
|
#include <WWTranslateDB\TranslateDB.h>
|
||
|
#include <WWDebug\WWDebug.h>
|
||
|
#include <WWDebug\WWProfile.h>
|
||
|
#include "specialbuilds.h"
|
||
|
#include "slavemaster.h"
|
||
|
#include "sctextobj.h"
|
||
|
#include "mainloop.h"
|
||
|
|
||
|
using namespace WWOnline;
|
||
|
|
||
|
// Check for patches every five minutes
|
||
|
#define PATCH_CHECK_FREQUENCY (1000 * 5)
|
||
|
|
||
|
const int RENEGADE_GAMECODE = 12;
|
||
|
const wchar_t* RENEGADE_LOBBY_PASSWORD = L"not_a_valid_password"; // Password removed per Security review requirements. LFeenanEA - 27th January 2025
|
||
|
|
||
|
const wchar_t* _cdecl Translate_WOLString(const char* token)
|
||
|
{
|
||
|
if (token) {
|
||
|
StringClass desc(80, true);
|
||
|
desc.Format("IDS_%s", token);
|
||
|
const WCHAR* text = TRANSLATE_BY_DESC(desc);
|
||
|
|
||
|
#ifdef WWDEBUG
|
||
|
if (STRING_NOT_FOUND == text) {
|
||
|
WWDEBUG_SAY(("ERROR: WOL String '%s' not found!\n", token));
|
||
|
return L"WOL_NO_STRING";
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
return text;
|
||
|
}
|
||
|
|
||
|
WWDEBUG_SAY(("WARNING: WOL_xxxx token is NULL\n"));
|
||
|
return L"WOL_BADSTRING";
|
||
|
}
|
||
|
|
||
|
|
||
|
/******************************************************************************
|
||
|
*
|
||
|
* NAME
|
||
|
* WolGameModeClass::WolGameModeClass
|
||
|
*
|
||
|
* DESCRIPTION
|
||
|
* Constructor
|
||
|
*
|
||
|
* INPUTS
|
||
|
* NONE
|
||
|
*
|
||
|
* RESULT
|
||
|
* NONE
|
||
|
*
|
||
|
******************************************************************************/
|
||
|
|
||
|
WolGameModeClass::WolGameModeClass() :
|
||
|
mWOLChatMgr(NULL),
|
||
|
mWOLBuddyMgr(NULL),
|
||
|
mGameInProgress(false),
|
||
|
mQuietMode(false),
|
||
|
mConnected(false),
|
||
|
mLastPatchCheckTime(0),
|
||
|
mStartQuitProcessTime(0),
|
||
|
mPatchAvailable(false),
|
||
|
mMonitorConnection(false)
|
||
|
{
|
||
|
WWDEBUG_SAY(("WOLGameModeClass Instantiated\n"));
|
||
|
|
||
|
WOLString::SetLookupFunc(Translate_WOLString);
|
||
|
}
|
||
|
|
||
|
|
||
|
/******************************************************************************
|
||
|
*
|
||
|
* NAME
|
||
|
* WolGameModeClass::~WolGameModeClass
|
||
|
*
|
||
|
* DESCRIPTION
|
||
|
* Destructor
|
||
|
*
|
||
|
* INPUTS
|
||
|
* NONE
|
||
|
*
|
||
|
* RESULT
|
||
|
* NONE
|
||
|
*
|
||
|
******************************************************************************/
|
||
|
|
||
|
WolGameModeClass::~WolGameModeClass()
|
||
|
{
|
||
|
WWDEBUG_SAY(("WOLGameModeClass Destroyed\n"));
|
||
|
}
|
||
|
|
||
|
|
||
|
/******************************************************************************
|
||
|
*
|
||
|
* NAME
|
||
|
* WolGameModeClass::Init
|
||
|
*
|
||
|
* DESCRIPTION
|
||
|
* Activate Westwood Online game mode
|
||
|
*
|
||
|
* INPUTS
|
||
|
* NONE
|
||
|
*
|
||
|
* RESULT
|
||
|
* NONE
|
||
|
*
|
||
|
******************************************************************************/
|
||
|
|
||
|
void WolGameModeClass::Init(void)
|
||
|
{
|
||
|
WWDEBUG_SAY(("WolGameModeClass Init\n"));
|
||
|
|
||
|
// Check if product is already initialized
|
||
|
RefPtrConst<Product> product = Product::Current();
|
||
|
|
||
|
if (!product.IsValid()) {
|
||
|
Product::Initializer(APPLICATION_SUB_KEY_NAME, RENEGADE_GAMECODE, RENEGADE_LOBBY_PASSWORD, RENEGADE_BASE_SKU);
|
||
|
}
|
||
|
|
||
|
mWOLSession = Session::GetInstance(true);
|
||
|
|
||
|
if (mWOLSession.IsValid()) {
|
||
|
mWOLSession->EnableProgressiveChannelList(true);
|
||
|
mWOLSession->SetAutoRequestFlags(REQUEST_NONE);
|
||
|
|
||
|
Observer<LadderInfoEvent>::NotifyMe(*mWOLSession);
|
||
|
|
||
|
mWOLBuddyMgr = WOLBuddyMgr::GetInstance(true);
|
||
|
WWASSERT_PRINT(mWOLBuddyMgr, "WOLBuddyManager failed to instantiate.");
|
||
|
|
||
|
mWOLChatMgr = WOLChatMgr::GetInstance(true);
|
||
|
WWASSERT_PRINT(mWOLChatMgr, "WOLChatMgr failed to instantiate.");
|
||
|
|
||
|
WOLNATInterface.Init();
|
||
|
|
||
|
LoginProfile::EnableSaving(mWOLSession->IsStoreLoginAllowed());
|
||
|
}
|
||
|
|
||
|
mQuickMatch = NULL;
|
||
|
mTheGame = NULL;
|
||
|
}
|
||
|
|
||
|
|
||
|
/******************************************************************************
|
||
|
*
|
||
|
* NAME
|
||
|
* WolGameModeClass::Shutdown
|
||
|
*
|
||
|
* DESCRIPTION
|
||
|
* Deactivate Westwood Online game mode.
|
||
|
*
|
||
|
* INPUTS
|
||
|
* NONE
|
||
|
*
|
||
|
* RESULT
|
||
|
* NONE
|
||
|
*
|
||
|
******************************************************************************/
|
||
|
|
||
|
void WolGameModeClass::Shutdown(void)
|
||
|
{
|
||
|
WWDEBUG_SAY(("WolGameModeClass Shutdown\n"));
|
||
|
|
||
|
if (mWOLSession.IsValid()) {
|
||
|
WOLNATInterface.Shutdown();
|
||
|
|
||
|
RefPtr<WaitCondition> logoutWait = mWOLSession->Logout();
|
||
|
WWASSERT(logoutWait.IsValid());
|
||
|
DlgWOLWait::DoDialog(IDS_WOL_LOGOFF, logoutWait);
|
||
|
}
|
||
|
|
||
|
if (mWOLBuddyMgr) {
|
||
|
mWOLBuddyMgr->Release_Ref();
|
||
|
mWOLBuddyMgr = NULL;
|
||
|
}
|
||
|
|
||
|
if (mWOLChatMgr) {
|
||
|
mWOLChatMgr->Release_Ref();
|
||
|
mWOLChatMgr = NULL;
|
||
|
}
|
||
|
|
||
|
// Release current profile.
|
||
|
LoginProfile::SetCurrent(NULL);
|
||
|
LoginInfo::ClearList();
|
||
|
|
||
|
mMonitorConnection = false;
|
||
|
|
||
|
mWOLSession.Release();
|
||
|
}
|
||
|
|
||
|
|
||
|
/******************************************************************************
|
||
|
*
|
||
|
* NAME
|
||
|
* WolGameModeClass::Think
|
||
|
*
|
||
|
* DESCRIPTION
|
||
|
* Periodic processing; called once each game loop.
|
||
|
*
|
||
|
* INPUTS
|
||
|
* NONE
|
||
|
*
|
||
|
* RESULT
|
||
|
* NONE
|
||
|
*
|
||
|
******************************************************************************/
|
||
|
|
||
|
void WolGameModeClass::Think(void)
|
||
|
{
|
||
|
WWPROFILE("WOL Think");
|
||
|
static unsigned long _last_auto_kick = 0;
|
||
|
static unsigned long _kick_history_persist_time = 1000 * 60 * 60;
|
||
|
unsigned long time = TIMEGETTIME();
|
||
|
|
||
|
//---------------------------------------------------------------------------
|
||
|
// Yield time to WWOnline
|
||
|
//---------------------------------------------------------------------------
|
||
|
if (mWOLSession.IsValid()) {
|
||
|
mWOLSession->Process();
|
||
|
}
|
||
|
|
||
|
//---------------------------------------------------------------------------
|
||
|
// Periodically update quickmatch bot with recent server information
|
||
|
//---------------------------------------------------------------------------
|
||
|
if (mGameInProgress) {// && mQuickMatch) {
|
||
|
unsigned long theTime = TIMEGETTIME();
|
||
|
|
||
|
if (theTime >= mSendServerInfoTime) {
|
||
|
//mSendServerInfoTime = (theTime + (120 * 1000));
|
||
|
//
|
||
|
// Try to help with hacks by updating the topic more frequently. Grrrr.
|
||
|
//
|
||
|
mSendServerInfoTime = (theTime + (20 * 1000));
|
||
|
|
||
|
RefPtr<ChannelData> channel = mWOLSession->GetCurrentChannel();
|
||
|
|
||
|
Update_Channel_Settings(mTheGame, channel);
|
||
|
mWOLSession->SendChannelTopic();
|
||
|
|
||
|
if (mQuickMatch) {
|
||
|
const char* exInfo = channel->GetExtraInfo();
|
||
|
const char* topic = channel->GetTopic();
|
||
|
mQuickMatch->SendServerInfo(exInfo, topic);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//---------------------------------------------------------------------------
|
||
|
// Autokick
|
||
|
//---------------------------------------------------------------------------
|
||
|
if (mGameInProgress && (time - _last_auto_kick > 2000 || time < _last_auto_kick)) {
|
||
|
_last_auto_kick = time;
|
||
|
Auto_Kick();
|
||
|
|
||
|
//
|
||
|
// Check for deadbeat channel lurkers.
|
||
|
//
|
||
|
if (cNetwork::I_Am_Server() && mGameInProgress) {
|
||
|
|
||
|
unsigned long time = TIMEGETTIME();
|
||
|
|
||
|
//
|
||
|
// Clear out old kicklist entries.
|
||
|
//
|
||
|
for (int i = IdleKickNameList.Count() - 1 ; i >= 0 ; i--) {
|
||
|
if (time - IdleKickTimeList[i] > _kick_history_persist_time || time < IdleKickTimeList[i]) {
|
||
|
IdleKickTimeList.Delete(i);
|
||
|
IdleKickNameList.Delete(i);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
const UserList& userList = mWOLSession->GetUserList();
|
||
|
const unsigned int count = userList.size();
|
||
|
|
||
|
for (unsigned int index = 0; index < count; index++) {
|
||
|
const RefPtr<UserData>& user = userList[index];
|
||
|
WWASSERT(user.IsValid());
|
||
|
|
||
|
if (user.IsValid()) {
|
||
|
|
||
|
//
|
||
|
// Make sure it's not me.
|
||
|
//
|
||
|
const RefPtr<LoginInfo>& login = mWOLSession->GetCurrentLogin();
|
||
|
|
||
|
WideStringClass myname;
|
||
|
if (login.IsValid()) {
|
||
|
myname = login->GetNickname();
|
||
|
}
|
||
|
|
||
|
if (myname.Compare_No_Case(user->GetName())) {
|
||
|
|
||
|
//
|
||
|
// Handle timer wrap.
|
||
|
//
|
||
|
if (time < user->mKickTimer) {
|
||
|
user->mKickTimer = time;
|
||
|
}
|
||
|
|
||
|
if (!cPlayerManager::Find_Player(user->GetName())) {
|
||
|
if (time - user->mKickTimer > 120 * 1000) {
|
||
|
StringClass tempstr;
|
||
|
user->GetName().Convert_To(tempstr);
|
||
|
WWDEBUG_SAY(("Kicking '%s' for sitting in the channel while not in the game\n", tempstr.Peek_Buffer()));
|
||
|
mWOLSession->KickUser(user->GetName());
|
||
|
user->mKickTimer += 10*1000;
|
||
|
|
||
|
//
|
||
|
// If he's already been kicked for this recently then ban him.
|
||
|
//
|
||
|
int chances = 3;
|
||
|
for (int i=0 ; i < IdleKickNameList.Count() ; i++) {
|
||
|
if (IdleKickNameList[i].Compare_No_Case(tempstr) == 0) {
|
||
|
chances--;
|
||
|
if (chances == 0) {
|
||
|
mWOLSession->BanUser(user->GetName(), true);
|
||
|
WWDEBUG_SAY(("Banning '%s' for being kicked too often.\n", tempstr.Peek_Buffer()));
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (chances > 0) {
|
||
|
WWDEBUG_SAY(("'%s' not banned - %d chances left.\n", tempstr.Peek_Buffer(), chances));
|
||
|
|
||
|
StringClass stringy(user->GetName());
|
||
|
IdleKickNameList.Add(stringy);
|
||
|
IdleKickTimeList.Add(TIMEGETTIME());
|
||
|
}
|
||
|
}
|
||
|
} else {
|
||
|
user->mKickTimer = time;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//---------------------------------------------------------------------------
|
||
|
// Check for restart conditions.
|
||
|
//---------------------------------------------------------------------------
|
||
|
if (mMonitorConnection) {
|
||
|
|
||
|
// Check for a pending restart for a new patch.
|
||
|
if ((mPatchAvailable || !mConnected) && mStartQuitProcessTime) {
|
||
|
if (time - mStartQuitProcessTime > 1000 * 4) {
|
||
|
if (SlaveMaster.Am_I_Slave()) {
|
||
|
Set_Exit_On_Exception(true);
|
||
|
cGameData::Set_Manual_Exit(true);
|
||
|
} else {
|
||
|
Quit_And_Restart();
|
||
|
}
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Check for patches.
|
||
|
// This doesn't work because you can't get a server list without also doing a complete reset of wolapi.
|
||
|
#if (0)
|
||
|
if (time - mLastPatchCheckTime > PATCH_CHECK_FREQUENCY) {
|
||
|
mLastPatchCheckTime = time;
|
||
|
if (mWOLSession.IsValid()) {
|
||
|
#ifdef WWDEBUG
|
||
|
bool success =
|
||
|
#endif //WWDEBUG
|
||
|
mWOLSession->RequestServerList(true);
|
||
|
WWASSERT(success);
|
||
|
}
|
||
|
}
|
||
|
#endif //(0)
|
||
|
|
||
|
// If we have lost connection and the number of players drops to zero then we can quit.
|
||
|
if (mMonitorConnection && !mConnected) {
|
||
|
if (The_Game() && The_Game()->Get_Time_Limit_Minutes()) {
|
||
|
if (cPlayerManager::Count() == 0) {
|
||
|
Quit_And_Restart();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Firewall code service.
|
||
|
WOLNATInterface.Service();
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
/******************************************************************************
|
||
|
*
|
||
|
* NAME
|
||
|
* WolGameModeClass::System_Timer_Reset
|
||
|
*
|
||
|
* DESCRIPTION
|
||
|
* Reset any internal variables as needed when the system timer resets.
|
||
|
*
|
||
|
* INPUTS
|
||
|
* NONE
|
||
|
*
|
||
|
* RESULT
|
||
|
* NONE
|
||
|
*
|
||
|
******************************************************************************/
|
||
|
|
||
|
void WolGameModeClass::System_Timer_Reset(void)
|
||
|
{
|
||
|
mSendServerInfoTime = (TIMEGETTIME() + (120 * 1000));
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
/******************************************************************************
|
||
|
*
|
||
|
* NAME
|
||
|
* WolGameModeClass::Create_Game
|
||
|
*
|
||
|
* DESCRIPTION
|
||
|
* Perform necessary game creation tasks for WWOnline.
|
||
|
* NOTE: This should only be called by game hosts.
|
||
|
*
|
||
|
* INPUTS
|
||
|
* Game - Instance of game to create for Westwood Online.
|
||
|
*
|
||
|
* RESULT
|
||
|
* NONE
|
||
|
*
|
||
|
******************************************************************************/
|
||
|
|
||
|
void WolGameModeClass::Create_Game(cGameData* theGame)
|
||
|
{
|
||
|
WWDEBUG_SAY(("WolGameModeClass::Create_Game\n"));
|
||
|
|
||
|
if (theGame) {
|
||
|
mTheGame = theGame;
|
||
|
mGameID = 0;
|
||
|
mGameInProgress = false;
|
||
|
|
||
|
//-------------------------------------------------------------------------
|
||
|
// Create and initialize channel for the new game.
|
||
|
//-------------------------------------------------------------------------
|
||
|
const WideStringClass& name = theGame->Get_Owner();
|
||
|
const wchar_t* password = theGame->Get_Password();
|
||
|
WWDEBUG_SAY(("Creating game channel '%S' Password: '%S'\n", (const WCHAR*)name, password));
|
||
|
|
||
|
RefPtrConst<Product> product = Product::Current();
|
||
|
WWASSERT(product.IsValid());
|
||
|
int gameCode = product->GetGameCode();
|
||
|
|
||
|
RefPtr<ChannelData> channel = ChannelData::Create(name, password, gameCode);
|
||
|
WWASSERT(channel.IsValid());
|
||
|
|
||
|
// Export channel settings for the game.
|
||
|
Update_Channel_Settings(theGame, channel);
|
||
|
|
||
|
//-------------------------------------------------------------------------
|
||
|
// Request WWOnline channel creation
|
||
|
//-------------------------------------------------------------------------
|
||
|
mChannelCreateSuccessFlag = false;
|
||
|
RefPtr<WaitCondition> createWait = mWOLSession->CreateChannel(channel, password);
|
||
|
WWASSERT(createWait.IsValid());
|
||
|
DlgWOLWait::DoDialog(IDS_GAME_CREATECHANNEL, createWait, this, 0, mQuietMode ? 0xffffffff : 0);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
/******************************************************************************
|
||
|
*
|
||
|
* NAME
|
||
|
* WolGameModeClass::Leave_Game
|
||
|
*
|
||
|
* DESCRIPTION
|
||
|
* Leave WWOnline game
|
||
|
*
|
||
|
* INPUTS
|
||
|
* NONE
|
||
|
*
|
||
|
* RESULT
|
||
|
* NONE
|
||
|
*
|
||
|
******************************************************************************/
|
||
|
|
||
|
void WolGameModeClass::Leave_Game(void)
|
||
|
{
|
||
|
WWDEBUG_SAY(("WolGameModeClass::Leave_Game\n"));
|
||
|
|
||
|
// Stop listening WOLSession notifications.
|
||
|
Observer<GameOptionsMessage>::StopObserving();
|
||
|
Observer<ChannelEvent>::StopObserving();
|
||
|
Observer<UserEvent>::StopObserving();
|
||
|
Observer<ServerError>::StopObserving();
|
||
|
Observer<ConnectionStatus>::StopObserving();
|
||
|
|
||
|
// Shutdown quickmatch
|
||
|
if (mQuickMatch) {
|
||
|
mQuickMatch->Release_Ref();
|
||
|
mQuickMatch = NULL;
|
||
|
}
|
||
|
|
||
|
// Leave the game channel.
|
||
|
if (mTheGame) {
|
||
|
WWASSERT(mWOLSession.IsValid());
|
||
|
RefPtr<WaitCondition> wait = mWOLSession->LeaveChannel();
|
||
|
WWASSERT(wait.IsValid());
|
||
|
DlgWOLWait::DoDialog(IDS_GAME_LEAVECHANNEL, wait);
|
||
|
}
|
||
|
|
||
|
mTheGame = NULL;
|
||
|
mGameID = 0;
|
||
|
mGameInProgress = false;
|
||
|
}
|
||
|
|
||
|
|
||
|
/******************************************************************************
|
||
|
*
|
||
|
* NAME
|
||
|
* WolGameModeClass::Start_Game
|
||
|
*
|
||
|
* DESCRIPTION
|
||
|
* Start of game processing. This is performed by both the host and clients
|
||
|
* at the begining of each game.
|
||
|
*
|
||
|
* INPUTS
|
||
|
* Game - Instance of game starting
|
||
|
*
|
||
|
* RESULT
|
||
|
* NONE
|
||
|
*
|
||
|
******************************************************************************/
|
||
|
|
||
|
void Get_Compact_Detail_String(StringClass& tmp);
|
||
|
|
||
|
void WolGameModeClass::Start_Game(cGameData* theGame)
|
||
|
{
|
||
|
WWDEBUG_SAY(("WolGameModeClass::Start_Game\n"));
|
||
|
|
||
|
// The game host (server) is responsible for obtaining the game ID
|
||
|
if (cNetwork::I_Am_Server()) {
|
||
|
WWASSERT(theGame == mTheGame && "Start_Game cGameData* mismatch");
|
||
|
|
||
|
// Re-evaluate the clans in this game.
|
||
|
Evaluate_Clans(theGame);
|
||
|
|
||
|
//-------------------------------------------------------------------------
|
||
|
// Update the channel settings for the new game.
|
||
|
//-------------------------------------------------------------------------
|
||
|
RefPtr<ChannelData> channel = mWOLSession->GetCurrentChannel();
|
||
|
WWASSERT(channel.IsValid());
|
||
|
Update_Channel_Settings(theGame, channel);
|
||
|
|
||
|
// Send the chat server the new channel settings.
|
||
|
mWOLSession->SendChannelExtraInfo();
|
||
|
mWOLSession->SendChannelTopic();
|
||
|
|
||
|
if (mQuickMatch) {
|
||
|
const char* exInfo = channel->GetExtraInfo();
|
||
|
const char* topic = channel->GetTopic();
|
||
|
mQuickMatch->SendServerInfo(exInfo, topic);
|
||
|
}
|
||
|
|
||
|
// Reset timer to send server information for quickmatch
|
||
|
mSendServerInfoTime = (TIMEGETTIME() + (120 * 1000));
|
||
|
|
||
|
//-------------------------------------------------------------------------
|
||
|
// Get WWOnline game id for this game.
|
||
|
//-------------------------------------------------------------------------
|
||
|
const WideStringClass& name = theGame->Get_Owner();
|
||
|
|
||
|
UserList players;
|
||
|
RefPtr<UserData> user = mWOLSession->FindUser(name);
|
||
|
players.push_back(user);
|
||
|
|
||
|
RefPtr<WaitCondition> wait = GameStartWait::Create(players, &Game_Start_Timeout_Callback);
|
||
|
WWASSERT(wait.IsValid());
|
||
|
|
||
|
Observer<GameStartEvent>::NotifyMe(*mWOLSession);
|
||
|
DlgWOLWait::DoDialog(TRANSLATE (IDS_MENU_STARTING_WOL_GAME), wait, NULL, 0, mQuietMode ? 0xffffffff : 0);
|
||
|
|
||
|
if (The_Game() && The_Game()->IsDedicated.Is_True()) {
|
||
|
mConnected = true;
|
||
|
mLastPatchCheckTime = TIMEGETTIME();
|
||
|
mStartQuitProcessTime = 0;
|
||
|
mMonitorConnection = true;
|
||
|
Observer<ServerError>::NotifyMe(*mWOLSession);
|
||
|
Observer<ConnectionStatus>::NotifyMe(*mWOLSession);
|
||
|
}
|
||
|
} else {
|
||
|
mTheGame = theGame;
|
||
|
}
|
||
|
|
||
|
// Prevent the page dialog from showing while we are playing the game.
|
||
|
// We will handle the displaying of pages and invitations within the game
|
||
|
// messaging system.
|
||
|
mWOLBuddyMgr->HidePagedDialog();
|
||
|
Observer<WOLPagedEvent>::NotifyMe(*mWOLBuddyMgr);
|
||
|
|
||
|
// Listen to events from WOLSession
|
||
|
Observer<ChannelEvent>::NotifyMe(*mWOLSession);
|
||
|
Observer<UserEvent>::NotifyMe(*mWOLSession);
|
||
|
|
||
|
mGameInProgress = true;
|
||
|
}
|
||
|
|
||
|
|
||
|
/******************************************************************************
|
||
|
*
|
||
|
* NAME
|
||
|
* WolGameModeClass::End_Game
|
||
|
*
|
||
|
* DESCRIPTION
|
||
|
* Do end of game processing.
|
||
|
*
|
||
|
* INPUTS
|
||
|
* NONE
|
||
|
*
|
||
|
* RESULT
|
||
|
* NONE
|
||
|
*
|
||
|
******************************************************************************/
|
||
|
|
||
|
void WolGameModeClass::End_Game(void)
|
||
|
{
|
||
|
if (mGameInProgress) {
|
||
|
WWDEBUG_SAY(("WolGameModeClass::End_Game\n"));
|
||
|
|
||
|
// The server sends the end of game results
|
||
|
if (mTheGame) {
|
||
|
if (cNetwork::I_Am_Server()) {
|
||
|
SendGameResults(mGameID, mTheGame, cPlayerManager::Get_Player_Object_List());
|
||
|
mWOLSession->GetChatObject()->RequestGameEnd();
|
||
|
|
||
|
//
|
||
|
// Re-read the ban list.
|
||
|
//
|
||
|
KickNameList.Delete_All();
|
||
|
KickIPList.Delete_All();
|
||
|
Read_Kick_List();
|
||
|
|
||
|
} else {
|
||
|
#ifdef BETACLIENT
|
||
|
// Jani do stuff here (send client system information string)
|
||
|
StringClass info(255, true);
|
||
|
info = "SYSINFO:";
|
||
|
info += CPUDetectClass::Get_Compact_Log();
|
||
|
info += DX8Wrapper::Get_Current_Caps()->Get_Compact_Log();
|
||
|
|
||
|
StringClass tmp(255,true);
|
||
|
Get_Compact_Detail_String(tmp);
|
||
|
info += tmp;
|
||
|
|
||
|
PlayerInfoLog::Get_Compact_Log(tmp);
|
||
|
info += tmp;
|
||
|
|
||
|
SystemInfoLog::Get_Compact_Log(tmp);
|
||
|
info += tmp;
|
||
|
|
||
|
BandwidthCheckerClass::Get_Compact_Log(tmp);
|
||
|
info += tmp;
|
||
|
|
||
|
WOLNATInterface.Get_Compact_Log(tmp);
|
||
|
info += tmp;
|
||
|
|
||
|
WWDEBUG_SAY(("Sending compact log: %s\n", info.Peek_Buffer()));
|
||
|
|
||
|
mWOLSession->SendPrivateGameOptions(mTheGame->Get_Owner(), info);
|
||
|
#endif // BETACLIENT
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Allow the page dialog to show while we are no longer playing the game.
|
||
|
Observer<WOLPagedEvent>::StopObserving();
|
||
|
mWOLBuddyMgr->ShowPagedDialog();
|
||
|
|
||
|
mGameID = 0;
|
||
|
mGameInProgress = false;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
/***********************************************************************************************
|
||
|
* WolGameModeClass::Post_Game_Check -- Call when game is about to cycle. *
|
||
|
* *
|
||
|
* *
|
||
|
* *
|
||
|
* INPUT: Nothing *
|
||
|
* *
|
||
|
* OUTPUT: True if cycle should be aborted *
|
||
|
* *
|
||
|
* WARNINGS: None *
|
||
|
* *
|
||
|
* HISTORY: *
|
||
|
* 11/7/2001 6:07PM ST : Created *
|
||
|
*=============================================================================================*/
|
||
|
bool WolGameModeClass::Post_Game_Check(void)
|
||
|
{
|
||
|
bool retval = false;
|
||
|
|
||
|
if (mMonitorConnection && !mConnected) {
|
||
|
Quit_And_Restart();
|
||
|
retval = true;
|
||
|
}
|
||
|
|
||
|
mMonitorConnection = false;
|
||
|
return(retval);
|
||
|
}
|
||
|
|
||
|
|
||
|
/******************************************************************************
|
||
|
*
|
||
|
* NAME
|
||
|
* WolGameModeClass::Accept_Actions
|
||
|
*
|
||
|
* DESCRIPTION
|
||
|
*
|
||
|
* INPUTS
|
||
|
* Game - Instance of game joining
|
||
|
*
|
||
|
* RESULT
|
||
|
* NONE
|
||
|
*
|
||
|
******************************************************************************/
|
||
|
|
||
|
void WolGameModeClass::Accept_Actions(void)
|
||
|
{
|
||
|
WWDEBUG_SAY(("WolGameModeClass::Accept_Actions\n"));
|
||
|
}
|
||
|
|
||
|
|
||
|
/******************************************************************************
|
||
|
*
|
||
|
* NAME
|
||
|
* WolGameModeClass::Refusal_Actions
|
||
|
*
|
||
|
* DESCRIPTION
|
||
|
*
|
||
|
* INPUTS
|
||
|
* Game - Instance of game joining
|
||
|
*
|
||
|
* RESULT
|
||
|
* NONE
|
||
|
*
|
||
|
******************************************************************************/
|
||
|
|
||
|
void WolGameModeClass::Refusal_Actions(void)
|
||
|
{
|
||
|
WWDEBUG_SAY(("WolGameModeClass::Refusal_Actions\n"));
|
||
|
|
||
|
// If the client's request to join the game was refused then we need to make
|
||
|
// sure we leave the host's channel.
|
||
|
RefPtr<WaitCondition> wait = mWOLSession->LeaveChannel();
|
||
|
DlgWOLWait::DoDialog(IDS_GAME_LEAVECHANNEL, wait);
|
||
|
}
|
||
|
|
||
|
|
||
|
/******************************************************************************
|
||
|
*
|
||
|
* NAME
|
||
|
* WolGameModeClass::Evaluate_Clans
|
||
|
*
|
||
|
* DESCRIPTION
|
||
|
*
|
||
|
* INPUTS
|
||
|
* Game - Instance of game.
|
||
|
*
|
||
|
* RESULT
|
||
|
* NONE
|
||
|
*
|
||
|
******************************************************************************/
|
||
|
|
||
|
void WolGameModeClass::Evaluate_Clans(cGameData* theGame)
|
||
|
{
|
||
|
if (theGame && cNetwork::I_Am_Server()) {
|
||
|
theGame->Clear_Clans();
|
||
|
|
||
|
if (theGame->IsClanGame.Is_True()) {
|
||
|
WWDEBUG_SAY(("CLANS: Evaluating clan assignments\n"));
|
||
|
|
||
|
// If the host is a member of a clan then his clan takes a slot
|
||
|
RefPtr<UserData> host = mWOLSession->GetCurrentUser();
|
||
|
|
||
|
if (host.IsValid()) {
|
||
|
unsigned long hostClanID = host->GetSquadID();
|
||
|
theGame->Set_Clan(0, hostClanID);
|
||
|
|
||
|
WWDEBUG_SAY(("CLANS: Assigning slot 0 to '%S' (host) clan #%lu\n", (const WCHAR*)host->GetName(), hostClanID));
|
||
|
}
|
||
|
|
||
|
// Determine which clans are in the game.
|
||
|
const UserList& userList = mWOLSession->GetUserList();
|
||
|
const unsigned int count = userList.size();
|
||
|
|
||
|
for (unsigned int index = 0; index < count; ++index) {
|
||
|
const RefPtr<UserData>& user = userList[index];
|
||
|
WWASSERT(user.IsValid());
|
||
|
|
||
|
unsigned long userClanID = user->GetSquadID();
|
||
|
|
||
|
if (userClanID != 0) {
|
||
|
|
||
|
// If the clan is not already assigned then assign this clan to the next slot.
|
||
|
if (!theGame->Is_Clan_Competing(userClanID)) {
|
||
|
int slot = theGame->Find_Free_Clan_Slot();
|
||
|
WWASSERT(slot != -1 && "More clans in game than slots available");
|
||
|
|
||
|
if (slot != -1) {
|
||
|
WWDEBUG_SAY(("CLANS: Assigning slot %d to clan #%lu\n", slot, userClanID));
|
||
|
theGame->Set_Clan(slot, userClanID);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Force server information to be resent.
|
||
|
mSendServerInfoTime = 0;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
/******************************************************************************
|
||
|
*
|
||
|
* NAME
|
||
|
* WolGameModeClass::Update_Channel_Settings
|
||
|
*
|
||
|
* DESCRIPTION
|
||
|
*
|
||
|
* INPUTS
|
||
|
* NONE
|
||
|
*
|
||
|
* RESULT
|
||
|
* NONE
|
||
|
*
|
||
|
******************************************************************************/
|
||
|
|
||
|
void WolGameModeClass::Update_Channel_Settings(cGameData* theGame, const RefPtr<ChannelData>& channel)
|
||
|
{
|
||
|
WWASSERT(theGame != NULL);
|
||
|
WWASSERT(channel.IsValid());
|
||
|
|
||
|
if (theGame && channel.IsValid()) {
|
||
|
WOLGameInfo gameInfo(*theGame);
|
||
|
gameInfo.ExportToChannel(channel);
|
||
|
|
||
|
// Quickmatch settings are appended to the channel topic
|
||
|
if (theGame->Is_QuickMatch_Server()) {
|
||
|
//---------------------------------------------------------------------------
|
||
|
// Get average FPS of game (Capped at 255 fps)
|
||
|
//---------------------------------------------------------------------------
|
||
|
unsigned long fps = TimeManager::Get_Average_Frame_Rate();
|
||
|
fps = min<unsigned long>(fps, 255);
|
||
|
|
||
|
int numPlayers = theGame->Get_Current_Players();
|
||
|
|
||
|
int avgPing = cPlayerManager::Get_Average_Ping();
|
||
|
avgPing = min<int>(avgPing, UCHAR_MAX);
|
||
|
|
||
|
unsigned short avgPoints = cPlayerManager::Get_Average_WOL_Points();
|
||
|
|
||
|
int avgPlayed = cPlayerManager::Get_Average_Games_Played();
|
||
|
avgPlayed = min<int>(avgPlayed, USHRT_MAX);
|
||
|
|
||
|
// Quickmatch settings format is: |fps,mode,avg_ping,avg_rank,num_players
|
||
|
const char* topic = channel->GetTopic();
|
||
|
|
||
|
char newTopic[81];
|
||
|
sprintf(newTopic, "%s|%02lx%02x%04x%04x%c", topic, fps, avgPing, avgPoints,
|
||
|
avgPlayed, (32 + numPlayers));
|
||
|
|
||
|
channel->SetTopic(newTopic);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
/******************************************************************************
|
||
|
*
|
||
|
* NAME
|
||
|
* WolGameModeClass::Init_WOL_Player
|
||
|
*
|
||
|
* DESCRIPTION
|
||
|
*
|
||
|
* INPUTS
|
||
|
* Player - Set players WOL settings.
|
||
|
*
|
||
|
* RESULT
|
||
|
* NONE
|
||
|
*
|
||
|
******************************************************************************/
|
||
|
|
||
|
void WolGameModeClass::Init_WOL_Player(cPlayer* player)
|
||
|
{
|
||
|
if (player) {
|
||
|
RefPtr<UserData> user = mWOLSession->FindUser(player->Get_Name());
|
||
|
|
||
|
if (user.IsValid()) {
|
||
|
RefPtr<LadderData> ladder = user->GetTeamLadder();
|
||
|
|
||
|
if (ladder.IsValid()) {
|
||
|
player->Set_WOL_Points(ladder->GetPoints());
|
||
|
player->Set_Wol_Rank(ladder->GetRung());
|
||
|
player->Set_Num_Wol_Games(ladder->GetReserved2());
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Ladder points start at 10000 and vary up or down depending on the players
|
||
|
// performance.
|
||
|
player->Set_WOL_Points(10000);
|
||
|
|
||
|
// Ranking of -1 indicates that the player doesn't have a rank.
|
||
|
player->Set_Wol_Rank(-1);
|
||
|
|
||
|
player->Set_Num_Wol_Games(0);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
/******************************************************************************
|
||
|
*
|
||
|
* NAME
|
||
|
* WolGameModeClass::Get_WOL_User_Data
|
||
|
*
|
||
|
* DESCRIPTION
|
||
|
*
|
||
|
* INPUTS
|
||
|
* Player - Name of player to find.
|
||
|
*
|
||
|
* RESULT
|
||
|
* User - WWOnline user data
|
||
|
*
|
||
|
******************************************************************************/
|
||
|
|
||
|
RefPtr<UserData> WolGameModeClass::Get_WOL_User_Data(const wchar_t* name)
|
||
|
{
|
||
|
return mWOLSession->FindUser(name);
|
||
|
}
|
||
|
|
||
|
|
||
|
/******************************************************************************
|
||
|
*
|
||
|
* NAME
|
||
|
* WolGameModeClass::Page_WOL_User
|
||
|
*
|
||
|
* DESCRIPTION
|
||
|
*
|
||
|
* INPUTS
|
||
|
* User - Name of user to page.
|
||
|
* Message - Message to send to user.
|
||
|
*
|
||
|
* RESULT
|
||
|
* NONE
|
||
|
*
|
||
|
******************************************************************************/
|
||
|
|
||
|
void WolGameModeClass::Page_WOL_User(const wchar_t* name, const wchar_t* msg)
|
||
|
{
|
||
|
if (name && (wcslen(name) > 0) && msg && (wcslen(msg) > 0)) {
|
||
|
mWOLSession->PageUser(name, msg);
|
||
|
|
||
|
WideStringClass message(0, true);
|
||
|
message.Format(TRANSLATE(IDS_GAME_PAGING), name, msg);
|
||
|
CombatManager::Get_Message_Window()->Add_Message(message, COLOR_CONSOLE_TEXT);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
/******************************************************************************
|
||
|
*
|
||
|
* NAME
|
||
|
* WolGameModeClass::Reply_Last_Page
|
||
|
*
|
||
|
* DESCRIPTION
|
||
|
* Send a reply message to the last user who paged.
|
||
|
*
|
||
|
* INPUTS
|
||
|
*
|
||
|
* RESULT
|
||
|
* NONE
|
||
|
*
|
||
|
******************************************************************************/
|
||
|
|
||
|
void WolGameModeClass::Reply_Last_Page(const wchar_t* msg)
|
||
|
{
|
||
|
if (msg && (wcslen(msg) > 0)) {
|
||
|
const WCHAR* pager = mWOLBuddyMgr->GetLastPagersName();
|
||
|
|
||
|
if (pager && (wcslen(pager) > 0)) {
|
||
|
mWOLBuddyMgr->PageUser(pager, msg);
|
||
|
|
||
|
WideStringClass message(0, true);
|
||
|
message.Format(TRANSLATE(IDS_GAME_PAGE_REPLYING), pager, msg);
|
||
|
CombatManager::Get_Message_Window()->Add_Message(message, COLOR_CONSOLE_TEXT);
|
||
|
} else {
|
||
|
CombatManager::Get_Message_Window()->Add_Message(TRANSLATE(IDS_GAME_PAGE_REPLY_CANT), COLOR_CONSOLE_TEXT);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
/******************************************************************************
|
||
|
*
|
||
|
* NAME
|
||
|
* WolGameModeClass::Locate_WOL_User
|
||
|
*
|
||
|
* DESCRIPTION
|
||
|
*
|
||
|
* INPUTS
|
||
|
* User - Name of user to locate.
|
||
|
*
|
||
|
* RESULT
|
||
|
* NONE
|
||
|
*
|
||
|
******************************************************************************/
|
||
|
|
||
|
void WolGameModeClass::Locate_WOL_User(const wchar_t* name)
|
||
|
{
|
||
|
if (name && wcslen(name) > 0) {
|
||
|
mWOLSession->RequestLocateUser(name);
|
||
|
|
||
|
WideStringClass message(0, true);
|
||
|
message.Format(TRANSLATE(IDS_GAME_LOCATING_USER), name);
|
||
|
CombatManager::Get_Message_Window()->Add_Message(message, COLOR_CONSOLE_TEXT);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
/******************************************************************************
|
||
|
*
|
||
|
* NAME
|
||
|
* WolGameModeClass::Invite_WOL_User
|
||
|
*
|
||
|
* DESCRIPTION
|
||
|
*
|
||
|
* INPUTS
|
||
|
* User - Name of user to locate.
|
||
|
*
|
||
|
* RESULT
|
||
|
* NONE
|
||
|
*
|
||
|
******************************************************************************/
|
||
|
|
||
|
void WolGameModeClass::Invite_WOL_User(const wchar_t* name, const wchar_t* msg)
|
||
|
{
|
||
|
if (name && wcslen(name)) {
|
||
|
cPlayer* player = cPlayerManager::Find_Player(name);
|
||
|
|
||
|
if (player) {
|
||
|
WideStringClass message(0, true);
|
||
|
message.Format(TRANSLATE (IDS_MENU_ALREADY_IN_GAME), name);
|
||
|
CombatManager::Get_Message_Window()->Add_Message(message, COLOR_INVITE_TEXT);
|
||
|
WWAudioClass::Get_Instance()->Create_Instant_Sound("Private_Message", Matrix3D(1));
|
||
|
} else {
|
||
|
mWOLBuddyMgr->InviteUser(name, msg);
|
||
|
|
||
|
WideStringClass message(0, true);
|
||
|
message.Format(TRANSLATE(IDS_GAME_INVITING_USER), name);
|
||
|
CombatManager::Get_Message_Window()->Add_Message(message, COLOR_CONSOLE_TEXT);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
/******************************************************************************
|
||
|
*
|
||
|
* NAME
|
||
|
* WolGameModeClass::Join_WOL_User
|
||
|
*
|
||
|
* DESCRIPTION
|
||
|
*
|
||
|
* INPUTS
|
||
|
* User - Name of user to join.
|
||
|
*
|
||
|
* RESULT
|
||
|
* NONE
|
||
|
*
|
||
|
******************************************************************************/
|
||
|
|
||
|
void WolGameModeClass::Join_WOL_User(const wchar_t* name)
|
||
|
{
|
||
|
// If the name is valid and it is not me
|
||
|
if (name && wcslen(name) && !mWOLSession->IsCurrentUser(name)) {
|
||
|
cPlayer* player = cPlayerManager::Find_Player(name);
|
||
|
|
||
|
if (player) {
|
||
|
WideStringClass message(0, true);
|
||
|
message.Format(TRANSLATE(IDS_MENU_YOURE_ALREADY_IN_GAME), name);
|
||
|
CombatManager::Get_Message_Window()->Add_Message(message, COLOR_INVITE_TEXT);
|
||
|
WWAudioClass::Get_Instance()->Create_Instant_Sound("Private_Message", Matrix3D(1));
|
||
|
} else {
|
||
|
RefPtr<UserData> user = UserData::Create(name);
|
||
|
mWOLBuddyMgr->JoinUser(user);
|
||
|
|
||
|
WideStringClass message(0, true);
|
||
|
message.Format(TRANSLATE(IDS_GAME_JOINING_USER), name);
|
||
|
CombatManager::Get_Message_Window()->Add_Message(message, COLOR_CONSOLE_TEXT);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
/******************************************************************************
|
||
|
*
|
||
|
* NAME
|
||
|
* WolGameModeClass::Kick_Player
|
||
|
*
|
||
|
* DESCRIPTION
|
||
|
* Kick a player from the game. Players kicked from a game are also banned
|
||
|
* from rejoining that game. Note: This is only allowed by game server hosts.
|
||
|
*
|
||
|
* INPUTS
|
||
|
* Player - Name of player to kick from the game.
|
||
|
*
|
||
|
* RESULT
|
||
|
* NONE
|
||
|
*
|
||
|
******************************************************************************/
|
||
|
|
||
|
bool WolGameModeClass::Kick_Player(const wchar_t* name)
|
||
|
{
|
||
|
// If the name is not NULL. we are the server and the player to kick is
|
||
|
// not ourself then proceed with the kick.
|
||
|
if (name && (wcslen(name) > 0)) {
|
||
|
if (cNetwork::I_Am_Server() && !mWOLSession->IsCurrentUser(name)) {
|
||
|
mWOLSession->KickUser(name);
|
||
|
mWOLSession->BanUser(name, true);
|
||
|
|
||
|
// Disconnect the player from the server
|
||
|
WideStringClass playername(0, true);
|
||
|
playername = name;
|
||
|
|
||
|
cPlayer* player = cPlayerManager::Find_Player(playername);
|
||
|
|
||
|
if (player && player->Is_Human()) {
|
||
|
WideStringClass message(0, true);
|
||
|
message.Format(TRANSLATE(IDS_GAME_KICKING_USER), name);
|
||
|
CombatManager::Get_Message_Window()->Add_Message(message, COLOR_CONSOLE_TEXT);
|
||
|
|
||
|
int playerID = player->Get_Id();
|
||
|
cNetwork::Server_Kill_Connection(playerID);
|
||
|
cNetwork::Cleanup_After_Client(playerID);
|
||
|
return(true);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
WideStringClass message(0, true);
|
||
|
message.Format(TRANSLATE(IDS_GAME_KICKING_NOT_ALLOWED), name);
|
||
|
CombatManager::Get_Message_Window()->Add_Message(message, COLOR_CONSOLE_TEXT);
|
||
|
}
|
||
|
return(false);
|
||
|
}
|
||
|
|
||
|
|
||
|
/***********************************************************************************************
|
||
|
* WolGameModeClass::Ban_Player -- Add player to ban list *
|
||
|
* *
|
||
|
* *
|
||
|
* *
|
||
|
* INPUT: Player name *
|
||
|
* *
|
||
|
* OUTPUT: Nothing *
|
||
|
* *
|
||
|
* WARNINGS: None *
|
||
|
* *
|
||
|
* HISTORY: *
|
||
|
* 8/8/2002 4:33PM ST : Created *
|
||
|
*=============================================================================================*/
|
||
|
void WolGameModeClass::Ban_Player(const wchar_t* name, unsigned long ip)
|
||
|
{
|
||
|
// If the name is not NULL. we are the server and the player to kick is
|
||
|
// not ourself then proceed with the kick.
|
||
|
if (name && cNetwork::I_Am_Server() && !mWOLSession->IsCurrentUser(name)) {
|
||
|
|
||
|
Kick_Player(name);
|
||
|
WideStringClass playername(0, true);
|
||
|
playername = name;
|
||
|
StringClass pn;
|
||
|
playername.Convert_To(pn);
|
||
|
|
||
|
if (!Is_Banned(pn, ip)) {
|
||
|
|
||
|
KickNameList.Add(pn);
|
||
|
KickIPList.Add(ip);
|
||
|
char ipstr[128];
|
||
|
pn += ":";
|
||
|
unsigned char *ip_ptr = (unsigned char*)&ip;
|
||
|
sprintf(ipstr, "%u.%u.%u.%u\n", (unsigned int)ip_ptr[0], (unsigned int)ip_ptr[1], (unsigned int)ip_ptr[2], (unsigned int)ip_ptr[3]);
|
||
|
pn += ipstr;
|
||
|
|
||
|
FILE *kick_list = fopen("wolbanlist.txt", "at");
|
||
|
if (kick_list != NULL) {
|
||
|
fwrite(pn.Peek_Buffer(), 1, pn.Get_Length(), kick_list);
|
||
|
fclose(kick_list);
|
||
|
}
|
||
|
DynamicVectorClass<unsigned long> KickIPList;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
/***********************************************************************************************
|
||
|
* WolGameModeClass::Auto_Kick -- Kick any banned users from the game *
|
||
|
* *
|
||
|
* *
|
||
|
* *
|
||
|
* INPUT: Nothing *
|
||
|
* *
|
||
|
* OUTPUT: Nothing *
|
||
|
* *
|
||
|
* WARNINGS: None *
|
||
|
* *
|
||
|
* HISTORY: *
|
||
|
* 8/8/2002 9:24PM ST : Created *
|
||
|
*=============================================================================================*/
|
||
|
void WolGameModeClass::Auto_Kick(void)
|
||
|
{
|
||
|
if (cNetwork::I_Am_Server()) {
|
||
|
cPlayer *player = NULL;
|
||
|
for (SLNode<cPlayer> *player_node = cPlayerManager::Get_Player_Object_List()->Head() ; player_node != NULL; player_node = player_node->Next()) {
|
||
|
player = player_node->Data();
|
||
|
if (player->Is_Active()) {
|
||
|
if (!mWOLSession->IsCurrentUser(player->Get_Name())) {
|
||
|
StringClass player_name(player->Get_Name());
|
||
|
if (Is_Banned(player_name, player->Get_Ip_Address())) {
|
||
|
Kick_Player(player->Get_Name());
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
/***********************************************************************************************
|
||
|
* WolGameModeClass::Is_Banned -- Is this player banned from our WOL server? *
|
||
|
* *
|
||
|
* *
|
||
|
* *
|
||
|
* INPUT: Player name *
|
||
|
* IP Address *
|
||
|
* *
|
||
|
* OUTPUT: Nothing *
|
||
|
* *
|
||
|
* WARNINGS: None *
|
||
|
* *
|
||
|
* HISTORY: *
|
||
|
* 8/8/2002 9:14PM ST : Created *
|
||
|
*=============================================================================================*/
|
||
|
bool WolGameModeClass::Is_Banned(const char *player_name, unsigned long ip)
|
||
|
{
|
||
|
int i;
|
||
|
|
||
|
if (KickNameList.Count() == 0) {
|
||
|
Read_Kick_List();
|
||
|
}
|
||
|
|
||
|
for (i=0 ; i<KickNameList.Count() ; i++) {
|
||
|
if (stricmp(player_name, KickNameList[i].Peek_Buffer()) == 0) {
|
||
|
return(true);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
for (i=0 ; i<KickIPList.Count() ; i++) {
|
||
|
if (KickIPList[i] == ip) {
|
||
|
return(true);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return(false);
|
||
|
}
|
||
|
|
||
|
|
||
|
/***********************************************************************************************
|
||
|
* WolGameModeClass::Read_Kick_List -- Read the list of autokick players *
|
||
|
* *
|
||
|
* *
|
||
|
* *
|
||
|
* INPUT: Nothing *
|
||
|
* *
|
||
|
* OUTPUT: Nothing *
|
||
|
* *
|
||
|
* WARNINGS: None *
|
||
|
* *
|
||
|
* HISTORY: *
|
||
|
* 8/8/2002 9:14PM ST : Created *
|
||
|
*=============================================================================================*/
|
||
|
void WolGameModeClass::Read_Kick_List(void)
|
||
|
{
|
||
|
FILE *kick_list = fopen("wolbanlist.txt", "rt");
|
||
|
if (kick_list) {
|
||
|
|
||
|
int i = 0;
|
||
|
bool eof = false;
|
||
|
char temp[256];
|
||
|
|
||
|
while (!eof) {
|
||
|
for (i=0 ; i<256 ; i++) {
|
||
|
if (fread(&temp[i], 1, 1, kick_list) == 0) {
|
||
|
eof = true;
|
||
|
break;
|
||
|
}
|
||
|
if (temp[i] == '\n') {
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
if (i > 10) {
|
||
|
temp[i + 1] = 0;
|
||
|
char *colon_ptr = strchr(temp, ':');
|
||
|
if (colon_ptr) {
|
||
|
*colon_ptr = 0;
|
||
|
KickNameList.Add(temp);
|
||
|
unsigned long ip = inet_addr(colon_ptr + 1);
|
||
|
KickIPList.Add(ip);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
fclose(kick_list);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
/******************************************************************************
|
||
|
*
|
||
|
* NAME
|
||
|
* WolGameModeClass::HandleNotification(ChannelEvent)
|
||
|
*
|
||
|
* DESCRIPTION
|
||
|
*
|
||
|
* INPUTS
|
||
|
* Event -
|
||
|
*
|
||
|
* RESULT
|
||
|
* NONE
|
||
|
*
|
||
|
******************************************************************************/
|
||
|
|
||
|
void WolGameModeClass::HandleNotification(ChannelEvent& event)
|
||
|
{
|
||
|
// This user has been kicked from the game.
|
||
|
if (ChannelKicked == event.GetStatus()) {
|
||
|
WWDEBUG_SAY(("WolGameModeClass Player Kicked!\n"));
|
||
|
|
||
|
mGameInProgress = false;
|
||
|
|
||
|
GameInitMgrClass::End_Game();
|
||
|
GameInitMgrClass::Display_End_Game_Menu();
|
||
|
|
||
|
DlgMsgBox::DoDialog(TRANSLATE(IDS_MENU_SERVER_MESSAGE_TITLE), TRANSLATE (IDS_MENU_SERVER_KICKED_MESSAGE));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
/******************************************************************************
|
||
|
*
|
||
|
* NAME
|
||
|
* WolGameModeClass::HandleNotification(UserEvent)
|
||
|
*
|
||
|
* DESCRIPTION
|
||
|
*
|
||
|
* INPUTS
|
||
|
* Event -
|
||
|
*
|
||
|
* RESULT
|
||
|
* NONE
|
||
|
*
|
||
|
******************************************************************************/
|
||
|
|
||
|
void WolGameModeClass::HandleNotification(UserEvent& event)
|
||
|
{
|
||
|
switch (event.GetEvent()) {
|
||
|
// A user has been kicked from the game.
|
||
|
case UserEvent::Kicked: {
|
||
|
WideStringClass message(0, true);
|
||
|
message.Format(TRANSLATE(IDS_MENU_PLAYER_KICKED_MESSAGE), event.Subject()->GetName());
|
||
|
CombatManager::Get_Message_Window()->Add_Message(message, COLOR_PUBLIC_TEXT);
|
||
|
WWAudioClass::Get_Instance()->Create_Instant_Sound("Public_Message", Matrix3D(1));
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case UserEvent::Located: {
|
||
|
const RefPtr<UserData>& user = event.Subject();
|
||
|
|
||
|
// Get the description of the user's location
|
||
|
WideStringClass location(64, true);
|
||
|
WOLBuddyMgr::GetLocationDescription(user, location);
|
||
|
|
||
|
// Build a string containing the user's name
|
||
|
WideStringClass message(0, true);
|
||
|
message.Format(TRANSLATE(IDS_CHAT_LOCATEDUSER), user->GetName());
|
||
|
message += L" - ";
|
||
|
message += location;
|
||
|
CombatManager::Get_Message_Window()->Add_Message(message, COLOR_PRIVATE_TEXT);
|
||
|
WWAudioClass::Get_Instance()->Create_Instant_Sound("Private_Message", Matrix3D(1));
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case UserEvent::LadderInfo:
|
||
|
if (mTheGame) {
|
||
|
const RefPtr<UserData>& user = event.Subject();
|
||
|
cPlayer* player = cPlayerManager::Find_Player(user->GetName());
|
||
|
Init_WOL_Player(player);
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case UserEvent::Join:
|
||
|
if (mTheGame && cNetwork::I_Am_Server()) {
|
||
|
const RefPtr<UserData>& user = event.Subject();
|
||
|
bool requestDetails = true;
|
||
|
|
||
|
// If the user is joining a clan game.
|
||
|
if (mTheGame->IsClanGame.Is_True()) {
|
||
|
WWDEBUG_SAY(("CLANS: User join clan assignment\n"));
|
||
|
|
||
|
unsigned long userClanID = user->GetSquadID();
|
||
|
WWASSERT(userClanID != 0 && "User not in a clan");
|
||
|
|
||
|
// If the game is open to a new clan then assign the user to a
|
||
|
// participating clan or a new slot.
|
||
|
if (mTheGame->Is_Clan_Game_Open()) {
|
||
|
|
||
|
// If the user is not a member of a participating clan then assign
|
||
|
// the next free slot to this users clan.
|
||
|
if (!mTheGame->Is_Clan_Competing(userClanID)) {
|
||
|
int slot = mTheGame->Find_Free_Clan_Slot();
|
||
|
|
||
|
if (slot != -1) {
|
||
|
WWDEBUG_SAY(("CLANS: Slot %d filled by '%S' Clan #%lu\n", slot,
|
||
|
(const WCHAR*)user->GetName(), userClanID));
|
||
|
|
||
|
mTheGame->Set_Clan(slot, userClanID);
|
||
|
}
|
||
|
|
||
|
// Send the chat server the new channel settings.
|
||
|
RefPtr<ChannelData> channel = mWOLSession->GetCurrentChannel();
|
||
|
Update_Channel_Settings(mTheGame, channel);
|
||
|
mWOLSession->SendChannelExtraInfo();
|
||
|
}
|
||
|
} else {
|
||
|
// If the game is closed and the user is not a member of one of the
|
||
|
// competing clans then kick him.
|
||
|
if (!mTheGame->Is_Clan_Competing(userClanID)) {
|
||
|
WWDEBUG_SAY(("CLANS: Game closed. Kicking user '%S'\n",
|
||
|
(const WCHAR*)user->GetName()));
|
||
|
|
||
|
mWOLSession->KickUser(user->GetName());
|
||
|
requestDetails = false;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (requestDetails) {
|
||
|
mWOLSession->RequestUserDetails(user, REQUEST_LADDERINFO|REQUEST_SQUADINFO);
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case UserEvent::Leave:
|
||
|
if (mTheGame && cNetwork::I_Am_Server()) {
|
||
|
if (mTheGame->IsClanGame.Is_True()) {
|
||
|
WWDEBUG_SAY(("CLANS: User leave re-evaluate clan assignment\n"));
|
||
|
Evaluate_Clans(mTheGame);
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
/******************************************************************************
|
||
|
*
|
||
|
* NAME
|
||
|
* WolGameModeClass::HandleNotification(DlgWOLWaitEvent)
|
||
|
*
|
||
|
* DESCRIPTION
|
||
|
* Response to completion of game channel creation.
|
||
|
*
|
||
|
* INPUTS
|
||
|
* Event -
|
||
|
*
|
||
|
* RESULT
|
||
|
* NONE
|
||
|
*
|
||
|
******************************************************************************/
|
||
|
|
||
|
void WolGameModeClass::HandleNotification(DlgWOLWaitEvent& wolEvent)
|
||
|
{
|
||
|
if (wolEvent.Result() == WaitCondition::ConditionMet) {
|
||
|
WWASSERT(mTheGame != NULL);
|
||
|
|
||
|
mChannelCreateSuccessFlag = true;
|
||
|
|
||
|
// Startup quickmatch if we are serving quickmatch games.
|
||
|
if (mTheGame->Is_QuickMatch_Server()) {
|
||
|
mQuickMatch = WOLQuickMatch::Create();
|
||
|
WWASSERT(mQuickMatch);
|
||
|
}
|
||
|
|
||
|
mSendServerInfoTime = 0;
|
||
|
|
||
|
// Start listening to Game Options messages from clients
|
||
|
Observer<GameOptionsMessage>::NotifyMe(*mWOLSession);
|
||
|
|
||
|
// Listen to events from WOLSession
|
||
|
Observer<ChannelEvent>::NotifyMe(*mWOLSession);
|
||
|
Observer<UserEvent>::NotifyMe(*mWOLSession);
|
||
|
} else {
|
||
|
if (!mQuietMode) {
|
||
|
DlgMsgBox::DoDialog(TRANSLATE (IDS_MENU_FAILED_TO_CREATE_GAME), wolEvent.Subject()->GetResultText());
|
||
|
}
|
||
|
}
|
||
|
|
||
|
Signaler<WolGameModeClass>::SendSignal(*this);
|
||
|
}
|
||
|
|
||
|
|
||
|
/******************************************************************************
|
||
|
*
|
||
|
* NAME
|
||
|
* WolGameModeClass::HandleNotification(GameStartEvent)
|
||
|
*
|
||
|
* DESCRIPTION
|
||
|
* Handle game start acknowledgement.
|
||
|
*
|
||
|
* INPUTS
|
||
|
*
|
||
|
* RESULT
|
||
|
* NONE
|
||
|
*
|
||
|
******************************************************************************/
|
||
|
|
||
|
void WolGameModeClass::HandleNotification(GameStartEvent& start)
|
||
|
{
|
||
|
WWDEBUG_SAY(("GameStartEvent received\n"));
|
||
|
mGameID = 0;
|
||
|
|
||
|
if (start.IsSuccess()) {
|
||
|
mGameID = start.GetGameID();
|
||
|
WWDEBUG_SAY(("GameID = %ld\n", mGameID));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
/******************************************************************************
|
||
|
*
|
||
|
* NAME
|
||
|
* WolGameModeClass::HandleNotification(GameOptionsMessage)
|
||
|
*
|
||
|
* DESCRIPTION
|
||
|
* Handle game options requests coming from other users.
|
||
|
*
|
||
|
* INPUTS
|
||
|
* OptionsMessage -
|
||
|
*
|
||
|
* RESULT
|
||
|
* NONE
|
||
|
*
|
||
|
******************************************************************************/
|
||
|
|
||
|
void WolGameModeClass::HandleNotification(GameOptionsMessage& message)
|
||
|
{
|
||
|
if (cNetwork::I_Am_Server() && mTheGame) {
|
||
|
const char* request = message.GetOptions();
|
||
|
|
||
|
// Request for game information?
|
||
|
if (strcmp("RGINFO", request) == 0) {
|
||
|
WideStringClass requestor(0, true);
|
||
|
requestor = message.GetSendersName();
|
||
|
|
||
|
//-----------------------------------------------------------------------
|
||
|
// Send game information
|
||
|
//-----------------------------------------------------------------------
|
||
|
unsigned long mapCRC = CRC_Stringi(mTheGame->Get_Map_Name());
|
||
|
float seconds = mTheGame->Get_Time_Remaining_Seconds();
|
||
|
|
||
|
// Game info sent as: MapCRC Seconds remaining
|
||
|
StringClass info(0, true);
|
||
|
info.Format("GINFO:%08lx %.4f", mapCRC, seconds);
|
||
|
|
||
|
WWDEBUG_SAY(("%S\n", info));
|
||
|
mWOLSession->SendPrivateGameOptions(requestor, info);
|
||
|
|
||
|
//-----------------------------------------------------------------------
|
||
|
// Send team information
|
||
|
//-----------------------------------------------------------------------
|
||
|
SList<cTeam>* teamList = cTeamManager::Get_Team_Object_List();
|
||
|
WWASSERT(teamList != NULL);
|
||
|
|
||
|
SLNode<cTeam>* teamNode = teamList->Head();
|
||
|
|
||
|
while (teamNode) {
|
||
|
cTeam* team = teamNode->Data();
|
||
|
WWASSERT(team != NULL);
|
||
|
|
||
|
int teamID = team->Get_Id();
|
||
|
int teamScore = team->Get_Score();
|
||
|
|
||
|
info.Format("TINFO:%d %d", teamID, teamScore);
|
||
|
|
||
|
WWDEBUG_SAY(("%S\n", info));
|
||
|
mWOLSession->SendPrivateGameOptions(requestor, info);
|
||
|
|
||
|
teamNode = teamNode->Next();
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------
|
||
|
// Send player information
|
||
|
//-----------------------------------------------------------------------
|
||
|
SList<cPlayer>* playerList = cPlayerManager::Get_Player_Object_List();
|
||
|
SLNode<cPlayer>* playerNode = playerList->Head();
|
||
|
|
||
|
while (playerNode) {
|
||
|
cPlayer* player = playerNode->Data();
|
||
|
|
||
|
if (player && player->Is_Active() && player->Is_Human()) {
|
||
|
const WideStringClass& name = player->Get_Name();
|
||
|
int type = player->Get_Player_Type();
|
||
|
int rung = player->Get_Rung();
|
||
|
int kills = player->Get_Kills();
|
||
|
int deaths = player->Get_Deaths();
|
||
|
int score = player->Get_Score();
|
||
|
|
||
|
// PINFO string format: Name fps,type,rank,kills,deaths
|
||
|
info.Format("PINFO:%S %d %d %d %d %d", (const WCHAR*)name, type, rung, kills, deaths, score);
|
||
|
|
||
|
mWOLSession->SendPrivateGameOptions(requestor, info);
|
||
|
}
|
||
|
|
||
|
playerNode = playerNode->Next();
|
||
|
}
|
||
|
} else {
|
||
|
// Write client system info to disk
|
||
|
const char* cmd = strstr(request, "SYSINFO:");
|
||
|
|
||
|
if (cmd == request) {
|
||
|
static int sysinfo_log_disabled=-1;
|
||
|
if (sysinfo_log_disabled==-1) { // Read from registry only once per run
|
||
|
RegistryClass registry( APPLICATION_SUB_KEY_NAME_DEBUG );
|
||
|
if ( registry.Is_Valid() ) {
|
||
|
sysinfo_log_disabled=registry.Get_Int( VALUE_NAME_DISABLE_SERVER_SYSINFO_COLLECTING, -1 );
|
||
|
// Write to registry to create the key if it didn't exist
|
||
|
if (sysinfo_log_disabled==-1) {
|
||
|
sysinfo_log_disabled=0;
|
||
|
registry.Set_Int( VALUE_NAME_DISABLE_SERVER_SYSINFO_COLLECTING, sysinfo_log_disabled);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
// Only copy the sysinfo if it isn't disabled in registry
|
||
|
if (sysinfo_log_disabled==0) {
|
||
|
const char* data = (request + strlen("SYSINFO:"));
|
||
|
int datalen=strlen(data);
|
||
|
if (!datalen) return;
|
||
|
StringClass tmp(0,true);
|
||
|
|
||
|
StringClass requestor(0, true);
|
||
|
requestor = message.GetSendersName();
|
||
|
|
||
|
StringClass datastring;
|
||
|
datastring=requestor;
|
||
|
datastring+="\t";
|
||
|
|
||
|
unsigned long versionminor,versionmajor;
|
||
|
Get_Version_Number(&versionmajor,&versionminor);
|
||
|
|
||
|
SYSTEMTIME time;
|
||
|
GetSystemTime(&time);
|
||
|
tmp.Format("%d/%d/%d %d:%d\t%d.%d\t",
|
||
|
time.wMonth,
|
||
|
time.wDay,
|
||
|
time.wYear,
|
||
|
time.wHour,
|
||
|
time.wMinute,
|
||
|
versionmajor,
|
||
|
versionminor);
|
||
|
datastring+=tmp;
|
||
|
|
||
|
datastring+=data;
|
||
|
datastring+="\r\n";
|
||
|
|
||
|
// Verify the sysinfo folder
|
||
|
StringClass dirname(0,true);
|
||
|
dirname.Format("sysinfo_%d",DebugManager::Get_Version_Number());
|
||
|
if (GetFileAttributes(dirname)==0xffffffff) {
|
||
|
if (!CreateDirectory(dirname,NULL)) {
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
StringClass filename(0,true);
|
||
|
filename=dirname;
|
||
|
filename+="\\";
|
||
|
tmp=requestor;
|
||
|
filename+=tmp;
|
||
|
filename+=".txt";
|
||
|
|
||
|
DWORD written;
|
||
|
HANDLE file;
|
||
|
file = CreateFile(filename, GENERIC_WRITE, 0, NULL, OPEN_ALWAYS,
|
||
|
FILE_ATTRIBUTE_NORMAL, NULL);
|
||
|
if (INVALID_HANDLE_VALUE != file) {
|
||
|
SetFilePointer(file, 0, NULL, FILE_END);
|
||
|
WriteFile(file, datastring, strlen(datastring), &written, NULL);
|
||
|
CloseHandle(file);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
/******************************************************************************
|
||
|
*
|
||
|
* NAME
|
||
|
* WolGameModeClass::HandleNotification(LadderInfoEvent)
|
||
|
*
|
||
|
* DESCRIPTION
|
||
|
*
|
||
|
* INPUTS
|
||
|
*
|
||
|
* RESULT
|
||
|
* NONE
|
||
|
*
|
||
|
******************************************************************************/
|
||
|
|
||
|
void WolGameModeClass::HandleNotification(LadderInfoEvent& ladderEvent)
|
||
|
{
|
||
|
if (ladderEvent.IsRanked()) {
|
||
|
LadderType type = ladderEvent.GetLadderType();
|
||
|
|
||
|
// If this is for the locale user and the ladder information is cached
|
||
|
// then update there profile with the latest ladder information.
|
||
|
if (LadderType_Team == type) {
|
||
|
WideStringClass name(64, true);
|
||
|
name = ladderEvent.GetReceivedName();
|
||
|
|
||
|
if (mWOLSession->IsCurrentUser(name)) {
|
||
|
LoginProfile* profile = LoginProfile::Get(name, false);
|
||
|
|
||
|
if (profile) {
|
||
|
WWDEBUG_SAY(("Updating team ladder info for %S\n", profile->GetName()));
|
||
|
const WOL::Ladder& wolLadder = ladderEvent.GetWOLLadder();
|
||
|
|
||
|
// Save the number of games played.
|
||
|
profile->SetGamesPlayed(wolLadder.reserved2);
|
||
|
|
||
|
// Save the ranking information
|
||
|
LoginProfile::Ranking rank;
|
||
|
rank.Wins = wolLadder.wins;
|
||
|
rank.Losses = wolLadder.losses;
|
||
|
rank.Deaths = wolLadder.reserved1;
|
||
|
rank.Kills = wolLadder.kills;
|
||
|
rank.Points = wolLadder.points;
|
||
|
rank.Rank = wolLadder.rung;
|
||
|
profile->SetRanking(LadderType_Team, rank);
|
||
|
|
||
|
profile->SaveSettings();
|
||
|
profile->Release_Ref();
|
||
|
}
|
||
|
}
|
||
|
} else if (LadderType_Clan == type) {
|
||
|
RefPtr<UserData> user = mWOLSession->GetCurrentUser();
|
||
|
|
||
|
if (user.IsValid()) {
|
||
|
RefPtr<SquadData> squad = user->GetSquad();
|
||
|
|
||
|
if (squad.IsValid() && (stricmp(squad->GetAbbr(), ladderEvent.GetReceivedName()) == 0)) {
|
||
|
LoginProfile* profile = LoginProfile::Get(user->GetName(), false);
|
||
|
|
||
|
if (profile) {
|
||
|
WWDEBUG_SAY(("Updating clan ladder info for %S\n", profile->GetName()));
|
||
|
const WOL::Ladder& wolLadder = ladderEvent.GetWOLLadder();
|
||
|
|
||
|
// Save the ranking information
|
||
|
LoginProfile::Ranking rank;
|
||
|
rank.Wins = wolLadder.wins;
|
||
|
rank.Losses = wolLadder.losses;
|
||
|
rank.Deaths = wolLadder.reserved1;
|
||
|
rank.Kills = wolLadder.kills;
|
||
|
rank.Points = wolLadder.points;
|
||
|
rank.Rank = wolLadder.rung;
|
||
|
profile->SetRanking(LadderType_Clan, rank);
|
||
|
|
||
|
profile->SaveSettings();
|
||
|
profile->Release_Ref();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
/***********************************************************************************************
|
||
|
* WolGameModeClass::HandleNotification -- Handle connection status notifications *
|
||
|
* *
|
||
|
* *
|
||
|
* *
|
||
|
* INPUT: Connection status *
|
||
|
* *
|
||
|
* OUTPUT: Nothing *
|
||
|
* *
|
||
|
* WARNINGS: None *
|
||
|
* *
|
||
|
* HISTORY: *
|
||
|
* 11/8/2001 10:20PM ST : Created *
|
||
|
*=============================================================================================*/
|
||
|
void WolGameModeClass::HandleNotification(ConnectionStatus &status)
|
||
|
{
|
||
|
if (mMonitorConnection && status == ConnectionDisconnected) {
|
||
|
Handle_Disconnect();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
/***********************************************************************************************
|
||
|
* WolGameModeClass::Handle_Disconnect -- Handle disconnect from chat server *
|
||
|
* *
|
||
|
* *
|
||
|
* *
|
||
|
* INPUT: Nothing *
|
||
|
* *
|
||
|
* OUTPUT: Nothing *
|
||
|
* *
|
||
|
* WARNINGS: None *
|
||
|
* *
|
||
|
* HISTORY: *
|
||
|
* 11/8/2001 10:21PM ST : Created *
|
||
|
*=============================================================================================*/
|
||
|
void WolGameModeClass::Handle_Disconnect(void)
|
||
|
{
|
||
|
if (mMonitorConnection && mConnected) {
|
||
|
mConnected = false;
|
||
|
|
||
|
if (cNetwork::I_Am_Server()) {
|
||
|
|
||
|
if (The_Game() && The_Game()->IsDedicated.Is_True() && AutoRestart.Get_Restart_Flag()) {
|
||
|
|
||
|
/*
|
||
|
** If the game has a time limit and players then we will wait until the next map change otherwise we will stop now.
|
||
|
*/
|
||
|
WWASSERT(PTheGameData != NULL);
|
||
|
//if (!The_Game()->Get_Time_Limit_Minutes() || SlaveMaster.Am_I_Slave()) {
|
||
|
if (cPlayerManager::Count() == 0) {
|
||
|
if (SlaveMaster.Am_I_Slave()) {
|
||
|
AutoRestart.Set_Restart_Flag(false);
|
||
|
Set_Exit_On_Exception(true);
|
||
|
cGameData::Set_Manual_Exit(true);
|
||
|
} else {
|
||
|
Quit_And_Restart();
|
||
|
}
|
||
|
} else {
|
||
|
/*
|
||
|
** Tell the players we have to quit
|
||
|
*/
|
||
|
mStartQuitProcessTime = TIMEGETTIME();
|
||
|
if (cNetwork::I_Am_Server()) {
|
||
|
WideStringClass widestring(TRANSLATE (IDS_MENU_QUITTING_DUE_TO_CONN_LOSS_MSG), true);
|
||
|
cScTextObj * message = new cScTextObj;
|
||
|
message->Init(widestring, TEXT_MESSAGE_PUBLIC, true, HOST_TEXT_SENDER, -1);
|
||
|
}
|
||
|
}
|
||
|
//} else {
|
||
|
//Quit_And_Restart();
|
||
|
//}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
/***********************************************************************************************
|
||
|
* WolGameModeClass::HandleNotification -- Handle server error notifications *
|
||
|
* *
|
||
|
* *
|
||
|
* *
|
||
|
* INPUT: Server error tyoe *
|
||
|
* *
|
||
|
* OUTPUT: Nothing *
|
||
|
* *
|
||
|
* WARNINGS: None *
|
||
|
* *
|
||
|
* HISTORY: *
|
||
|
* 11/8/2001 10:21PM ST : Created *
|
||
|
*=============================================================================================*/
|
||
|
void WolGameModeClass::HandleNotification(ServerError& server_error)
|
||
|
{
|
||
|
/*
|
||
|
** This doesn't work because you can't get a server list without also doing a complete reset of wolapi.
|
||
|
*/
|
||
|
#if (0)
|
||
|
HRESULT code = server_error.GetErrorCode();
|
||
|
|
||
|
if (code == CHAT_E_MUSTPATCH) {
|
||
|
if (mMonitorConnection && mConnected) {
|
||
|
mPatchAvailable = true;
|
||
|
|
||
|
/*
|
||
|
** If the game has a time limit and players then we will wait until the next map change otherwise we will stop now.
|
||
|
*/
|
||
|
WWASSERT(PTheGameData != NULL);
|
||
|
|
||
|
if (!The_Game()->Get_Time_Limit_Minutes() || cPlayerManager::Count() == 0) {
|
||
|
mStartQuitProcessTime = TIMEGETTIME();
|
||
|
} else {
|
||
|
Quit_And_Restart();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
#endif //(0)
|
||
|
}
|
||
|
|
||
|
|
||
|
/***********************************************************************************************
|
||
|
* WolGameModeClass::Quit_And_Restart -- Setup a restart then quit the game *
|
||
|
* *
|
||
|
* *
|
||
|
* *
|
||
|
* INPUT: Nothing *
|
||
|
* *
|
||
|
* OUTPUT: Nothing *
|
||
|
* *
|
||
|
* WARNINGS: None *
|
||
|
* *
|
||
|
* HISTORY: *
|
||
|
* 11/8/2001 10:21PM ST : Created *
|
||
|
*=============================================================================================*/
|
||
|
void WolGameModeClass::Quit_And_Restart(void)
|
||
|
{
|
||
|
static bool reenter_ye_not = false;
|
||
|
|
||
|
if (!reenter_ye_not) {
|
||
|
|
||
|
reenter_ye_not = true;
|
||
|
/*
|
||
|
** This will cause the server to leave the channel if needed.
|
||
|
*/
|
||
|
GameInitMgrClass::End_Game();
|
||
|
|
||
|
/*
|
||
|
** If there is a patch available then download it.
|
||
|
*/
|
||
|
if (mConnected) {
|
||
|
WOLLogonMgr::Logoff();
|
||
|
if (mPatchAvailable) {
|
||
|
RefPtr<WWOnline::Session> wolSession = WWOnline::Session::GetInstance(false);
|
||
|
DlgDownload::DoDialog(TRANSLATE(IDS_WOL_DOWNLOAD), wolSession->GetPatchDownloadList(), true);
|
||
|
}
|
||
|
} else {
|
||
|
/*
|
||
|
** If we lost connection then drop out of the game and try to re-establish connection.
|
||
|
*/
|
||
|
AutoRestart.Set_Restart_Flag(true);
|
||
|
Set_Exit_On_Exception(true);
|
||
|
cGameData::Set_Manual_Exit(true);
|
||
|
Stop_Main_Loop(EXIT_SUCCESS);
|
||
|
}
|
||
|
reenter_ye_not = false;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
/******************************************************************************
|
||
|
*
|
||
|
* NAME
|
||
|
* WolGameModeClass::HandleNotification(WOLPagedEvent)
|
||
|
*
|
||
|
* DESCRIPTION
|
||
|
* Handle the display of pages and invitations from users outside the game.
|
||
|
*
|
||
|
* INPUTS
|
||
|
*
|
||
|
* RESULT
|
||
|
* NONE
|
||
|
*
|
||
|
******************************************************************************/
|
||
|
|
||
|
void WolGameModeClass::HandleNotification(WOLPagedEvent& event)
|
||
|
{
|
||
|
PageMessage* page = event.Subject();
|
||
|
WWASSERT(page && "NULL page in WOLPagedEvent");
|
||
|
|
||
|
switch (event.GetAction()) {
|
||
|
case PAGE_RECEIVED: {
|
||
|
WideStringClass message(255, true);
|
||
|
message.Format(L"%s: %s", page->GetPagersName(), page->GetPageMessage());
|
||
|
CombatManager::Get_Message_Window()->Add_Message(message, COLOR_PAGED_TEXT);
|
||
|
WWAudioClass::Get_Instance()->Create_Instant_Sound("Private_Message", Matrix3D(1));
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case INVITATION_RECEIVED:
|
||
|
case INVITATION_DECLINED:
|
||
|
CombatManager::Get_Message_Window()->Add_Message(page->GetPageMessage(), COLOR_INVITE_TEXT);
|
||
|
WWAudioClass::Get_Instance()->Create_Instant_Sound("Private_Message", Matrix3D(1));
|
||
|
break;
|
||
|
|
||
|
case PAGE_ERROR:
|
||
|
case PAGE_NOT_THERE:
|
||
|
case PAGE_TURNED_OFF: {
|
||
|
WideStringClass message(255, true);
|
||
|
message.Format(L"%s %s", TRANSLATE(IDS_WOL_PAGEUSERERROR), page->GetPageMessage());
|
||
|
CombatManager::Get_Message_Window()->Add_Message(page->GetPageMessage(), COLOR_CONSOLE_TEXT);
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
void WolGameModeClass::Game_Start_Timeout_Callback(void)
|
||
|
{
|
||
|
GameModeClass* game = GameModeManager::Find("WOL");
|
||
|
if (game && game->Is_Active()) {
|
||
|
WolGameModeClass* wolgame = reinterpret_cast<WolGameModeClass*>(game);
|
||
|
wolgame->Game_Start_Timed_Out();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
void WolGameModeClass::Game_Start_Timed_Out(void)
|
||
|
{
|
||
|
/*
|
||
|
** If we lost connection without getting a report from WW Online then the only clue we have is that we will fail to
|
||
|
** get the game ID by timing out. Since this is pretty much fatal anyway, let's quit and restart and see if things fix
|
||
|
** themselves up.
|
||
|
**
|
||
|
** ST - 8/21/2002 11:27AM
|
||
|
*/
|
||
|
if (cNetwork::I_Am_Server()) {
|
||
|
if (The_Game() && The_Game()->IsDedicated.Is_True() && AutoRestart.Get_Restart_Flag()) {
|
||
|
mConnected = false;
|
||
|
if (SlaveMaster.Am_I_Slave()) {
|
||
|
AutoRestart.Set_Restart_Flag(false);
|
||
|
Set_Exit_On_Exception(true);
|
||
|
cGameData::Set_Manual_Exit(true);
|
||
|
} else {
|
||
|
Quit_And_Restart();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
}
|