Initial commit of Command & Conquer Renegade source code.

This commit is contained in:
LFeenanEA
2025-02-27 16:39:46 +00:00
parent 74ab8fa5e0
commit 58ed459113
4918 changed files with 1366710 additions and 0 deletions

View File

@@ -0,0 +1,343 @@
/*
** 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/>.
*/
/******************************************************************************
*
* FILE
* $Archive: /Commando/Code/Commando/AnnounceEvent.cpp $
*
* DESCRIPTION
* Client announcement
*
* PROGRAMMER
* Denzil E. Long, Jr.
* $Author: Denzil_l $
*
* VERSION INFO
* $Revision: 9 $
* $Modtime: 1/12/02 9:33p $
*
******************************************************************************/
#include "announceevent.h"
#include "networkobjectfactory.h"
#include "apppackettypes.h"
#include "networkobjectmgr.h"
#include "cnetwork.h"
#include "gamemode.h"
#include "playertype.h"
#include "translateobj.h"
#include "translatedb.h"
#include "wwaudio.h"
#include "messagewindow.h"
#include <wwlib\widestring.h>
#include "cncmodesettings.h"
#include "floodprotectionmgr.h"
DECLARE_NETWORKOBJECT_FACTORY(CSAnnouncement, NETCLASSID_CSANNOUNCEMENT);
CSAnnouncement::CSAnnouncement(void) :
mFromID(-1),
mToID(-1),
mAnnouncementID(0),
mRadioCmdID(-1),
mType(ANNOUNCEMENT_PUBLIC)
{
Set_App_Packet_Type(APPPACKETTYPE_CSANNOUNCEMENT);
}
CSAnnouncement::~CSAnnouncement()
{
}
void CSAnnouncement::Init(int to_id, int announcementID, AnnouncementEnum type, int radio_cmd_id)
{
WWASSERT(cNetwork::I_Am_Client());
mToID = to_id;
mFromID = cNetwork::Get_My_Id();
mAnnouncementID = announcementID;
mRadioCmdID = radio_cmd_id;
mType = type;
Set_Network_ID(NetworkObjectMgrClass::Get_New_Client_ID());
//
// Is this user "flooding" the server with text?
//
if (FloodProtectionMgrClass::Detect_Flooding (L"") == false)
{
if (cNetwork::I_Am_Server())
{
Act();
}
else
{
Set_Object_Dirty_Bit(0, BIT_CREATION, true);
}
}
else
{
//
// Flooding detected -- don't send the message
//
Set_Delete_Pending();
}
}
void CSAnnouncement::Act(void)
{
WWASSERT(cNetwork::I_Am_Server());
if (GameModeManager::Find("Combat")->Is_Active())
{
SCAnnouncement* announce = new SCAnnouncement;
announce->Init(mToID, mFromID, mAnnouncementID, mType, mRadioCmdID);
}
Set_Delete_Pending();
}
void CSAnnouncement::Export_Creation(BitStreamClass& packet)
{
WWASSERT(cNetwork::I_Am_Only_Client());
cNetEvent::Export_Creation(packet);
packet.Add(mToID);
packet.Add(mFromID);
packet.Add(mAnnouncementID);
packet.Add(mRadioCmdID);
packet.Add((BYTE)mType);
Set_Delete_Pending();
}
void CSAnnouncement::Import_Creation(BitStreamClass& packet)
{
WWASSERT(cNetwork::I_Am_Server());
cNetEvent::Import_Creation(packet);
packet.Get(mToID);
packet.Get(mFromID);
packet.Get(mAnnouncementID);
packet.Get(mRadioCmdID);
BYTE type = 0;
packet.Get(type);
mType = (AnnouncementEnum)type;
Act();
}
//-----------------------------------------------------------------------------
DECLARE_NETWORKOBJECT_FACTORY(SCAnnouncement, NETCLASSID_SCANNOUNCEMENT);
SCAnnouncement::SCAnnouncement(void) :
mToID(-1),
mFromID(-1),
mAnnouncementID(0),
mRadioCmdID(-1),
mType(ANNOUNCEMENT_PUBLIC)
{
Set_App_Packet_Type(APPPACKETTYPE_SCANNOUNCEMENT);
}
SCAnnouncement::~SCAnnouncement()
{
}
void SCAnnouncement::Init(int to_id, int from_id, int announcementID, AnnouncementEnum type, int radio_cmd_id)
{
WWASSERT(cNetwork::I_Am_Server());
mToID = to_id;
mFromID = from_id;
mAnnouncementID = announcementID;
mRadioCmdID = radio_cmd_id;
mType = type;
switch (type)
{
case ANNOUNCEMENT_PUBLIC:
Set_Object_Dirty_Bit(BIT_CREATION, true);
break;
case ANNOUNCEMENT_TEAM:
if (mToID >= 0)
{
Set_Dirty_Bit_For_Team(BIT_CREATION, mToID);
}
break;
case ANNOUNCEMENT_PRIVATE:
if (mToID >= 0)
{
Set_Object_Dirty_Bit(mToID, BIT_CREATION, true);
}
break;
default:
break;
}
// Explicitly show the message on the server if he is among the recipients.
if (cNetwork::I_Am_Client() && Is_Client_Dirty(cNetwork::Get_My_Id()))
{
Act();
}
}
void SCAnnouncement::Set_Dirty_Bit_For_Team(DIRTY_BIT bit, int team)
{
WWASSERT(team == PLAYERTYPE_NOD || team == PLAYERTYPE_GDI);
SList<cPlayer>* playerList = cPlayerManager::Get_Player_Object_List();
if (playerList)
{
SLNode<cPlayer>* playerNode = playerList->Head();
while (playerNode)
{
cPlayer* player = playerNode->Data();
if (player && player->Is_Active() && (player->Get_Player_Type() == team))
{
Set_Object_Dirty_Bit(player->Get_Id(), bit, true);
}
playerNode = playerNode->Next();
}
}
}
void SCAnnouncement::Act(void)
{
if (mAnnouncementID > 0)
{
// Lookup the translation object from the strings database
TDBObjClass* translateObj = TranslateDBClass::Find_Object(mAnnouncementID);
cPlayer* sender = cPlayerManager::Find_Player(mFromID);
//
// Display the emot icon as ncessary
//
if (sender != NULL && mRadioCmdID != -1)
{
//
// Dig the soldier game object out from the player data
//
SmartGameObj *game_obj = sender->Get_GameObj();
if (game_obj != NULL && game_obj->As_SoldierGameObj () != NULL)
{
CNCModeSettingsDef* cncDef = CNCModeSettingsDef::Get_Instance();
if (cncDef != NULL)
{
//
// Display the emot icon
//
const float EMOT_ICON_DURATION = 2.0F;
const char *emot_icon_name = cncDef->Get_Radio_Command_Emot_Icon (mRadioCmdID);
game_obj->As_SoldierGameObj ()->Set_Emot_Icon (emot_icon_name, EMOT_ICON_DURATION);
}
}
}
if (translateObj)
{
// Display the text on the screen
const WCHAR* string = translateObj->Get_String();
if (string)
{
if (sender)
{
WideStringClass message(0, true);
message.Format(L"%s: %s", sender->Get_Name(), string);
CombatManager::Get_Message_Window()->Add_Message(message, sender->Get_Color());
}
else
{
CombatManager::Get_Message_Window()->Add_Message(string, Vector3(1,1,1));
}
}
// Play the sound effect
int soundID = (int)translateObj->Get_Sound_ID();
if (soundID > 0)
{
WWAudioClass::Get_Instance()->Create_Instant_Sound(soundID, Matrix3D(1));
}
}
}
Set_Delete_Pending();
}
//-----------------------------------------------------------------------------
void SCAnnouncement::Export_Creation(BitStreamClass& packet)
{
cNetEvent::Export_Creation(packet);
packet.Add(mToID);
packet.Add(mFromID);
packet.Add(mAnnouncementID);
packet.Add(mRadioCmdID);
packet.Add((BYTE)mType);
Set_Delete_Pending();
}
//-----------------------------------------------------------------------------
void SCAnnouncement::Import_Creation(BitStreamClass& packet)
{
cNetEvent::Import_Creation(packet);
WWASSERT(cNetwork::I_Am_Only_Client());
packet.Get(mToID);
packet.Get(mFromID);
packet.Get(mAnnouncementID);
packet.Add(mRadioCmdID);
BYTE type = 0;
packet.Get(type);
mType = (AnnouncementEnum)type;
Act();
}

View File

@@ -0,0 +1,108 @@
/*
** 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/>.
*/
/******************************************************************************
*
* FILE
* $Archive: /Commando/Code/commando/AnnounceEvent.h $
*
* DESCRIPTION
* Client announcement
*
* PROGRAMMER
* Denzil E. Long, Jr.
* $Author: Patrick $
*
* VERSION INFO
* $Revision: 5 $
* $Modtime: 11/28/01 4:22p $
*
******************************************************************************/
#ifndef __ANNOUNCEEVENT_H__
#define __ANNOUNCEEVENT_H__
#include "NetEvent.h"
#include "NetClassIDs.h"
enum AnnouncementEnum
{
ANNOUNCEMENT_PUBLIC = 0,
ANNOUNCEMENT_TEAM,
ANNOUNCEMENT_PRIVATE,
};
class CSAnnouncement :
public cNetEvent
{
public:
CSAnnouncement();
virtual ~CSAnnouncement();
void Init(int to_id, int announcementID, AnnouncementEnum type, int radio_cmd_id = -1);
virtual void Export_Creation(BitStreamClass& packet);
virtual void Import_Creation(BitStreamClass& packet);
virtual uint32 Get_Network_Class_ID(void) const
{return NETCLASSID_CSANNOUNCEMENT;}
protected:
CSAnnouncement(const CSAnnouncement&);
const CSAnnouncement& operator=(const CSAnnouncement&);
virtual void Act(void);
int mToID;
int mFromID;
int mAnnouncementID;
int mRadioCmdID;
AnnouncementEnum mType;
};
class SCAnnouncement :
public cNetEvent
{
public:
SCAnnouncement();
virtual ~SCAnnouncement();
void Init(int to_id, int from_id, int announcementID, AnnouncementEnum type, int radio_cmd_id = -1);
virtual void Export_Creation(BitStreamClass& packet);
virtual void Import_Creation(BitStreamClass& packet);
virtual uint32 Get_Network_Class_ID(void) const
{return NETCLASSID_SCANNOUNCEMENT;}
protected:
SCAnnouncement(const SCAnnouncement&);
const SCAnnouncement& operator=(const SCAnnouncement&);
virtual void Act(void);
void Set_Dirty_Bit_For_Team(DIRTY_BIT bit, int team);
int mToID;
int mFromID;
int mAnnouncementID;
int mRadioCmdID;
AnnouncementEnum mType;
};
#endif // __ANNOUNCEEVENT_H__

968
Code/Commando/AutoStart.cpp Normal file
View File

@@ -0,0 +1,968 @@
/*
** 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/AutoStart.cpp $*
* *
* $Author:: Steve_t $*
* *
* $Modtime:: 8/13/02 4:58p $*
* *
* $Revision:: 24 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include "always.h"
#include "autostart.h"
//#include "dlgmplangametype.h"
#include "gameinitmgr.h"
#include "registry.h"
#include "_globals.h"
#include "gamedata.h"
#include "gameinitmgr.h"
#include "campaign.h"
#include "win.h"
#include "except.h"
#include "listctrl.h"
#include "dlgwolautostart.h"
#include "dlgdownload.h"
#include "translatedb.h"
#include "string_ids.h"
#include "slavemaster.h"
#include "gamesideservercontrol.h"
#include "gamedata.h"
#include "nat.h"
#include "consolemode.h"
#include "wwonline\wolserver.h"
#include "notify.h"
#include "serversettings.h"
#include "wolbuddymgr.h"
#include "bandwidthcheck.h"
#include "bandwidth.h"
#include "gamespyadmin.h"
#include "specialbuilds.h"
/*
** Single instance of restart class.
*/
AutoRestartClass AutoRestart;
/*
** Registry entries.
*/
const char *AutoRestartClass::REG_VALUE_AUTO_RESTART_FLAG = "AutoRestartFlag";
const char *AutoRestartClass::REG_VALUE_AUTO_RESTART_TYPE = "AutoRestartType";
static const char *WINDOWS_SUB_KEY_RUN_ONCE = "Software\\Microsoft\\Windows\\CurrentVersion\\RunOnce\\";
static const char *WINDOWS_SUB_KEY_RUN_ONCE_APP = "Renegade";
/*
** Stupid extern for main loop exit.
*/
extern void Stop_Main_Loop (int exitCode);
AutoRestartProgressDialogClass *AutoRestartProgressDialogClass::Instance;
/***********************************************************************************************
* AutoRestartClass::AutoRestartClass -- Class constructor *
* *
* *
* *
* INPUT: Nothing *
* *
* OUTPUT: Nothing *
* *
* WARNINGS: None *
* *
* HISTORY: *
* 11/5/2001 3:21PM ST : Created *
*=============================================================================================*/
AutoRestartClass::AutoRestartClass(void)
{
RestartState = STATE_DONE;
CancelRequest = false;
GameMode = 0;
NumChannelCreateTries = 0;
}
/***********************************************************************************************
* AutoRestartClass::Restart_Game -- Initiate the restart process *
* *
* *
* *
* INPUT: Nothing *
* *
* OUTPUT: Nothing *
* *
* WARNINGS: None *
* *
* HISTORY: *
* 11/5/2001 3:22PM ST : Created *
*=============================================================================================*/
void AutoRestartClass::Restart_Game(void)
{
if (RestartState == STATE_DONE) {
RestartState = STATE_FIRST;
CancelRequest = false;
RegistryClass registry (APPLICATION_SUB_KEY_NAME_WOLSETTINGS);
if (registry.Is_Valid()) {
GameMode = registry.Get_Int(REG_VALUE_AUTO_RESTART_TYPE, GameMode);
}
Set_Restart_Flag(false);
}
}
/***********************************************************************************************
* AutoRestartClass::Cancel -- Cancel game restart *
* *
* *
* *
* INPUT: Nothing *
* *
* OUTPUT: Nothing *
* *
* WARNINGS: None *
* *
* HISTORY: *
* 11/5/2001 9:42PM ST : Created *
*=============================================================================================*/
void AutoRestartClass::Cancel(void)
{
CancelRequest = true;
}
/***********************************************************************************************
* AutoRestartClass::Think -- Class service function *
* *
* *
* *
* INPUT: Nothing *
* *
* OUTPUT: Nothing *
* *
* WARNINGS: None *
* *
* HISTORY: *
* 11/5/2001 3:22PM ST : Created *
*=============================================================================================*/
void AutoRestartClass::Think(void)
{
static unsigned long time;
bool can_render = ConsoleBox.Is_Exclusive() ? false : true;
switch (RestartState) {
/*
** Idle, not doing anything.
*/
case STATE_DONE:
break;
/*
** This is the first restart state. Initialise WOL and login.
*/
case STATE_FIRST:
if (CancelRequest) {
RestartState = STATE_CANCELLED;
}
/*
** Create the progress dialog.
*/
if (can_render) {
START_DIALOG(AutoRestartProgressDialogClass);
AutoRestartProgressDialogClass::Get_Instance()->Add_Text(L"Auto starting game. Type 'quit' at the console window to abort");
}
ConsoleBox.Print("*** Auto starting game. Type 'quit' to abort ***\n");
/*
** Start listening for server control messages.
*/
GameSideServerControlClass::Init();
/*
** Initialise WOL or LAN mode.
*/
if (!GameMode) {
if (can_render) {
AutoRestartProgressDialogClass::Get_Instance()->Add_Text(L"Initializing LAN Mode");
}
if (cGameSpyAdmin::Get_Is_Server_Gamespy_Listed()) {
ConsoleBox.Print("Initializing GameSpy Mode\n");
} else {
ConsoleBox.Print("Initializing LAN Mode\n");
}
GameInitMgrClass::Initialize_LAN();
RestartState = STATE_GAME_MODE_WAIT;
} else {
if (can_render) {
AutoRestartProgressDialogClass::Get_Instance()->Add_Text(L"Initializing Westwood Online");
}
ConsoleBox.Print("Initializing Westwood Online Mode\n");
GameInitMgrClass::Initialize_WOL();
RestartState = STATE_GAME_MODE_WAIT;
/*
** Force a new server list update. This will cause a complete WOLAPI reset too btw.
*/
RefPtr<WWOnline::Session> wol_session = WWOnline::Session::GetInstance(false);
wol_session->Reset();
/*
** Hide the page dialog - we don't want that sucker popping up when there's no-one around.
*/
WOLBuddyMgr* buddy = WOLBuddyMgr::GetInstance(false);
if (buddy) {
buddy->HidePagedDialog();
buddy->Release_Ref();
}
}
break;
case STATE_GAME_MODE_WAIT:
if (cGameData::Is_Manual_Exit()) {
/*
** Allow the page dialog to display again.
*/
if (GameMode) {
WOLBuddyMgr* buddy = WOLBuddyMgr::GetInstance(false);
if (buddy) {
buddy->ShowPagedDialog();
buddy->Release_Ref();
}
}
RestartState = STATE_DONE;
Stop_Main_Loop (EXIT_SUCCESS);
break;
} else {
if (!GameMode) {
GameModeClass *game_mode = GameModeManager::Find("LAN");
if (game_mode && game_mode->Is_Active()) {
RestartState = STATE_CREATE_GAME;
break;
}
/*
** It won't have initialzed above if a shutdown was already pending. Maybe we need to try again.
*/
if (game_mode && game_mode->Is_Inactive()) {
GameInitMgrClass::Initialize_LAN();
break;
}
} else {
GameModeClass *game_mode = GameModeManager::Find("WOL");
if (game_mode && game_mode->Is_Active()) {
/*
** Logon to WOL.
*/
if (can_render) {
AutoRestartProgressDialogClass::Get_Instance()->Add_Text(L"Logging on");
}
LogonAction = (WOLLogonAction) -1;
WOLLogonMgr::Set_Quiet_Mode(true);
RefPtr<WWOnline::Session> WOLSession = WWOnline::Session::GetInstance(false);
Observer<WWOnline::ServerError>::NotifyMe(*WOLSession);
WOLLogonMgr::Logon(this);
RestartState = STATE_LOGIN;
break;
}
/*
** It won't have initialzed above if a shutdown was already pending. Maybe we need to try again.
*/
if (game_mode && game_mode->Is_Inactive()) {
GameInitMgrClass::Initialize_WOL();
break;
}
}
}
break;
/*
** Wait for the login process to complete.
*/
case STATE_LOGIN:
if (cGameData::Is_Manual_Exit()) {
/*
** Allow the page dialog to display again.
*/
if (GameMode) {
WOLBuddyMgr* buddy = WOLBuddyMgr::GetInstance(false);
if (buddy) {
buddy->ShowPagedDialog();
buddy->Release_Ref();
}
}
Observer<WWOnline::ServerError>::StopObserving();
RestartState = STATE_DONE;
Stop_Main_Loop (EXIT_SUCCESS);
break;
}
switch (LogonAction) {
/*
** Login failed. Might be that the user is still logged in from last time so retry.
*/
case WOLLOGON_FAILED:
if (CancelRequest) {
Observer<WWOnline::ServerError>::StopObserving();
RestartState = STATE_CANCELLED;
break;
}
if (can_render) {
AutoRestartProgressDialogClass::Get_Instance()->Add_Text(L"Failed, retrying");
}
ConsoleBox.Print("Failed to log in, retrying\n");
LogonAction = (WOLLogonAction) -1;
if (can_render) {
AutoRestartProgressDialogClass::Get_Instance()->Add_Text(L"Logging on");
}
ConsoleBox.Print("Logging on....\n");
WOLLogonMgr::Logon(this);
break;
/*
** Logged in OK. Move onto the next step.
*/
case WOLLOGON_SUCCESS:
if (CancelRequest) {
Observer<WWOnline::ServerError>::StopObserving();
WOLLogonMgr::Logoff();
RestartState = STATE_CANCELLED;
break;
}
if (can_render) {
AutoRestartProgressDialogClass::Get_Instance()->Add_Text(L"Logged on OK");
}
ConsoleBox.Print("Logged on OK\n");
WOLLogonMgr::Set_Quiet_Mode(false);
RestartState = STATE_CREATE_GAME;
time = TIMEGETTIME();
Observer<WWOnline::ServerError>::StopObserving();
break;
/*
** Patch available. At this point we want to
**
** 1. Download the patch.
** 2. Quit to apply the patch.
** 3. Reload the level after the restart.
**
*/
case WOLLOGON_PATCHREQUIRED:
{
RefPtr<WWOnline::Session> wol_session = WWOnline::Session::GetInstance(false);
ConsoleBox.Print("Downloading patch\n");
DlgDownload::DoDialog(TRANSLATE(IDS_WOL_DOWNLOAD), wol_session->GetPatchDownloadList(), true);
Set_Restart_Flag(true);
RestartState = STATE_DONE;
Observer<WWOnline::ServerError>::StopObserving();
break;
}
/*
** Fatal error. Abort restart process.
*/
case WOLLOGON_CANCEL:
WOLLogonMgr::Set_Quiet_Mode(false);
RestartState = STATE_CANCELLED;
Observer<WWOnline::ServerError>::StopObserving();
break;
}
break;
/*
** Create the game object and initialise it with the settings from the last game.
*/
case STATE_CREATE_GAME:
{
if (cGameData::Is_Manual_Exit()) {
/*
** Allow the page dialog to display again.
*/
if (GameMode) {
WOLBuddyMgr* buddy = WOLBuddyMgr::GetInstance(false);
if (buddy) {
buddy->ShowPagedDialog();
buddy->Release_Ref();
}
}
RestartState = STATE_DONE;
Stop_Main_Loop (EXIT_SUCCESS);
break;
}
if (CancelRequest) {
if (GameMode) {
WOLLogonMgr::Logoff();
}
RestartState = STATE_CANCELLED;
break;
}
/*
** We have to wait for the firewall thread to discover the local IP before we can build the game.
*/
if (GameMode) {
if (FirewallHelper.Get_Local_Address() == 0) {
if (TIMEGETTIME() - time < 1000 * 6) {
break;
}
}
}
/*
** Work out what type of game to create.
*/
if (can_render) {
AutoRestartProgressDialogClass::Get_Instance()->Add_Text(L"Building game info");
}
/*
int last_game_type = 0;
RegistryClass registry (APPLICATION_SUB_KEY_NAME_WOLSETTINGS);
if (registry.Is_Valid ()) {
last_game_type = registry.Get_Int(REG_VALUE_LAST_GAME_TYPE, last_game_type);
}
last_game_type = min(last_game_type, NUM_GAME_TYPE_MENU_ENTRIES-1);
last_game_type = max(last_game_type, 0);
int game_type = MPLanGameTypeMenuClass::GameTypeList[last_game_type].GameType;
*/
int game_type = cGameData::GAME_TYPE_CNC;
/*
** Create the new game data.
*/
PTheGameData = cGameData::Create_Game_Of_Type((cGameData::GameTypeEnum)game_type);
WWASSERT(PTheGameData != NULL);
/*
** Apply command line/ini settings.
*/
if (ServerSettingsClass::Parse(true) == false) {
/*
** Allow the page dialog to display again.
*/
if (GameMode) {
WOLBuddyMgr* buddy = WOLBuddyMgr::GetInstance(false);
if (buddy) {
buddy->ShowPagedDialog();
buddy->Release_Ref();
}
}
RestartState = STATE_DONE;
Stop_Main_Loop (EXIT_SUCCESS);
break;
}
/*
** Start listening for server control messages.
*/
//GameSideServerControlClass::Init();
/*
** Load alternate server settings if required.
*/
if (SlaveMaster.Am_I_Slave()) {
RegistryClass reg(APPLICATION_SUB_KEY_NAME_OPTIONS);
char file_name[MAX_PATH];
reg.Get_String("MultiplayerSettings", file_name, sizeof(file_name), "");
if (strlen(file_name)) {
WWDEBUG_SAY(("Loading multiplayer settings from file %s\n", file_name));
The_Game()->Set_Ini_Filename(file_name);
}
}
/*
** Load the game settings.
*/
The_Game()->Load_From_Server_Config();
/*
** Set MaxPlayers based on Bandwidth test results if MaxPlayers is
** set to 0 in the INI file.
*/
if (ServerSettingsClass::Get_Game_Mode() == ServerSettingsClass::MODE_WOL &&
The_Game()->Get_Max_Players() == 0 && BandwidthCheckerClass::Got_Bandwidth()) {
int max_players = (cBandwidth::Get_Bandwidth_Bps_From_Type(BANDWIDTH_AUTO) / 250000) * 4;
if (max_players < 2) {
if (cBandwidth::Get_Bandwidth_Bps_From_Type(BANDWIDTH_AUTO) > 100000) {
max_players = 4;
} else {
max_players = 2;
}
} else if (max_players > 32) {
max_players = 32;
}
The_Game()->Set_Max_Players(max_players);
}
/*
** Override gama settings in command line mode.
*/
if (ServerSettingsClass::Is_Command_Line_Mode()) {
The_Game()->IsAutoRestart.Set(true);
The_Game()->IsDedicated.Set(true);
}
StringClass inifile = The_Game()->Get_Ini_Filename();
StringClass nick(32, true);
cNetInterface::Get_Nickname().Convert_To(nick);
ConsoleBox.Set_Title(nick.Peek_Buffer(), inifile.Peek_Buffer());
if (GameMode) {
NumChannelCreateTries = 0;
RestartState = STATE_CREATE_CHANNEL;
} else {
RestartState = STATE_START_GAME;
}
break;
}
/*
** Create the game channel on the chat server.
*/
case STATE_CREATE_CHANNEL:
{
if (cGameData::Is_Manual_Exit()) {
/*
** Allow the page dialog to display again.
*/
if (GameMode) {
WOLBuddyMgr* buddy = WOLBuddyMgr::GetInstance(false);
if (buddy) {
buddy->ShowPagedDialog();
buddy->Release_Ref();
}
/*
** Log off.
*/
WOLLogonMgr::Logoff();
}
RestartState = STATE_DONE;
Stop_Main_Loop (EXIT_SUCCESS);
break;
}
if (CancelRequest) {
WOLLogonMgr::Logoff();
RestartState = STATE_CANCELLED;
break;
}
if (can_render) {
AutoRestartProgressDialogClass::Get_Instance()->Add_Text(L"Creating game channel....");
}
ConsoleBox.Print("Creating game channel...\n");
/*
** Create the game channel.
*/
GameModeClass *game_mode = GameModeManager::Find("WOL");
LastChannelCreateTime = TIMEGETTIME();
if (game_mode && game_mode->Is_Active()) {
WolGameModeClass* wol_game = (WolGameModeClass*) game_mode;
WWASSERT(wol_game);
wol_game->Set_Quiet_Mode(true);
wol_game->SignalMe(*this);
WWASSERT(PTheGameData != NULL);
NumChannelCreateTries++;
wol_game->Create_Game(The_Game());
RestartState = STATE_WAIT_CHANNEL_CREATE;
} else {
RestartState = STATE_START_GAME;
}
break;
}
/*
** Wait for the game channel creation result.
*/
case STATE_WAIT_CHANNEL_CREATE:
if (cGameData::Is_Manual_Exit()) {
/*
** Allow the page dialog to display again.
*/
if (GameMode) {
WOLBuddyMgr* buddy = WOLBuddyMgr::GetInstance(false);
if (buddy) {
buddy->ShowPagedDialog();
buddy->Release_Ref();
}
/*
** Log off.
*/
WOLLogonMgr::Logoff();
}
RestartState = STATE_DONE;
Stop_Main_Loop (EXIT_SUCCESS);
}
if (CancelRequest) {
WOLLogonMgr::Logoff();
RestartState = STATE_CANCELLED;
break;
}
break;
/*
** Waiting to retry channel create.
*/
case STATE_WAIT_CHANNEL_CREATE_RETRY:
if (cGameData::Is_Manual_Exit()) {
/*
** Allow the page dialog to display again.
*/
if (GameMode) {
WOLBuddyMgr* buddy = WOLBuddyMgr::GetInstance(false);
if (buddy) {
buddy->ShowPagedDialog();
buddy->Release_Ref();
}
/*
** Log off.
*/
WOLLogonMgr::Logoff();
}
RestartState = STATE_DONE;
Stop_Main_Loop (EXIT_SUCCESS);
break;
}
if (CancelRequest) {
WOLLogonMgr::Logoff();
RestartState = STATE_CANCELLED;
break;
}
/*
** Give up and restart if we fail enough times when trying to create a channel.
*/
if (NumChannelCreateTries > 10) {
Set_Exit_On_Exception(true);
cGameData::Set_Manual_Exit(true);
}
if (TIMEGETTIME() - LastChannelCreateTime > 5*1000) {
ConsoleBox.Print("Retrying channel create\n");
RestartState = STATE_CREATE_CHANNEL;
}
break;
/*
** Load the game.
*/
case STATE_START_GAME:
{
if (cGameData::Is_Manual_Exit()) {
/*
** Allow the page dialog to display again.
*/
if (GameMode) {
WOLBuddyMgr* buddy = WOLBuddyMgr::GetInstance(false);
if (buddy) {
buddy->ShowPagedDialog();
buddy->Release_Ref();
}
/*
** Log off.
*/
WOLLogonMgr::Logoff();
}
RestartState = STATE_DONE;
Stop_Main_Loop (EXIT_SUCCESS);
break;
}
if (can_render) {
AutoRestartProgressDialogClass::Get_Instance()->Add_Text(L"Channel created OK");
}
ConsoleBox.Print("Channel created OK\n");
SlaveMaster.Startup_Slaves();
GameModeClass *game_mode = GameModeManager::Find("WOL");
if (game_mode && game_mode->Is_Active()) {
WolGameModeClass* wol_game = (WolGameModeClass*) game_mode;
WWASSERT(wol_game);
wol_game->Set_Quiet_Mode(false);
}
//ConsoleBox.Print("Loading level...\n");
WWASSERT(PTheGameData != NULL);
CampaignManager::Select_Backdrop_Number_By_MP_Type(The_Game()->Get_Game_Type());
GameInitMgrClass::Set_Is_Client_Required(false);
GameInitMgrClass::Set_Is_Server_Required(true);
if (can_render) {
AutoRestartProgressDialogClass::Get_Instance()->End_Dialog();
}
GameInitMgrClass::Start_Game(The_Game()->Get_Map_Name(), -1, 0);
//ConsoleBox.Print("Level loaded OK\n");
RestartState = STATE_DONE;
/*
** Allow the page dialog to display again (it can't really anyway since it's disabled when the game is in progress.
*/
if (GameMode) {
WOLBuddyMgr* buddy = WOLBuddyMgr::GetInstance(false);
if (buddy) {
buddy->ShowPagedDialog();
buddy->Release_Ref();
}
}
break;
}
/*
** User cancelled.
*/
case STATE_CANCELLED:
RestartState = STATE_DONE;
/*
** Allow the page dialog to display again.
*/
WOLBuddyMgr* buddy = WOLBuddyMgr::GetInstance(false);
if (buddy) {
buddy->ShowPagedDialog();
buddy->Release_Ref();
}
if (can_render) {
AutoRestartProgressDialogClass::Get_Instance()->End_Dialog();
}
if (SlaveMaster.Am_I_Slave()) {
if (GameMode) {
WOLLogonMgr::Logoff();
}
RestartState = STATE_DONE;
Stop_Main_Loop (EXIT_SUCCESS);
} else {
RenegadeDialogMgrClass::Goto_Location (RenegadeDialogMgrClass::LOC_MAIN_MENU);
}
break;
}
}
/***********************************************************************************************
* AutoRestartClass::HandleNotification -- Notification callback for WOL login *
* *
* *
* *
* INPUT: Success code *
* *
* OUTPUT: Nothing *
* *
* WARNINGS: None *
* *
* HISTORY: *
* 11/5/2001 3:23PM ST : Created *
*=============================================================================================*/
void AutoRestartClass::HandleNotification(WOLLogonAction& action)
{
LogonAction = action;
}
/***********************************************************************************************
* WolGameModeClass::HandleNotification -- Handle server error notifications *
* *
* *
* *
* INPUT: Server error tyoe *
* *
* OUTPUT: Nothing *
* *
* WARNINGS: None *
* *
* HISTORY: *
* 11/8/2001 10:21PM ST : Created *
*=============================================================================================*/
void AutoRestartClass::HandleNotification(WWOnline::ServerError& server_error)
{
ConsoleBox.Print("Error - %S\n", server_error.GetDescription());
}
/***********************************************************************************************
* AutoRestartClass::ReceiveSignal -- Channel creation signal handler *
* *
* *
* *
* INPUT: Game mode *
* *
* OUTPUT: Nothing *
* *
* WARNINGS: None *
* *
* HISTORY: *
* 11/5/2001 3:23PM ST : Created *
*=============================================================================================*/
void AutoRestartClass::ReceiveSignal(WolGameModeClass &game_mode)
{
if (RestartState == STATE_WAIT_CHANNEL_CREATE) {
if (game_mode.Channel_Create_OK()) {
RestartState = STATE_START_GAME;
} else {
bool can_render = ConsoleBox.Is_Exclusive() ? false : true;
if (can_render) {
AutoRestartProgressDialogClass::Get_Instance()->Add_Text(L"Failed, retrying");
}
ConsoleBox.Print("Failed to create channel\n");
RestartState = STATE_WAIT_CHANNEL_CREATE_RETRY;
}
}
}
/***********************************************************************************************
* AutoRestartClass::Set_Restart_Flag -- Set state of auto restart mode *
* *
* *
* *
* INPUT: New state *
* *
* OUTPUT: Nothing *
* *
* WARNINGS: None *
* *
* HISTORY: *
* 11/5/2001 3:32PM ST : Created *
*=============================================================================================*/
void AutoRestartClass::Set_Restart_Flag(bool enable)
{
RegistryClass registry (APPLICATION_SUB_KEY_NAME_WOLSETTINGS);
if (registry.Is_Valid ()) {
registry.Set_Int(REG_VALUE_AUTO_RESTART_FLAG, enable ? 1 : 0);
GameModeClass *game_mode = GameModeManager::Find("WOL");
if (game_mode && game_mode->Is_Active()) {
GameMode = 1;
} else {
GameModeClass *game_mode = GameModeManager::Find("LAN");
if (game_mode && game_mode->Is_Active()) {
GameMode = 0;
}
}
if (enable) {
registry.Set_Int(REG_VALUE_AUTO_RESTART_TYPE, GameMode);
Set_Exit_On_Exception(true);
} else {
Set_Exit_On_Exception(false);
}
RegistryClass registry_too(WINDOWS_SUB_KEY_RUN_ONCE);
if (registry_too.Is_Valid()) {
if (enable) {
/*
** The the current path and build a path/file combo that points to the launcher.
*/
char path_to_exe[256];
char drive[_MAX_DRIVE];
char dir[_MAX_DIR];
char path[_MAX_PATH];
GetModuleFileName(ProgramInstance, path_to_exe, sizeof(path_to_exe));
_splitpath(path_to_exe, drive, dir, NULL, NULL);
#ifdef FREEDEDICATEDSERVER
_makepath(path, drive, dir, "renegadeserver", "exe");
#else //FREEDEDICATEDSERVER
_makepath(path, drive, dir, "renegade", "exe");
char options[256];
options[0] = 0;
if (ServerSettingsClass::Is_Active()) {
sprintf(options, " /startserver=%s", ServerSettingsClass::Get_Settings_File_Name());
}
if (ConsoleBox.Is_Exclusive()) {
strcat(options, " /nodx");
}
strcat(path, options);
#endif //FREEDEDICATEDSERVER
WWDEBUG_SAY(("Writing %s to RunOnce key\n", path));
registry_too.Set_String(WINDOWS_SUB_KEY_RUN_ONCE_APP, path);
} else {
WWDEBUG_SAY(("Removing RunOnce key\n"));
registry_too.Delete_Value(WINDOWS_SUB_KEY_RUN_ONCE_APP);
}
}
}
}
/***********************************************************************************************
* AutoRestartClass::Get_Restart_Flag -- Is a restart indicated by the registry? *
* *
* *
* *
* INPUT: New state *
* *
* OUTPUT: Nothing *
* *
* WARNINGS: None *
* *
* HISTORY: *
* 11/5/2001 3:32PM ST : Created *
*=============================================================================================*/
bool AutoRestartClass::Get_Restart_Flag(void)
{
bool flag = false;
RegistryClass registry (APPLICATION_SUB_KEY_NAME_WOLSETTINGS);
if (registry.Is_Valid()) {
int restart = registry.Get_Int(REG_VALUE_AUTO_RESTART_FLAG, 0);
flag = restart ? true : false;
}
return(flag);
}

154
Code/Commando/AutoStart.h Normal file
View File

@@ -0,0 +1,154 @@
/*
** 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/AutoStart.h $*
* *
* $Author:: Steve_t $*
* *
* $Modtime:: 8/13/02 4:57p $*
* *
* $Revision:: 6 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#pragma once
#ifndef _AUTOSTART_H
#define _AUTOSTART_H
#include "WOLLogonMgr.h"
#include <wwlib\signaler.h>
#include "wolgmode.h"
#include "menudialog.h"
#include "resource.h"
#include <wwonline\refptr.h>
#include <wwonline\wolsession.h>
namespace WOL {
class WOLSession;
class ServerError;
}
/*
**
** This class handles restarting a server after a crash or system reboot.
**
**
*/
class AutoRestartClass : public Observer<WOLLogonAction>, public Observer<WWOnline::ServerError>, protected Signaler<WolGameModeClass>
{
public:
/*
** Constructor, destructor.
*/
AutoRestartClass(void);
/*
** Misc public functions.
*/
void Restart_Game(void);
void Think(void);
bool Is_Active(void) {return((bool)(RestartState != STATE_DONE));}
void Set_Restart_Flag(bool enable);
bool Get_Restart_Flag(void);
void Cancel(void);
/*
** Callbacks.
*/
void HandleNotification(WOLLogonAction&);
void HandleNotification(WWOnline::ServerError& server_error);
void ReceiveSignal(WolGameModeClass&);
/*
** Enum of steps to go through to restart a game.
*/
typedef enum {
STATE_FIRST,
STATE_GAME_MODE_WAIT,
STATE_LOGIN,
STATE_CREATE_GAME,
STATE_CREATE_CHANNEL,
STATE_WAIT_CHANNEL_CREATE,
STATE_WAIT_CHANNEL_CREATE_RETRY,
STATE_START_GAME,
STATE_CANCELLED,
STATE_DONE,
} RestartStateType;
static const char *REG_VALUE_AUTO_RESTART_FLAG;
static const char *REG_VALUE_AUTO_RESTART_TYPE;
private:
/*
** WOL Login state.
*/
WOLLogonAction LogonAction;
/*
** Restart state.
*/
RestartStateType RestartState;
/*
** Cancel request flag.
*/
bool CancelRequest;
/*
** Game mode. 0 = LAN, 1 = internet.
*/
int GameMode;
/*
** Reference pointer to WOLSession.
*/
RefPtr<WWOnline::Session> WOLSession;
/*
** Time we last tried to create the game channel.
*/
unsigned long LastChannelCreateTime;
/*
** Number of times we tried to create the channel.
*/
int NumChannelCreateTries;
};
extern AutoRestartClass AutoRestart;
#endif //_AUTOSTART_H

166
Code/Commando/CDKeyAuth.cpp Normal file
View File

@@ -0,0 +1,166 @@
/*
** 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/>.
*/
/***********************************************************************************************
*** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : Renegade *
* *
* $Archive:: /Commando/Code/Commando/CDKeyAuth.cpp $*
* *
* Original Author:: Brian Hayes *
* *
* $Author:: Bhayes $*
* *
* $Modtime:: 3/15/02 2:56p $*
* *
* $Revision:: 3 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include <GameSpy\gcdkeyserver.h>
#include <GameSpy\gcdkeyclient.h>
#include <GameSpy\nonport.h>
#include <GameSpy\gs_md5.h>
#include <stdlib.h>
#include "wwdebug.h"
#include "CDKeyAuth.h"
#include "gamespyauthmgr.h"
#include "registry.h"
#include "playermanager.h"
#include "_globals.h"
#include "ServerSettings.h"
// static void c_auth_callback(int localid, int authenticated, char *errmsg, void *instance)
// {
// ((CCDKeyAuth *)instance)->auth_callback(localid, authenticated, errmsg);
// }
//generate a rand nchar challenge
char * CCDKeyAuth::GenChallenge(int nchars)
{
static char s[33];
if (nchars > 32) nchars = 32;
s[nchars] = 0;
while (nchars--)
{
s[nchars] = (char)('a' + rand() % 26);
}
return s;
}
/* Callback function to indicate whether a client has been authorized or not.
If the client has been, then we send them a "welcome" string, representative of
allowing them to "enter" the game. If they have not been authenticated, we dump
them after sending an error message */
void CCDKeyAuth::auth_callback(int localid, int authenticated, char *errmsg, void *instance)
{
// client_t *clients = (client_t *)instance;
// char outbuf[512];
WWDEBUG_SAY(("CDKeyAuth -- %d:%d:%s\n", localid, authenticated, errmsg));
cPlayer * p_player = cPlayerManager::Find_Player(localid);
if (p_player != NULL) {
if (!authenticated) //doh.. bad!
{
// This client failed.
//p_player->Set_GameSpy_Auth_State(GAMESPY_AUTH_STATE_REJECTING);
//cGameSpyAuthMgr::Evict_Player(localid);
cGameSpyAuthMgr::Initiate_Auth_Rejection(localid);
// printf("Client %d was NOT authenticated (%s)\n",localid, errmsg);
// sprintf(outbuf,"E:%s\n",errmsg);
// send(clients[localid].sock, outbuf, strlen(outbuf),0);
// shutdown(clients[localid].sock, 2);
// closesocket(clients[localid].sock);
// clients[localid].sock = INVALID_SOCKET;
} else
{
// This client passed.
p_player->Set_GameSpy_Auth_State(GAMESPY_AUTH_STATE_ACCEPTED);
// printf("Client %d was authenticated (%s)\n",localid, errmsg);
// sprintf(outbuf,"M:Welcome to the game, have fun! (%s)\n",errmsg);
// send(clients[localid].sock, outbuf, strlen(outbuf),0);
}
}
}
void CCDKeyAuth::DisconnectUser(int localid) {
gcd_disconnect_user(localid);
}
void CCDKeyAuth::AuthenticateUser(int localid, ULONG ip, char *challenge, char *authstring) {
// Customize this with our playerdata struct
// Take the response from our challenge that we sent to the client
// and send it off to the Authserver along with the original challenge
gcd_authenticate_user(localid, ip, challenge, authstring, CCDKeyAuth::auth_callback, NULL);
}
void CCDKeyAuth::AuthSerial(const char *challenge, StringClass &resp) {
char response[RESPONSE_SIZE];
StringClass sserial;
WWASSERT(challenge);
GetSerialNum(sserial);
const char *serial = sserial;
char *cdkey = new char [strlen(serial)+1];
char *outb = cdkey;
const char *linep = serial;
char md5hash[33];
while (*linep) {
if (*linep >= '0' && *linep <= '9') {
*outb++ = *linep;
}
linep++;
}
*outb = 0;
// MD5 Hash Here.
MD5Digest((BYTE *)cdkey, strlen(cdkey), md5hash);
// hashserial, challenge, outbuf
gcd_compute_response(md5hash, challenge, response);
delete [] cdkey;
resp = response;
}
void CCDKeyAuth::GetSerialNum(StringClass &serial) {
RegistryClass main_reg(APPLICATION_SUB_KEY_NAME);
StringClass stringval;
StringClass serial_out;
main_reg.Get_String("Serial", stringval);
ServerSettingsClass::Encrypt_Serial(stringval, serial, false);
}

48
Code/Commando/CDKeyAuth.h Normal file
View File

@@ -0,0 +1,48 @@
/*
** 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/>.
*/
#ifndef _CDKEYAUTH_H_
#define _CDKEYAUTH_H_
/********
INCLUDES
********/
#include <WWLib\wwstring.h>
/********
DEFINES
********/
class CCDKeyAuth
{
protected:
static void auth_callback(int localid, int authenticated, char *errmsg, void *instance);
public:
static void GetSerialNum(StringClass &serial);
static void DisconnectUser(int localid);
static void AuthenticateUser(int localid, ULONG ip, char *challenge, char *authstring);
static char *GenChallenge(int nchars);
static void AuthSerial(const char *challenge, StringClass &resp);
};
#endif // CDKEYAUTH

File diff suppressed because it is too large Load Diff

153
Code/Commando/ConsoleMode.h Normal file
View File

@@ -0,0 +1,153 @@
/*
** 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/ConsoleMode.h $*
* *
* $Author:: Steve_t $*
* *
* $Modtime:: 8/14/02 12:00p $*
* *
* $Revision:: 10 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include <win.h>
class WideStringClass;
class StringClass;
class Vector3;
/*
** This is a console interface for the game so you can do stuff even if you can't display the main game window.
**
**
*/
class ConsoleModeClass
{
public:
/*
** Constructor, destructor.
*/
ConsoleModeClass(void);
~ConsoleModeClass(void);
/*
** Init.
*/
void Init(void);
void Set_Title(char *name, char *settings);
/*
** Input processing.
*/
void Think();
void Wait_For_Keypress(void);
/*
** Console output.
*/
void Print(char const * string, ...);
void Print_Maybe(char const * string, ...);
static void Static_Print_Maybe(char const * string, ...);
Add_Message(WideStringClass *formatted_text, Vector3 *text_color, bool forced = false);
/*
** Profiling support.
*/
void Update_Profile(StringClass profile_string);
void Set_Profile_Mode(bool set) {ProfileMode = set; LastProfileCRC = 0; LastProfilePrint = 0;}
void Handle_Profile_Key(int key);
/*
** Master/Slave console window settings/support.
*/
void Set_Exclusive(bool set) {IsExclusive = set;}
bool Is_Exclusive(void) {return(IsExclusive);}
HWND Get_Slave_Window_By_Title(char *name, char *settings);
StringClass Compose_Window_Title(char *name, char *settings, bool slave);
void cprintf(char const * string, ...);
/*
** File logging.
*/
void Log_To_Disk(const char *string);
const char *Get_Log_File_Name(void);
private:
/*
** Private functions.
*/
void Apply_Attributes(void);
/*
** Input and output handles.
*/
HANDLE ConsoleInputHandle;
HANDLE ConsoleOutputHandle;
/*
** Window handle.
*/
HWND ConsoleWindow;
/*
** Input parsing variables.
*/
unsigned long LastKeypressTime;
int Pos;
/*
** Console title bar contents.
*/
char Title[256];
/*
** Is console mode the only mode?
*/
bool IsExclusive;
/*
** Is the console in profile mode?
*/
bool ProfileMode;
/*
** Last profile text CRC.
*/
unsigned long LastProfileCRC;
/*
** Last time we printed the profile.
*/
unsigned long LastProfilePrint;
};
/*
** Single instance of console.
*/
extern ConsoleModeClass ConsoleBox;

View File

@@ -0,0 +1,534 @@
/*
** 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/>.
*/
/******************************************************************************
*
* FILE
* $Archive: /Commando/Code/Commando/DlgDownload.cpp $
*
* DESCRIPTION
* File download dialog.
*
* PROGRAMMER
* Denzil E. Long, Jr.
* $Author: Steve_t $
*
* VERSION INFO
* $Revision: 11 $
* $Modtime: 1/12/02 2:53p $
*
******************************************************************************/
#include "DlgDownload.h"
#include "DlgMessageBox.h"
#include "DlgRestart.h"
#include "Resource.h"
#include <WWUI\ProgressCtrl.h>
#include "String_IDs.h"
#include <WWTranslateDB\TranslateDB.h>
#include <WWDebug\WWDebug.h>
#include "mainloop.h"
#include "consolemode.h"
#ifdef _MSC_VER
#pragma warning (push,3)
#endif
#include "systimer.h"
#ifdef _MSC_VER
#pragma warning (pop)
#endif
using namespace WWOnline;
static void PrintableSize(unsigned long size, WideStringClass& printable);
static void PrintableTime(unsigned long seconds, WideStringClass& printable);
bool DlgDownload::mQuietMode = false;
/******************************************************************************
*
* NAME
* DlgDownload::DoDialog
*
* DESCRIPTION
* Start download dialog
*
* INPUTS
* Title - Dialog title
* Files - List of files to download
*
* RESULT
* Success - True if dialog successfully started.
*
******************************************************************************/
bool DlgDownload::DoDialog(const WCHAR* title, const DownloadList& files, bool quiet)
{
if (!files.empty())
{
mQuietMode = quiet;
DlgDownload* popup = new DlgDownload;
if (popup)
{
if (popup->FinalizeCreate(files))
{
popup->Start_Dialog();
popup->Set_Title(title);
}
popup->Release_Ref();
}
return (popup != NULL);
}
return false;
}
/******************************************************************************
*
* NAME
* DlgDownload::DlgDownload
*
* DESCRIPTION
* Constructor
*
* INPUTS
* NONE
*
* RESULT
* NONE
*
******************************************************************************/
DlgDownload::DlgDownload() :
PopupDialogClass(IDD_WOL_DOWNLOAD),
mDownloading(false)
{
WWDEBUG_SAY(("DlgDownload: Instantiated\n"));
}
/******************************************************************************
*
* NAME
* DlgDownload::~DlgDownload
*
* DESCRIPTION
* Destructor
*
* INPUTS
* NONE
*
* RESULT
* NONE
*
******************************************************************************/
DlgDownload::~DlgDownload()
{
WWDEBUG_SAY(("DlgDownload: Destructing\n"));
}
/******************************************************************************
*
* NAME
* DlgDownload::FinalizeCreate
*
* DESCRIPTION
* Finalize the dialog creation.
*
* INPUTS
* Files - List of files to download.
*
* RESULT
* True if successful.
*
******************************************************************************/
bool DlgDownload::FinalizeCreate(const DownloadList& files)
{
mWait = DownloadWait::Create(files);
return mWait.IsValid();
}
/******************************************************************************
*
* NAME
* DlgDownload::On_Init_Dialog
*
* DESCRIPTION
* One time dialog initialization.
*
* INPUTS
* NONE
*
* RESULT
* NONE
*
******************************************************************************/
void DlgDownload::On_Init_Dialog(void)
{
// Set estimated time and read / total
WideStringClass text(0, true);
text.Format(TRANSLATE(IDS_MENU_TRANSFER_RATE_TIME), 0, 0, 0);
Set_Dlg_Item_Text(IDC_PROGRESSTEXT, text);
// Update transfer rate.
text.Format(TRANSLATE(IDS_MENU_TRANSFER_RATE), 0);
Set_Dlg_Item_Text(IDC_TRANSFERTEXT, text);
// Start the wait condition
mWait->SetCallback(DlgDownload::HandleCallback, (unsigned long)this);
mWait->WaitBeginning();
PopupDialogClass::On_Init_Dialog();
}
/******************************************************************************
*
* NAME
* DlgDownload::On_Command
*
* DESCRIPTION
* Process command message
*
* INPUTS
* Ctrl - ID of control
* Message -
* Param -
*
* RESULT
* NONE
*
******************************************************************************/
void DlgDownload::On_Command(int ctrl, int message, DWORD param)
{
if (ctrl == IDCANCEL)
{
WWDEBUG_SAY(("DlgDownload: User Aborted\n"));
mWait->EndWait(WaitCondition::UserCancel, TRANSLATE(IDS_WOL_CANCELED));
}
PopupDialogClass::On_Command(ctrl, message, param);
}
/******************************************************************************
*
* NAME
* DlgDownload::On_Periodic
*
* DESCRIPTION
*
* INPUTS
* NONE
*
* RESULT
* NONE
*
******************************************************************************/
void DlgDownload::On_Periodic(void)
{
PopupDialogClass::On_Periodic();
// Check the status of the wait condition
WaitCondition::WaitResult waitStatus = mWait->GetResult();
// If we are no longer waiting then process the result.
if (waitStatus != WaitCondition::Waiting)
{
if (waitStatus == WaitCondition::ConditionMet)
{
if (mQuietMode)
{
ConsoleBox.Print("Restarting....\n");
Stop_Main_Loop(RESTART_EXITCODE);
}
else
{
DlgRestart::DoDialog();
}
}
else
{
// If the download was aborted or errored then show a message dialog
// describing the failure.
DlgMsgBox::DoDialog(TRANSLATE(IDS_WOL_DOWNLOADERROR), mWait->GetResultText());
}
End_Dialog();
}
}
/******************************************************************************
*
* NAME
* DlgDownload::UpdateProgress
*
* DESCRIPTION
*
* INPUTS
*
* RESULT
* NONE
*
******************************************************************************/
void DlgDownload::UpdateProgress(DownloadEvent& event)
{
const RefPtr<Download>& download = event.GetDownload();
switch (event.GetEvent())
{
case DownloadEvent::DOWNLOAD_STATUS:
Set_Dlg_Item_Text(IDC_STATUSTEXT, download->GetStatusText());
break;
case DownloadEvent::DOWNLOAD_PROGRESS:
{
int read = 0;
int size = 0;
int elapsed = 0;
int remaining = 0;
download->GetProgress(read, size, elapsed, remaining);
if (ConsoleBox.Is_Exclusive())
{
if (!mDownloading)
{
mStartTime = TIMEGETTIME();
mDownloading = true;
}
// Calculate the transfer rate
unsigned long transferRate = read;
unsigned long elapsedTime = ((TIMEGETTIME() - mStartTime) / 1000);
if (elapsedTime > 0)
{
transferRate = (read / elapsedTime);
}
ConsoleBox.Print("Got %d Kb of %d at %d Kb per second \r", read/1024, size/1024, transferRate / 1024);
}
else
{
// Update progress bar
ProgressCtrlClass* progress = (ProgressCtrlClass*)Get_Dlg_Item(IDC_PROGRESS);
if (progress)
{
// If we have just begun downloading then set the progress bar range
// for the size of the new file.
if (!mDownloading)
{
progress->Set_Range(0, size);
mStartTime = TIMEGETTIME();
mDownloading = true;
}
progress->Set_Position(read);
}
//-----------------------------------------------------------------------
// Update download statistics
//-----------------------------------------------------------------------
// Calculate the transfer rate
unsigned long transferRate = read;
unsigned long elapsedTime = ((TIMEGETTIME() - mStartTime) / 1000);
if (elapsedTime > 0)
{
transferRate = (read / elapsedTime);
}
// Update transfer rate.
WideStringClass sizetext(64, true);
PrintableSize(transferRate, sizetext);
WideStringClass text(0, true);
text.Format(TRANSLATE(IDS_MENU_TRANSFER_RATE_PER_SEC), (const WCHAR*)sizetext);
Set_Dlg_Item_Text(IDC_TRANSFERTEXT, text);
// Calculate estimated time based on the current transfer rate.
unsigned long estimatedTime = 0;
if (transferRate > 0)
{
estimatedTime = ((size - read) / transferRate);
}
// Update estimated time and read / total
WideStringClass timetext(64,true);
PrintableTime(estimatedTime, timetext);
WideStringClass readtext(64, true);
PrintableSize(read, readtext);
PrintableSize(size, sizetext);
text.Format(TRANSLATE(IDS_MENU_TRANSFER_TIME_LEFT),
(const WCHAR*)timetext, (const WCHAR*)readtext, (const WCHAR*)sizetext);
Set_Dlg_Item_Text(IDC_PROGRESSTEXT, text);
}
}
break;
case DownloadEvent::DOWNLOAD_BEGIN:
if (ConsoleBox.Is_Exclusive())
{
ConsoleBox.Print("\n");
}
break;
case DownloadEvent::DOWNLOAD_END:
if (ConsoleBox.Is_Exclusive())
{
ConsoleBox.Print("\nDownload complete\n");
}
WWDEBUG_SAY(("DlgDownload: Successful '%s' Elapsed time: %ld ms\n",
download->GetFilename(), (TIMEGETTIME() - mStartTime)));
mDownloading = false;
break;
case DownloadEvent::DOWNLOAD_STOPPED:
WWDEBUG_SAY(("DlgDownload: Stopped '%s'\n", download->GetFilename()));
mDownloading = false;
break;
case DownloadEvent::DOWNLOAD_ERROR:
WWDEBUG_SAY(("DlgDownload: Error '%s'\n", download->GetFilename()));
mDownloading = false;
break;
default:
break;
}
}
/******************************************************************************
*
* NAME
* DlgDownload::HandleCallback
*
* DESCRIPTION
*
* INPUTS
*
* RESULT
* NONE
*
******************************************************************************/
void DlgDownload::HandleCallback(DownloadEvent& event, unsigned long userdata)
{
DlgDownload* dialog = (DlgDownload*)userdata;
if (dialog)
{
dialog->UpdateProgress(event);
}
}
/******************************************************************************
*
* NAME
* PrintableSize
*
* DESCRIPTION
* Get filesize in a printable format.
*
* INPUTS
* Size -
*
* RESULT
* NONE
*
******************************************************************************/
void PrintableSize(unsigned long size, WideStringClass& printable)
{
float value = ((float)size / (float)(1024 * 1024));
if (value >= 1.0)
{
printable.Format(TRANSLATE(IDS_MENU_TRANSFER_MB_FORMAT), value);
return;
}
value = ((float)size / 1024.0);
if (value >= 1.0)
{
printable.Format(TRANSLATE(IDS_MENU_TRANSFER_KB_FORMAT), value);
return;
}
printable.Format(TRANSLATE(IDS_MENU_TRANSFER_BYTE_FORMAT), size);
}
/******************************************************************************
*
* NAME
* PrintableTime
*
* DESCRIPTION
* Get time in a printable format.
*
* INPUTS
* Size -
*
* RESULT
* NONE
*
******************************************************************************/
void PrintableTime(unsigned long time, WideStringClass& printable)
{
unsigned long minutes = (time / 60);
unsigned long seconds = (time % 60);
if (minutes > 0)
{
printable.Format(TRANSLATE(IDS_MENU_TRANSFER_MIN_SEC_FORMAT), minutes, seconds);
}
else
{
seconds = max<unsigned long>(seconds, 1);
printable.Format(TRANSLATE(IDS_MENU_TRANSFER_SEC_FORMAT), seconds);
}
}

View File

@@ -0,0 +1,74 @@
/*
** 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/>.
*/
/******************************************************************************
*
* FILE
* $Archive: /Commando/Code/Commando/DlgDownload.h $
*
* DESCRIPTION
* File download dialog.
*
* PROGRAMMER
* Denzil E. Long, Jr.
* $Author: Denzil_l $
*
* VERSION INFO
* $Revision: 5 $
* $Modtime: 12/20/01 9:43a $
*
******************************************************************************/
#ifndef __DLGDOWNLOAD_H__
#define __DLGDOWNLOAD_H__
#include <WWUI\PopupDialog.h>
#include <WWOnline\WOLDownload.h>
class DlgDownload :
public PopupDialogClass
{
public:
static bool DoDialog(const WCHAR* title, const WWOnline::DownloadList& files, bool quiet = false);
protected:
DlgDownload();
~DlgDownload();
// Prevent copy and assignment
DlgDownload(const DlgDownload&);
const DlgDownload& operator=(const DlgDownload&);
bool FinalizeCreate(const WWOnline::DownloadList& files);
void On_Init_Dialog(void);
void On_Command(int ctrl, int message, DWORD param);
void On_Periodic(void);
void UpdateProgress(WWOnline::DownloadEvent& event);
static void HandleCallback(WWOnline::DownloadEvent& event, unsigned long userdata);
private:
RefPtr<WWOnline::DownloadWait> mWait;
unsigned long mStartTime;
bool mDownloading;
static bool mQuietMode;
};
#endif // __DLGDOWNLOAD_H__

View File

@@ -0,0 +1,294 @@
/*
** 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/>.
*/
/******************************************************************************
*
* NAME
* $Archive: /Commando/Code/Commando/DlgMPConnect.cpp $
*
* DESCRIPTION
* Dialog to inform user that we are connecting to a game host.
*
* PROGRAMMER
* Denzil E. Long, Jr.
* $Author: Tom_s $
*
* VERSION INFO
* $Revision: 12 $
* $Modtime: 2/25/02 11:29a $
*
******************************************************************************/
#include "dlgmpconnect.h"
#include "gamedata.h"
#include "gameinitmgr.h"
#include "campaign.h"
#include "cnetwork.h"
#include "resource.h"
#include <wwdebug\wwdebug.h>
#include "dlgmainmenu.h"
#include "gamespyadmin.h"
#include "specialbuilds.h"
#include "dialogtests.h"
#include "dialogmgr.h"
#include "gamemode.h"
#include "langmode.h"
#include "wolgmode.h"
/******************************************************************************
*
* NAME
* DlgMPConnect::DoDialog
*
* DESCRIPTION
*
* INPUTS
* NONE
*
* RESULT
* True if dialog created successfully.
*
******************************************************************************/
bool DlgMPConnect::DoDialog(int teamChoice, unsigned long clanID)
{
DlgMPConnect* popup = new DlgMPConnect(teamChoice, clanID);
if (popup)
{
popup->Start_Dialog();
popup->Release_Ref();
}
return (popup != NULL);
}
/******************************************************************************
*
* NAME
* DlgMPConnect::DlgMPConnect
*
* DESCRIPTION
* Constructor
*
* INPUTS
* NONE
*
* RESULT
* NONE
*
******************************************************************************/
DlgMPConnect::DlgMPConnect(int teamChoice, unsigned long clanID) :
PopupDialogClass(IDD_MULTIPLAY_CONNECTING),
mTeamChoice(teamChoice),
mClanID(clanID),
mTheGame(NULL),
mFailed(false)
{
WWDEBUG_SAY(("DlgMPConnect: Instantiated\n"));
}
/******************************************************************************
*
* NAME
* DlgMPConnect::~DlgMPConnect
*
* DESCRIPTION
* Destructor
*
* INPUTS
* NONE
*
* RESULT
* NONE
*
******************************************************************************/
DlgMPConnect::~DlgMPConnect()
{
WWDEBUG_SAY(("DlgMPConnect: Destructing\n"));
}
/******************************************************************************
*
* NAME
* DlgMPConnect::Connected
*
* DESCRIPTION
* Handle connection.
*
* INPUTS
* GameData - Pointer to game data instance
*
* RESULT
* NONE
*
******************************************************************************/
void DlgMPConnect::Connected(cGameData* theGame)
{
mTheGame = theGame;
}
/******************************************************************************
*
* NAME
* DlgMPConnect::Connected
*
* DESCRIPTION
* Handle connection.
*
* INPUTS
* GameData - Pointer to game data instance
*
* RESULT
* NONE
*
******************************************************************************/
void DlgMPConnect::Failed_To_Connect(void)
{
mFailed = true;
}
/******************************************************************************
*
* NAME
* DlgMPConnect::On_Command
*
* DESCRIPTION
* Process command messages from controls
*
* INPUTS
* Ctrl - ID of control
* Message -
* Param - 0 = User invoked abort. 1 = Connection refused by server.
*
* RESULT
* NONE
*
******************************************************************************/
void DlgMPConnect::On_Command(int ctrlID, int message, DWORD param)
{
if ((IDCANCEL == ctrlID) && (1 != param))
{
if (cNetwork::I_Am_Client())
{
cNetwork::Cleanup_Client();
}
if (cGameSpyAdmin::Get_Is_Launched_From_Gamespy())
{
extern void Stop_Main_Loop (int);
Stop_Main_Loop(EXIT_SUCCESS);
}
else if (DialogMgrClass::Get_Dialog_Count () == 1)
{
START_DIALOG (MainMenuDialogClass);
}
}
PopupDialogClass::On_Command(ctrlID, message, param);
}
/******************************************************************************
*
* NAME
* DlgMPConnect::On_Periodic
*
* DESCRIPTION
*
* INPUTS
* NONE
*
* RESULT
* NONE
*
******************************************************************************/
void DlgMPConnect::On_Periodic(void)
{
PopupDialogClass::On_Periodic();
if (mTheGame != NULL)
{
// Add a reference to keep us alive while we process the game start
Add_Ref();
// Remove the dialog from menuing system
End_Dialog();
// Check to ensure the settings are playable
WideStringClass outMsg;
if (mTheGame->Is_Valid_Settings(outMsg))
{
WWDEBUG_SAY(("DlgMPConnect: Starting the game.\n"));
CampaignManager::Select_Backdrop_Number_By_MP_Type(mTheGame->Get_Game_Type());
// Start the game!
GameInitMgrClass::Set_Is_Client_Required(true);
GameInitMgrClass::Set_Is_Server_Required(false);
GameInitMgrClass::Start_Game(mTheGame->Get_Map_Name(), mTeamChoice, mClanID);
}
else
{
WWDEBUG_SAY(("ERROR: %s\n", (const WCHAR*)outMsg));
}
// Release the keep alive reference (this will delete this object)
Release_Ref();
}
else
{
if (mFailed)
{
Add_Ref();
// Remove the dialog from menuing system
End_Dialog();
if (GameModeManager::Find("LAN")->Is_Active())
{
PLC->Refusal_Actions();
}
else
{
GameModeClass* gameMode = GameModeManager::Find("WOL");
if (gameMode && gameMode->Is_Active())
{
WolGameModeClass* wolGame = static_cast<WolGameModeClass*>(gameMode);
WWASSERT(wolGame);
wolGame->Refusal_Actions();
}
}
Release_Ref();
}
}
}

View File

@@ -0,0 +1,76 @@
/*
** 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/>.
*/
/******************************************************************************
*
* NAME
* $Archive: /Commando/Code/Commando/DlgMPConnect.h $
*
* DESCRIPTION
* Dialog to inform user that we are connecting to a game host.
*
* PROGRAMMER
* Denzil E. Long, Jr.
* $Author: Steve_t $
*
* VERSION INFO
* $Revision: 4 $
* $Modtime: 2/14/02 2:03p $
*
******************************************************************************/
#ifndef __DLGMPCONNECT_H__
#define __DLGMPCONNECT_H__
#include <WWUI\PopupDialog.h>
class cGameData;
class DlgMPConnect :
public PopupDialogClass
{
public:
// Display connecting dialog.
// TeamChoice - Team preference of connecting player
// ClanID - ID of players clan (0 if not a clan game)
static bool DoDialog(int teamChoice, unsigned long clanID);
void Connected(cGameData* theGame);
void Failed_To_Connect(void);
protected:
DlgMPConnect(int teamChoice, unsigned long clanID);
virtual ~DlgMPConnect();
void On_Command(int ctrl, int message, DWORD param);
void On_Periodic(void);
private:
// Prevent copy and assignment
DlgMPConnect(const DlgMPConnect&);
const DlgMPConnect& operator=(const DlgMPConnect&);
int mTeamChoice;
unsigned long mClanID;
cGameData* mTheGame;
bool mFailed;
};
#endif // __DLGMPCONNECT_H__

View File

@@ -0,0 +1,195 @@
/*
** 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/>.
*/
/******************************************************************************
*
* NAME
* $Archive: /Commando/Code/Commando/DlgMPConnectionRefused.cpp $
*
* DESCRIPTION
*
******************************************************************************/
#include "DlgMPConnectionRefused.h"
#include "cnetwork.h"
#include "resource.h"
#include <wwdebug\wwdebug.h>
#include "dlgmainmenu.h"
#include "gamespyadmin.h"
#include "specialbuilds.h"
#include "dialogtests.h"
#include "dialogmgr.h"
#include "gameinitmgr.h"
/******************************************************************************
*
* NAME
* DlgMPConnectionRefused::DoDialog
*
* DESCRIPTION
*
* INPUTS
* NONE
*
* RESULT
* True if dialog created successfully.
*
******************************************************************************/
bool DlgMPConnectionRefused::DoDialog(const WCHAR * text, bool show_splash_screen)
{
DlgMPConnectionRefused* popup = new DlgMPConnectionRefused(text, show_splash_screen);
if (popup)
{
popup->Start_Dialog();
popup->Release_Ref();
}
return (popup != NULL);
}
/******************************************************************************
*
* NAME
* DlgMPConnectionRefused::DlgMPConnectionRefused
*
* DESCRIPTION
* Constructor
*
* INPUTS
* NONE
*
* RESULT
* NONE
*
******************************************************************************/
DlgMPConnectionRefused::DlgMPConnectionRefused(const WCHAR * text, bool show_splash_screen) :
PopupDialogClass(IDD_MULTIPLAY_CONNECTION_REFUSED)
{
WWDEBUG_SAY(("DlgMPConnectionRefused: Instantiated\n"));
WWASSERT(text != NULL);
Text.Format(text);
ShowSplashScreen = show_splash_screen;
}
/******************************************************************************
*
* NAME
* DlgMPConnectionRefused::~DlgMPConnectionRefused
*
* DESCRIPTION
* Destructor
*
* INPUTS
* NONE
*
* RESULT
* NONE
*
******************************************************************************/
DlgMPConnectionRefused::~DlgMPConnectionRefused()
{
WWDEBUG_SAY(("DlgMPConnectionRefused: Destructing\n"));
}
/******************************************************************************
*
* NAME
* DlgMPConnectionRefused::On_Init_Dialog
*
* DESCRIPTION
*
* INPUTS
* NONE
*
* RESULT
* NONE
*
******************************************************************************/
void DlgMPConnectionRefused::On_Init_Dialog(void)
{
Set_Dlg_Item_Text(IDC_REFUSAL_TEXT, Text);
PopupDialogClass::On_Init_Dialog();
}
/******************************************************************************
*
* NAME
* DlgMPConnectionRefused::On_Command
*
* DESCRIPTION
* Process command messages from controls
*
* INPUTS
* Ctrl - ID of control
* Message -
* Param - 0 = User invoked abort. 1 = Connection refused by server.
*
* RESULT
* NONE
*
******************************************************************************/
void DlgMPConnectionRefused::On_Command(int ctrlID, int message, DWORD param)
{
if ((IDOK == ctrlID) && (1 != param))
{
if (cNetwork::I_Am_Client())
{
cNetwork::Cleanup_Client();
}
if (cGameSpyAdmin::Get_Is_Launched_From_Gamespy())
{
#ifdef MULTIPLAYERDEMO
GameInitMgrClass::End_Game ();
if (ShowSplashScreen)
{
DialogMgrClass::Flush_Dialogs ();
START_DIALOG (SplashOutroMenuDialogClass);
}
else
{
extern void Stop_Main_Loop (int);
Stop_Main_Loop(EXIT_SUCCESS);
}
#else
extern void Stop_Main_Loop (int);
Stop_Main_Loop(EXIT_SUCCESS);
#endif // MULTIPLAYERDEMO
}
else if (DialogMgrClass::Get_Dialog_Count () == 1)
{
START_DIALOG (MainMenuDialogClass);
}
}
PopupDialogClass::On_Command(ctrlID, message, param);
}

View File

@@ -0,0 +1,55 @@
/*
** 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/>.
*/
/******************************************************************************
*
* NAME
* $Archive: /Commando/Code/Commando/DlgMPConnectionRefused.h $
*
* DESCRIPTION
*
******************************************************************************/
#ifndef __DLGMPCONNECTIONREFUSED_H__
#define __DLGMPCONNECTIONREFUSED_H__
#include <WWUI\PopupDialog.h>
class DlgMPConnectionRefused :
public PopupDialogClass
{
public:
static bool DoDialog(const WCHAR * text, bool show_splash_screen);
void On_Init_Dialog(void);
protected:
DlgMPConnectionRefused(const WCHAR * text, bool show_splash_screen);
virtual ~DlgMPConnectionRefused();
void On_Command(int ctrl, int message, DWORD param);
private:
// Prevent copy and assignment
DlgMPConnectionRefused(const DlgMPConnectionRefused&);
const DlgMPConnectionRefused& operator=(const DlgMPConnectionRefused&);
WideStringClass Text;
bool ShowSplashScreen;
};
#endif // __DLGMPCONNECTIONREFUSED_H__

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,112 @@
/*
** 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/>.
*/
/******************************************************************************
*
* FILE
* $Archive: /Commando/Code/Commando/DlgMPTeamSelect.h $
*
* DESCRIPTION
* Multiplayer team selection dialog.
*
* PROGRAMMER
* Denzil E. Long, Jr.
* $Author: Denzil_l $
*
* VERSION INFO
* $Revision: 8 $
* $Modtime: 2/11/02 11:28a $
*
******************************************************************************/
#ifndef __DLGMPTEAMSELECT_H__
#define __DLGMPTEAMSELECT_H__
#include "PlayerManager.h"
#include <WWUI\MenuDialog.h>
#include <WWLib\Notify.h>
#include <WWLib\Signaler.h>
#include <WWOnline\RefPtr.h>
#include "WOLGameInfo.h"
namespace WWOnline
{
class Session;
class ChannelEvent;
class UserEvent;
class GameOptionsMessage;
};
class cPlayer;
typedef TypedEventPair<bool, int> MPChooseTeamSignal;
class DlgMPTeamSelect :
public MenuDialogClass,
protected Signaler<MPChooseTeamSignal>,
protected Observer<WWOnline::ChannelEvent>,
protected Observer<WWOnline::UserEvent>,
protected Observer<WWOnline::GameOptionsMessage>,
protected Observer<PlayerMgrEvent>
{
public:
static void DoDialog(Signaler<MPChooseTeamSignal>& target);
protected:
DlgMPTeamSelect(void);
~DlgMPTeamSelect();
bool FinalizeCreate(void);
void On_Init_Dialog(void);
void On_Frame_Update(void);
void On_Command(int ctrlID, int message, DWORD param);
void On_Last_Menu_Ending(void);
void InitSideChoice(int sidePref);
void SelectSideChoice(int side);
int GetSideChoice(void);
void RequestWOLGameInfo(void);
void ShowTimeRemaining(float remainingSecond);
bool FindPlayerInListCtrl(const WCHAR* name, ListCtrlClass*& outList, int& outIndex);
void HandleNotification(WWOnline::ChannelEvent&);
void HandleNotification(WWOnline::UserEvent&);
void HandleNotification(WWOnline::GameOptionsMessage&);
void HandleNotification(PlayerMgrEvent&);
static void ProcessWOLGameInfo(DlgMPTeamSelect& dialog, const char* data);
static void ProcessWOLTeamInfo(DlgMPTeamSelect& dialog, const char* data);
static void ProcessWOLPlayerInfo(DlgMPTeamSelect& dialog, const char* data);
void PopulateWithLANPlayers(void);
void AddLANPlayerInfo(cPlayer* lanPlayer);
void RemoveLANPlayerInfo(cPlayer* lanPlayer);
protected:
bool mWOLGame;
bool mCanChoose;
float mTimeRemaining;
RefPtr<WWOnline::Session> mWOLSession;
WOLGameInfo mGameInfo;
};
#endif // __DLGMPTEAMSELECT_H__

View File

@@ -0,0 +1,277 @@
/*
** 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/>.
*/
/******************************************************************************
*
* NAME
* $Archive: /Commando/Code/Commando/DlgMessageBox.cpp $
*
* DESCRIPTION
* Popup message dialog.
*
* PROGRAMMER
* Denzil E. Long, Jr.
* $Author: Denzil_l $
*
* VERSION INFO
* $Revision: 7 $
* $Modtime: 10/02/01 2:42p $
*
******************************************************************************/
#include "DlgMessageBox.h"
#include "Resource.h"
#include <WWTranslateDB\TranslateDB.h>
#include "WWDebug.h"
//
// Class statics
//
int DlgMsgBox::CurrentCount = 0;
/******************************************************************************
*
* NAME
* DlgMsgBox::DoDialog
*
* DESCRIPTION
* Create a Popup message box dialog.
*
* INPUTS
* Title - Message box title
* Text - Message content
*
* RESULT
* Object - Instance of message box
*
******************************************************************************/
bool DlgMsgBox::DoDialog(const WCHAR* title, const WCHAR* text,
DlgMsgBox::Type type, Observer<DlgMsgBoxEvent>* observer, unsigned long user_data)
{
DlgMsgBox* popup = new DlgMsgBox;
if (popup)
{
popup->SetResourceType(type);
popup->Start_Dialog();
popup->Set_Title(title);
popup->Set_Dlg_Item_Text(IDC_MESSAGE, text);
popup->Set_User_Data(user_data);
if (observer)
{
popup->AddObserver(*observer);
}
popup->Release_Ref();
}
return (popup != NULL);
}
/******************************************************************************
*
* NAME
* DlgMsgBox::DoDialog
*
* DESCRIPTION
* Create a Popup message box dialog.
*
* INPUTS
* TitleID - ID of message box title
* TextID - ID of message content
*
* RESULT
* Object - Instance of message box
*
******************************************************************************/
bool DlgMsgBox::DoDialog(int titleID, int textID,
DlgMsgBox::Type type, Observer<DlgMsgBoxEvent>* observer, unsigned long user_data)
{
const WCHAR* title = TranslateDBClass::Get_String(titleID);
const WCHAR* text = TranslateDBClass::Get_String(textID);
return DoDialog(title, text, type, observer, user_data);
}
/******************************************************************************
*
* NAME
* DlgMsgBox::DlgMsgBox
*
* DESCRIPTION
* Constructor
*
* INPUTS
* NONE
*
* RESULT
* NONE
*
******************************************************************************/
DlgMsgBox::DlgMsgBox() :
mUserData(0),
PopupDialogClass(IDD_MESSAGEBOX_OK)
{
CurrentCount++;
}
/******************************************************************************
*
* NAME
* DlgMsgBox::~DlgMsgBox
*
* DESCRIPTION
* Destructor
*
* INPUTS
* NONE
*
* RESULT
* NONE
*
******************************************************************************/
DlgMsgBox::~DlgMsgBox()
{
CurrentCount--;
WWASSERT(CurrentCount >= 0);
}
/******************************************************************************
*
* NAME
* DlgMsgBox::SetResourceType
*
* DESCRIPTION
* Set the type of dialog box to use.
*
* INPUTS
*
* RESULT
*
******************************************************************************/
void DlgMsgBox::SetResourceType(DlgMsgBox::Type type)
{
static UINT _types[] =
{
IDD_MESSAGEBOX_OK,
IDD_MESSAGEBOX_YESNO
};
DialogResID = _types[type];
}
/******************************************************************************
*
* NAME
* DlgMsgBox::End_Dialog
*
* DESCRIPTION
*
* INPUTS
* NONE
*
* RESULT
* NONE
*
******************************************************************************/
void DlgMsgBox::End_Dialog(void)
{
Add_Ref();
DlgMsgBoxEvent event(DlgMsgBoxEvent::Quitting, this, mUserData);
NotifyObservers(event);
Release_Ref();
PopupDialogClass::End_Dialog();
}
/******************************************************************************
*
* NAME
* DlgMsgBox::On_Command
*
* DESCRIPTION
* Process command message
*
* INPUTS
* Ctrl - ID of control
* Message -
* Param -
*
* RESULT
* NONE
*
******************************************************************************/
void DlgMsgBox::On_Command(int ctrl, int message, DWORD param)
{
switch (ctrl)
{
case IDOK:
{
Add_Ref();
DlgMsgBoxEvent event(DlgMsgBoxEvent::Okay, this, mUserData);
NotifyObservers(event);
Release_Ref();
End_Dialog();
}
break;
case IDYES:
{
Add_Ref();
DlgMsgBoxEvent event(DlgMsgBoxEvent::Yes, this, mUserData);
NotifyObservers(event);
Release_Ref();
End_Dialog();
}
break;
case IDNO:
{
Add_Ref();
DlgMsgBoxEvent event(DlgMsgBoxEvent::No, this, mUserData);
NotifyObservers(event);
Release_Ref();
End_Dialog();
}
break;
default:
PopupDialogClass::On_Command(ctrl, message, param);
break;
}
}

View File

@@ -0,0 +1,131 @@
/*
** 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/>.
*/
/******************************************************************************
*
* NAME
* $Archive: /Commando/Code/Commando/DlgMessageBox.h $
*
* DESCRIPTION
* Popup message dialog.
*
* PROGRAMMER
* Denzil E. Long, Jr.
* $Author: Denzil_l $
*
* VERSION INFO
* $Revision: 8 $
* $Modtime: 10/13/01 4:50p $
*
******************************************************************************/
#ifndef __DLGMESSAGEBOX_H__
#define __DLGMESSAGEBOX_H__
#include <WWUI\PopupDialog.h>
#include <WWLib\Notify.h>
class DlgMsgBox;
class DlgMsgBoxEvent :
public TypedEventPtr<DlgMsgBoxEvent, DlgMsgBox>
{
public:
typedef enum
{
None = 0, // NULL event
Okay, // Okay button pressed
Yes, // Yes button pressed
No, // No button pressed
Quitting, // Dialog quitting.
} EventID;
//! Retrieve event
inline EventID Event(void) const
{return mEvent;}
//! User data access
inline unsigned long Get_User_Data(void) const
{return mUserData;}
inline void Set_User_Data(unsigned long data)
{mUserData = data;}
DlgMsgBoxEvent(EventID event, DlgMsgBox* object, unsigned long user_data) :
TypedEventPtr<DlgMsgBoxEvent, DlgMsgBox>(object),
mEvent(event), mUserData (user_data)
{}
protected:
// Prevent copy and assignment
DlgMsgBoxEvent(const DlgMsgBoxEvent&);
const DlgMsgBoxEvent& operator=(const DlgMsgBoxEvent&);
private:
EventID mEvent;
unsigned long mUserData;
};
class DlgMsgBox :
public PopupDialogClass,
public Notifier<DlgMsgBoxEvent>
{
public:
typedef enum
{
Okay = 0, // Message box with okay button (Default)
YesNo, // Yes/No message box
} Type;
static bool DoDialog(const WCHAR* title, const WCHAR* text,
DlgMsgBox::Type type = DlgMsgBox::Okay, Observer<DlgMsgBoxEvent>* observer = NULL,
unsigned long user_data = 0);
static bool DoDialog(int titleID, int textID, DlgMsgBox::Type type = DlgMsgBox::Okay,
Observer<DlgMsgBoxEvent>* observer = NULL, unsigned long user_data = 0);
void Set_User_Data(unsigned long user_data)
{mUserData = user_data;}
unsigned long Get_User_Data(void) const
{return mUserData;}
static int Get_Current_Count(void)
{return CurrentCount;}
protected:
DlgMsgBox();
virtual ~DlgMsgBox();
void SetResourceType(DlgMsgBox::Type type);
void End_Dialog(void);
void On_Command(int ctrl, int message, DWORD param);
DECLARE_NOTIFIER(DlgMsgBoxEvent)
private:
// Prevent copy and assignment
DlgMsgBox(const DlgMsgBox&);
const DlgMsgBox& operator=(const DlgMsgBox&);
static int CurrentCount;
unsigned long mUserData;
};
#endif // __DLGMESSAGEBOX_H__

View File

@@ -0,0 +1,256 @@
/*
** 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/>.
*/
/******************************************************************************
*
* FILE
* $Archive: /Commando/Code/Commando/DlgPasswordPrompt.cpp $
*
* DESCRIPTION
* General purpose password entry dialog for joining a game.
*
* PROGRAMMER
* Denzil E. Long, Jr.
* $Author: Denzil_l $
*
* VERSION INFO
* $Revision: 3 $
* $Modtime: 11/29/01 9:19p $
*
******************************************************************************/
#include "DlgPasswordPrompt.h"
#include <WWUI\EditCtrl.h>
/******************************************************************************
*
* NAME
* DlgPasswordPrompt::DoDialog
*
* DESCRIPTION
* Create a dialog to prompt the user to enter a password.
*
* INPUTS
* Target - Target to receive signal that a password was entered.
*
* RESULT
* True if dialog created successfully.
*
******************************************************************************/
bool DlgPasswordPrompt::DoDialog(Signaler<DlgPasswordPrompt>* target)
{
DlgPasswordPrompt* dialog = new DlgPasswordPrompt;
if (dialog)
{
dialog->Start_Dialog();
if (target)
{
dialog->SignalMe(*target);
}
dialog->Release_Ref();
}
return (dialog != NULL);
}
/******************************************************************************
*
* NAME
* DlgPasswordPrompt::DlgPasswordPrompt
*
* DESCRIPTION
* Constructor
*
* INPUTS
* NONE
*
* RESULT
* NONE
*
******************************************************************************/
DlgPasswordPrompt::DlgPasswordPrompt() :
PopupDialogClass(IDD_MP_JOIN_PASSWORD)
{
WWDEBUG_SAY(("DlgPasswordPrompt Instantiated\n"));
}
/******************************************************************************
*
* NAME
* DlgPasswordPrompt::~DlgPasswordPrompt
*
* DESCRIPTION
* Destructor
*
* INPUTS
* NONE
*
* RESULT
* NONE
*
******************************************************************************/
DlgPasswordPrompt::~DlgPasswordPrompt()
{
WWDEBUG_SAY(("DlgPasswordPrompt Destroyed\n"));
}
/******************************************************************************
*
* NAME
* DlgPasswordPrompt::GetPassword
*
* DESCRIPTION
* Retrieve the password entered by the user.
*
* INPUTS
* NONE
*
* RESULT
* Password - Pointer to password string.
*
******************************************************************************/
const WCHAR* DlgPasswordPrompt::GetPassword(void) const
{
return Get_Dlg_Item_Text(IDC_PASSWORD_EDIT);
}
/******************************************************************************
*
* NAME
* DlgPasswordPrompt::On_Init_Dialog
*
* DESCRIPTION
* One time dialog initialization.
*
* INPUTS
* NONE
*
* RESULT
* NONE
*
******************************************************************************/
void DlgPasswordPrompt::On_Init_Dialog(void)
{
// Disable the join button until the user enters text.
Enable_Dlg_Item(IDC_JOIN_GAME_BUTTON, false);
EditCtrlClass* edit = (EditCtrlClass*)Get_Dlg_Item(IDC_PASSWORD_EDIT);
if (edit)
{
edit->Set_Focus();
}
PopupDialogClass::On_Init_Dialog();
}
/******************************************************************************
*
* NAME
* DlgPasswordPrompt::On_Command
*
* DESCRIPTION
* Handle command messages from dialog controls.
*
* INPUTS
* CtrlID - ID of control sending command.
* Message - Message identifier.
* Param - Message parameter
*
* RESULT
* NONE
*
******************************************************************************/
void DlgPasswordPrompt::On_Command(int ctrlID, int message, DWORD param)
{
if (IDC_JOIN_GAME_BUTTON == ctrlID)
{
Signaler<DlgPasswordPrompt>::SendSignal(*this);
End_Dialog();
}
PopupDialogClass::On_Command(ctrlID, message, param);
}
/******************************************************************************
*
* NAME
* DlgPasswordPrompt::On_EditCtrl_Change
*
* DESCRIPTION
* Handle notification that the contents of the edit control has changed.
*
* INPUTS
* Edit - Pointer to edit control whose contents has changed.
* ID - Identifier of control.
*
* RESULT
* NONE
*
******************************************************************************/
void DlgPasswordPrompt::On_EditCtrl_Change(EditCtrlClass* edit, int id)
{
if (IDC_PASSWORD_EDIT == id)
{
const WCHAR* text = edit->Get_Text();
bool enableJoin = (text && (wcslen(text) > 0));
Enable_Dlg_Item(IDC_JOIN_GAME_BUTTON, enableJoin);
}
}
/******************************************************************************
*
* NAME
* DlgPasswordPrompt::On_EditCtrl_Enter_Pressed
*
* DESCRIPTION
* Handle notification that the enter key was pressed in an edit control.
*
* INPUTS
* Edit - Pointer to edit control whose contents has changed.
* ID - Identifier of control.
*
* RESULT
* NONE
*
******************************************************************************/
void DlgPasswordPrompt::On_EditCtrl_Enter_Pressed(EditCtrlClass* edit, int id)
{
if ((IDC_PASSWORD_EDIT == id) && Is_Dlg_Item_Enabled(IDC_JOIN_GAME_BUTTON))
{
On_Command(IDC_JOIN_GAME_BUTTON, 0, 0);
}
}

View File

@@ -0,0 +1,63 @@
/*
** 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/>.
*/
/******************************************************************************
*
* FILE
* $Archive: /Commando/Code/Commando/DlgPasswordPrompt.h $
*
* DESCRIPTION
*
* PROGRAMMER
* Denzil E. Long, Jr.
* $Author: Denzil_l $
*
* VERSION INFO
* $Revision: 3 $
* $Modtime: 11/29/01 9:17p $
*
******************************************************************************/
#include "Resource.h"
#include <WWUI\PopupDialog.h>
#include <WWLib\Signaler.h>
class DlgPasswordPrompt :
public PopupDialogClass,
public Signaler<DlgPasswordPrompt>
{
public:
static bool DoDialog(Signaler<DlgPasswordPrompt>* target);
const WCHAR* GetPassword(void) const;
protected:
DlgPasswordPrompt();
~DlgPasswordPrompt();
// Prevent copy and assignment
DlgPasswordPrompt(const DlgPasswordPrompt&);
const DlgPasswordPrompt& operator=(const DlgPasswordPrompt&);
void On_Init_Dialog(void);
void On_Command(int ctrlID, int mesage, DWORD param);
void On_EditCtrl_Change(EditCtrlClass* edit, int id);
void On_EditCtrl_Enter_Pressed(EditCtrlClass* edit, int id);
};

View File

@@ -0,0 +1,498 @@
/*
** 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/>.
*/
/******************************************************************************
*
* NAME
* $Archive: /Commando/Code/Commando/DlgQuickmatch.cpp $
*
* DESCRIPTION
* Quick match dialog
*
* PROGRAMMER
* Denzil E. Long, Jr.
* $Author: Denzil_l $
*
* VERSION INFO
* $Revision: 21 $
* $Modtime: 1/16/02 5:06p $
*
******************************************************************************/
#include "DlgQuickMatch.h"
#include "DlgWOLWait.h"
#include "DlgMessageBox.h"
#include "DlgMPWolQuickMatchOptions.h"
#include "Resource.h"
#include "DialogResource.h"
#include "gameinitmgr.h"
#include "WOLJoinGame.h"
#include "String_IDs.h"
#include <WWTranslateDB\TranslateDB.h>
#include <WWOnline\WaitCondition.h>
#include <WWUI\ListCtrl.h>
#include <WWDebug\WWDebug.h>
#ifdef _MSC_VER
#pragma warning (push,3)
#endif
#include "systimer.h"
#ifdef _MSC_VER
#pragma warning (pop)
#endif
using namespace WWOnline;
/******************************************************************************
*
* NAME
* DlgQuickMatch::DoDialog
*
* DESCRIPTION
*
* INPUTS
*
* RESULT
* Success - True if dialog successfully started.
*
******************************************************************************/
bool DlgQuickMatch::DoDialog(void)
{
DlgQuickMatch* dialog = new DlgQuickMatch;
if (dialog)
{
if (dialog->FinalizeCreate())
{
dialog->Start_Dialog();
}
dialog->Release_Ref();
}
return (dialog != NULL);
}
/******************************************************************************
*
* NAME
* DlgQuickMatch::DlgQuickMatch
*
* DESCRIPTION
* Constructor
*
* INPUTS
* NONE
*
* RESULT
* NONE
*
******************************************************************************/
DlgQuickMatch::DlgQuickMatch() :
MenuDialogClass(IDD_MP_WOL_QUICKMATCH_CONNECT),
mTimeoutTime(0),
mResendTime(0)
{
WWDEBUG_SAY(("DlgQuickMatch: Instantiating\n"));
}
/******************************************************************************
*
* NAME
* DlgQuickMatch::~DlgQuickMatch
*
* DESCRIPTION
* Destructor
*
* INPUTS
* NONE
*
* RESULT
* NONE
*
******************************************************************************/
DlgQuickMatch::~DlgQuickMatch()
{
WWDEBUG_SAY(("DlgQuickMatch: Destructing\n"));
if (mQuickMatch)
{
mQuickMatch->Release_Ref();
}
}
/******************************************************************************
*
* NAME
* DlgQuickMatch::FinalizeCreate
*
* DESCRIPTION
* Finalize the creation of this object (Initialize).
*
* INPUTS
*
* RESULT
*
******************************************************************************/
bool DlgQuickMatch::FinalizeCreate(void)
{
mQuickMatch = WOLQuickMatch::Create();
if (!mQuickMatch)
{
return false;
}
Observer<QuickMatchEvent>::NotifyMe(*mQuickMatch);
return true;
}
/******************************************************************************
*
* NAME
* DlgQuickMatch::On_Init_Dialog
*
* DESCRIPTION
*
* INPUTS
* NONE
*
* RESULT
* NONE
*
******************************************************************************/
void DlgQuickMatch::On_Init_Dialog(void)
{
ListCtrlClass* output = (ListCtrlClass*)Get_Dlg_Item(IDC_OUTPUT);
WWASSERT_PRINT(output, "IDC_OUTOUT list control missing from dialog!");
if (output)
{
output->Add_Column(L"", 1.0F, Vector3 (1, 1, 1));
}
Connect();
MenuDialogClass::On_Init_Dialog();
}
/******************************************************************************
*
* NAME
* DlgQuickMatch::On_Frame_Update
*
* DESCRIPTION
*
* INPUTS
* NONE
*
* RESULT
* NONE
*
******************************************************************************/
void DlgQuickMatch::On_Frame_Update(void)
{
if (mConnectWait.IsValid())
{
WaitCondition::WaitResult waitStatus = mConnectWait->GetResult();
if (waitStatus != WaitCondition::Waiting)
{
if (waitStatus == WaitCondition::ConditionMet)
{
SendMatchingInfo();
}
else
{
OutputMessage(mConnectWait->GetResultText());
}
mConnectWait.Release();
}
}
unsigned long theTime = TIMEGETTIME();
if ((mResendTime > 0) && (theTime >= mResendTime))
{
mQuickMatch->SendClientInfo();
mResendTime = 0;
}
// Watch for timeout
if ((mTimeoutTime > 0) && (theTime >= mTimeoutTime))
{
OutputMessage(TRANSLATE(IDS_WOL_TIMEDOUT));
mTimeoutTime = 0;
}
MenuDialogClass::On_Frame_Update();
}
/******************************************************************************
*
* NAME
* DlgQuickMatch::
*
* DESCRIPTION
*
* INPUTS
* NONE
*
* RESULT
* NONE
*
******************************************************************************/
void DlgQuickMatch::On_Command(int ctrl, int message, DWORD param)
{
if (ctrl == IDC_MENU_BACK_BUTTON)
{
OutputMessage(IDS_QM_DISCONNECT);
RefPtr<WaitCondition> wait = mQuickMatch->Disconnect();
if (wait.IsValid())
{
DlgWOLWait::DoDialog(IDS_QM_DISCONNECT, wait);
}
}
MenuDialogClass::On_Command(ctrl, message, param);
}
/******************************************************************************
*
* NAME
* DlgQuickMatch::Connect
*
* DESCRIPTION
*
* INPUTS
* NONE
*
* RESULT
* NONE
*
******************************************************************************/
void DlgQuickMatch::Connect(void)
{
OutputMessage(IDS_QM_CONNECTING);
mConnectWait = mQuickMatch->ConnectClient();
if (mConnectWait.IsValid())
{
mConnectWait->WaitBeginning();
}
mTimeoutTime = (TIMEGETTIME() + 60000);
}
/******************************************************************************
*
* NAME
* DlgQuickMatch::SendMatchingInfo
*
* DESCRIPTION
*
* INPUTS
* NONE
*
* RESULT
* NONE
*
******************************************************************************/
void DlgQuickMatch::SendMatchingInfo(void)
{
OutputMessage(IDS_QM_SENDINGMATCHINFO);
bool sent = mQuickMatch->SendClientInfo();
if (sent)
{
OutputMessage(TRANSLATE (IDS_MENU_SEARCHING_FOR_MATCH));
}
else
{
OutputMessage(TRANSLATE (IDS_MENU_CANT_LOCATE_MATCH));
}
}
/******************************************************************************
*
* NAME
* DlgQuickMatch::OutputMessage
*
* DESCRIPTION
*
* INPUTS
* Message - Message to add to output.
*
* RESULT
* NONE
*
******************************************************************************/
void DlgQuickMatch::OutputMessage(int messageID)
{
const WCHAR* message = TranslateDBClass::Get_String(messageID);
OutputMessage(message);
}
/******************************************************************************
*
* NAME
* DlgQuickMatch::OutputMessage
*
* DESCRIPTION
*
* INPUTS
* Message - Message to add to output.
*
* RESULT
* NONE
*
******************************************************************************/
void DlgQuickMatch::OutputMessage(const WCHAR* message)
{
WWDEBUG_SAY(("QM: %S\n", message));
ListCtrlClass* output = (ListCtrlClass*)Get_Dlg_Item(IDC_OUTPUT);
if (output)
{
int entryCount = output->Get_Entry_Count();
output->Insert_Entry(entryCount, message);
// Limit message entries.
if (entryCount > 100)
{
output->Delete_Entry(0);
}
}
}
/******************************************************************************
*
* NAME
* DlgQuickMatch::HandleNotification(QuickMatchEvent)
*
* DESCRIPTION
* Handle status information from quickmatch.
*
* INPUTS
* Status -
*
* RESULT
* NONE
*
******************************************************************************/
void DlgQuickMatch::HandleNotification(QuickMatchEvent& status)
{
QuickMatchEvent::Event event = status.GetEvent();
const WCHAR* msg = (const WCHAR*)status.Subject();
if (QuickMatchEvent::QMERROR == event)
{
const WideStringClass& statusMsg = status.Subject();
// If no match then resend the request in 10 seconds.
if (statusMsg.Compare_No_Case(L"QM:NoMatch") == 0)
{
msg = TRANSLATE(IDS_QM_NOMATCH);
}
else
{
#ifdef QUICKMATCH_OPTIONS
// Unable to match user because preferred modes are all zero.
if (statusMsg.Compare_No_Case(L"QM:NoModes") == 0)
{
DlgMsgBox::DoDialog(TRANSLATE (IDS_MENU_INVALID_QM_SETTINGS_TITLE), TRANSLATE (IDS_MENU_INVALID_QM_SETTINGS),
DlgMsgBox::Okay, this);
return;
}
#endif
}
}
else if (QuickMatchEvent::QMMATCHED == event)
{
GameInitMgrClass::Set_WOL_Return_Dialog(RenegadeDialogMgrClass::LOC_INTERNET_MAIN);
// Join the game
const WCHAR* gameName = (const WCHAR*)status.Subject();
WOLJoinGame::JoinTheGame(gameName, L"", false);
return;
}
// Assume any other message is for the user.
OutputMessage(msg);
}
/******************************************************************************
*
* NAME
* DlgQuickMatch::HandleNotification(DlgMsgBoxEvent)
*
* DESCRIPTION
*
* INPUTS
*
* RESULT
* NONE
*
******************************************************************************/
void DlgQuickMatch::HandleNotification(DlgMsgBoxEvent& msgbox)
{
#ifdef QUICKMATCH_OPTIONS
Add_Ref();
if (msgbox.Event() == DlgMsgBoxEvent::Okay)
{
End_Dialog();
START_DIALOG(MPWolQuickMatchOptionsMenuClass);
}
Release_Ref();
#endif // QUICKMATCH_OPTIONS
}

View File

@@ -0,0 +1,85 @@
/*
** 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/>.
*/
/******************************************************************************
*
* NAME
* $Archive: /Commando/Code/Commando/DlgQuickmatch.h $
*
* DESCRIPTION
* Quick match dialog
*
* PROGRAMMER
* Denzil E. Long, Jr.
* $Author: Denzil_l $
*
* VERSION INFO
* $Revision: 8 $
* $Modtime: 8/23/01 8:30a $
*
******************************************************************************/
#ifndef __DLGQUICKMATCH_H__
#define __DLGQUICKMATCH_H__
#include "WOLQuickMatch.h"
#include <WWUI\MenuDialog.h>
#include <WWLib\Notify.h>
#include <WWOnline\RefPtr.h>
class WaitCondition;
class DlgMsgBoxEvent;
class DlgQuickMatch :
public MenuDialogClass,
public Observer<QuickMatchEvent>,
public Observer<DlgMsgBoxEvent>
{
public:
static bool DoDialog(void);
protected:
DlgQuickMatch();
virtual ~DlgQuickMatch();
bool FinalizeCreate(void);
void On_Init_Dialog(void);
void On_Frame_Update(void);
void On_Command(int ctrl, int message, DWORD param);
void Connect(void);
void SendMatchingInfo(void);
void OutputMessage(int messageID);
void OutputMessage(const WCHAR* message);
void HandleNotification(QuickMatchEvent&);
void HandleNotification(DlgMsgBoxEvent&);
private:
DlgQuickMatch(const DlgQuickMatch&);
const DlgQuickMatch& operator=(const DlgQuickMatch&);
WOLQuickMatch* mQuickMatch;
RefPtr<WaitCondition> mConnectWait;
DWORD mTimeoutTime;
DWORD mResendTime;
};
#endif // __DLGQUICKMATCH_H__

View File

@@ -0,0 +1,167 @@
/*
** 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/>.
*/
/******************************************************************************
*
* NAME
* $Archive: /Commando/Code/Commando/DlgRestart.cpp $
*
* DESCRIPTION
* Dialog to notify the user that the game requires a restart.
*
* PROGRAMMER
* Denzil E. Long, Jr.
* $Author: Denzil_l $
*
* VERSION INFO
* $Revision: 3 $
* $Modtime: 10/18/01 6:23p $
*
******************************************************************************/
#include "DlgRestart.h"
#include "Resource.h"
#include "MainLoop.h"
#include "String_IDs.h"
#include <WWTranslateDB\TranslateDB.h>
#include <WWDebug\WWDebug.h>
/******************************************************************************
*
* NAME
* DlgRestart::DoDialog
*
* DESCRIPTION
*
* INPUTS
* NONE
*
* RESULT
* True if dialog created successfully.
*
******************************************************************************/
bool DlgRestart::DoDialog(void)
{
DlgRestart* popup = new DlgRestart;
if (popup)
{
popup->Start_Dialog();
popup->Set_Title(TRANSLATE(IDS_RESTART_TITLE));
popup->Release_Ref();
}
return (popup != NULL);
}
/******************************************************************************
*
* NAME
* DlgRestart::DlgRestart
*
* DESCRIPTION
* Constructor
*
* INPUTS
* NONE
*
* RESULT
* NONE
*
******************************************************************************/
DlgRestart::DlgRestart() :
PopupDialogClass(IDD_MESSAGEBOX_OK)
{
WWDEBUG_SAY(("DlgRestart: Instantiated\n"));
}
/******************************************************************************
*
* NAME
* DlgRestart::~DlgRestart
*
* DESCRIPTION
* Destructor
*
* INPUTS
* NONE
*
* RESULT
* NONE
*
******************************************************************************/
DlgRestart::~DlgRestart()
{
WWDEBUG_SAY(("DlgRestart: Destructing\n"));
}
/******************************************************************************
*
* NAME
* DlgRestart::On_Init_Dialog
*
* DESCRIPTION
* One time initialzation.
*
* INPUTS
* NONE
*
* RESULT
* NONE
*
******************************************************************************/
void DlgRestart::On_Init_Dialog(void)
{
Set_Dlg_Item_Text(IDC_MESSAGE, TRANSLATE(IDS_RESTART_PROMPT));
PopupDialogClass::On_Init_Dialog();
}
/******************************************************************************
*
* NAME
* DlgRestart::On_Command
*
* DESCRIPTION
* Process command message
*
* INPUTS
* Ctrl - ID of control
* Message -
* Param -
*
* RESULT
* NONE
*
******************************************************************************/
void DlgRestart::On_Command(int ctrl, int message, DWORD param)
{
if (IDOK == ctrl)
{
Stop_Main_Loop(RESTART_EXITCODE);
End_Dialog();
}
}

View File

@@ -0,0 +1,61 @@
/*
** 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/>.
*/
/******************************************************************************
*
* NAME
* $Archive: /Commando/Code/Commando/DlgRestart.h $
*
* DESCRIPTION
* Dialog to notify the user that the game requires a restart.
*
* PROGRAMMER
* Denzil E. Long, Jr.
* $Author: Denzil_l $
*
* VERSION INFO
* $Revision: 1 $
* $Modtime: 10/15/01 3:12p $
*
******************************************************************************/
#ifndef __DLGRESTART_H__
#define __DLGRESTART_H__
#include <WWUI\PopupDialog.h>
class DlgRestart :
public PopupDialogClass
{
public:
static bool DoDialog(void);
protected:
DlgRestart();
virtual ~DlgRestart();
void On_Init_Dialog(void);
void On_Command(int ctrl, int message, DWORD param);
private:
// Prevent copy and assignment
DlgRestart(const DlgRestart&);
const DlgRestart& operator=(const DlgRestart&);
};
#endif // __DLGRESTART_H__

View File

@@ -0,0 +1,168 @@
/*
** 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/DlgWOLAutoStart.cpp $*
* *
* $Author:: Steve_t $*
* *
* $Modtime:: 12/06/01 2:04p $*
* *
* $Revision:: 2 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include "always.h"
#include "autostart.h"
#include "win.h"
#include "listctrl.h"
#include "dlgwolautostart.h"
#include "menubackdrop.h"
#include "registry.h"
#include "_globals.h"
/***********************************************************************************************
* AutoRestartProgressDialogClass::AutoRestartProgressDialogClass -- Constructor *
* *
* *
* *
* INPUT: Nothing *
* *
* OUTPUT: Nothing *
* *
* WARNINGS: None *
* *
* HISTORY: *
* 11/6/2001 11:02AM ST : Created *
*=============================================================================================*/
AutoRestartProgressDialogClass::AutoRestartProgressDialogClass(void) :
MenuDialogClass (IDD_MP_AUTO_RESTART_PROGRESS)
{
Instance = this;
AddItemIndex = 0;
}
/***********************************************************************************************
* AutoRestartProgressDialogClass::On_Init_Dialog -- Initialise the dialog *
* *
* *
* *
* INPUT: Nothing *
* *
* OUTPUT: Nothing *
* *
* WARNINGS: None *
* *
* HISTORY: *
* 11/6/2001 11:03AM ST : Created *
*=============================================================================================*/
void AutoRestartProgressDialogClass::On_Init_Dialog (void)
{
/*
** Create the backdrop if necessary
*/
RegistryClass reg(APPLICATION_SUB_KEY_NAME_OPTIONS);
if (reg.Get_Int("DisableMenuAnim", 0) == 0) {
if (Get_BackDrop ()->Peek_Model () == NULL) {
Get_BackDrop ()->Set_Model ("IF_BACK01");
Get_BackDrop ()->Set_Animation ("IF_BACK01.IF_BACK01");
}
}
/*
** Set the columns up. Just one with nothing in it.
*/
ListCtrlClass *list_ctrl = (ListCtrlClass *)Get_Dlg_Item (IDC_PROGRESS_INFO);
if (list_ctrl != NULL) {
list_ctrl->Add_Column (L"", 1.0F, Vector3 (1, 1, 1));
list_ctrl->Allow_Selection(false);
list_ctrl->Set_Wants_Focus(false);
}
/*
** Start adding items at index 0.
*/
AddItemIndex = 0;
/*
** Call the base class init.
*/
MenuDialogClass::On_Init_Dialog ();
}
/***********************************************************************************************
* AutoRestartProgressDialogClass::On_Command -- Message handler for dialog *
* *
* *
* *
* INPUT: ID of control that message refers to *
* ID of message *
* misc param *
* *
* OUTPUT: Nothing *
* *
* WARNINGS: None *
* *
* HISTORY: *
* 11/6/2001 11:03AM ST : Created *
*=============================================================================================*/
void AutoRestartProgressDialogClass::On_Command (int ctrl_id, int message_id, DWORD param)
{
switch (ctrl_id)
{
case IDCANCEL:
AutoRestart.Cancel();
break;
}
MenuDialogClass::On_Command (ctrl_id, message_id, param);
}
/***********************************************************************************************
* AutoRestartProgressDialogClass::Add_Text -- Adds text to the progress info box *
* *
* *
* *
* INPUT: Ptr to wide text string *
* *
* OUTPUT: Nothing *
* *
* WARNINGS: None *
* *
* HISTORY: *
* 11/6/2001 11:04AM ST : Created *
*=============================================================================================*/
void AutoRestartProgressDialogClass::Add_Text(unsigned short *txt)
{
ListCtrlClass *list_ctrl = (ListCtrlClass *)Get_Dlg_Item(IDC_PROGRESS_INFO);
if (list_ctrl) {
list_ctrl->Insert_Entry(AddItemIndex++, txt);
}
}

View File

@@ -0,0 +1,66 @@
/*
** 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/DlgWOLAutoStart.h $*
* *
* $Author:: Steve_t $*
* *
* $Modtime:: 11/06/01 11:06a $*
* *
* $Revision:: 1 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#pragma once
#ifndef _DLGWOLAUTOSTART_H
#define _DLGWOLAUTOSTART_H
#include "menudialog.h"
#include "resource.h"
/*
** This dialog just shows progress during a server auto start.
**
**
*/
class AutoRestartProgressDialogClass : public MenuDialogClass
{
public:
AutoRestartProgressDialogClass(void);
void On_Init_Dialog(void);
void On_Command(int ctrl_id, int message_id, DWORD param);
void Add_Text(unsigned short *txt);
static AutoRestartProgressDialogClass *Get_Instance(void) {return(Instance);}
private:
int AddItemIndex;
static AutoRestartProgressDialogClass *Instance;
};
#endif //_DLGWOLAUTOSTART_H

View File

@@ -0,0 +1,589 @@
/*
** 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/>.
*/
/******************************************************************************
*
* FILE
* $Archive: /Commando/Code/Commando/DlgWOLLogon.cpp $
*
* DESCRIPTION
* Westwood Online Login Dialog. This is the dialog that gathers the login
* information from the user.
*
* PROGRAMMER
* Denzil E. Long, Jr.
* $Author: Denzil_l $
*
* VERSION INFO
* $Revision: 21 $
* $Modtime: 1/19/02 12:05a $
*
******************************************************************************/
#include "DlgWOLLogon.h"
#include "RenegadeDialogMgr.h"
#include "MPSettingsMgr.h"
#include "DlgMessageBox.h"
#include "DlgWOLSettings.h"
#include <WWOnline\WOLLoginInfo.h>
#include <WWUI\ComboBoxCtrl.h>
#include <WWUI\EditCtrl.h>
#include "DlgWebpage.h"
#include "string_ids.h"
#include "Resource.h"
using namespace WWOnline;
/******************************************************************************
*
* NAME
* DlgWOLLogon::DoDialog
*
* DESCRIPTION
*
* INPUTS
* Login - Login to display
* Observer - Observer to be notified.
*
* RESULT
* Success - True if dialog successfully started.
*
******************************************************************************/
bool DlgWOLLogon::DoDialog(const wchar_t* login, Observer<DlgWOLLogonEvent>* observer)
{
DlgWOLLogon* dialog = new DlgWOLLogon;
if (dialog)
{
if (dialog->FinalizeCreate(login))
{
if (observer)
{
dialog->AddObserver(*observer);
}
dialog->Start_Dialog();
}
dialog->Release_Ref();
}
return (dialog != NULL);
}
/******************************************************************************
*
* NAME
* DlgWOLLogon::DlgWOLLogon
*
* DESCRIPTION
* Constructor
*
* INPUTS
* NONE
*
* RESULT
* NONE
*
******************************************************************************/
DlgWOLLogon::DlgWOLLogon() :
PopupDialogClass(IDD_WOL_LOGON),
mIsPasswordEncrypted(false)
{
WWDEBUG_SAY(("DlgWOLLogon: Instantiated\n"));
}
/******************************************************************************
*
* NAME
* DlgWOLLogon::~DlgWOLLogon
*
* DESCRIPTION
* Destructor
*
* INPUTS
* NONE
*
* RESULT
* NONE
*
******************************************************************************/
DlgWOLLogon::~DlgWOLLogon()
{
WWDEBUG_SAY(("DlgWOLLogon: Destroyed\n"));
}
/******************************************************************************
*
* NAME
* DlgWOLLogon::FinalizeCreate
*
* DESCRIPTION
* Finalize the creation of this object (Initialize).
*
* INPUTS
*
* RESULT
* Success - True if successful.
*
******************************************************************************/
bool DlgWOLLogon::FinalizeCreate(const wchar_t* login)
{
mLogin = login;
return true;
}
/******************************************************************************
*
* NAME
* DlgWOLLogon::On_Init_Dialog
*
* DESCRIPTION
* Initialize the dialog.
*
* INPUTS
* NONE
*
* RESULT
* NONE
*
******************************************************************************/
void DlgWOLLogon::On_Init_Dialog(void)
{
Check_Dlg_Button(IDC_REMEMBER_LOGIN_CHECK, false);
Enable_Dlg_Item(IDC_WOL_LOG_ON_BUTTON, false);
// Limit password length to 8 characters.
EditCtrlClass* edit = (EditCtrlClass*)Get_Dlg_Item(IDC_PASSWORD_EDIT);
if (edit)
{
edit->Set_Text_Limit(8);
}
UpdatePersonas();
SelectPersona(mLogin);
PopupDialogClass::On_Init_Dialog();
}
/******************************************************************************
*
* NAME
* DlgWOLLogon::On_Command
*
* DESCRIPTION
* Handle command notification for the dialog.
*
* INPUTS
* Ctrl - ID of control originating command
* Message - Command message
* Param - Message parameter
*
* RESULT
* NONE
*
******************************************************************************/
void DlgWOLLogon::On_Command(int ctrl, int message, DWORD param)
{
switch (ctrl)
{
case IDC_WOL_LOG_ON_BUTTON:
{
// If this login is not stored then always use the password typed by the user.
const wchar_t* name = Get_Dlg_Item_Text(IDC_PERSONA_COMBO);
RefPtr<LoginInfo> login = LoginInfo::Find(name);
if (login.IsValid() && !login->IsStored())
{
const wchar_t* password = Get_Dlg_Item_Text(IDC_PASSWORD_EDIT);
login->SetPassword(password, false);
mIsPasswordEncrypted = false;
}
Add_Ref();
DlgWOLLogonEvent event(DlgWOLLogonEvent::Login, *this);
NotifyObservers(event);
Release_Ref();
End_Dialog();
}
break;
case IDC_DELETE_ACCOUNT_BUTTON:
{
// Delete this login from our local cache and purge it from storage.
const WCHAR* nickname = Get_Dlg_Item_Text(IDC_PERSONA_COMBO);
RefPtr<LoginInfo> login = LoginInfo::Find(nickname);
if (login.IsValid())
{
login->Forget(true);
}
// Refresh the UI
UpdatePersonas();
SelectPersona(NULL);
}
break;
case IDC_MANAGE_ACCOUNT_BUTTON:
DlgWebPage::DoDialog("Signup");
break;
case IDC_MENU_BACK_BUTTON:
Add_Ref();
DlgWOLLogonEvent event(DlgWOLLogonEvent::Cancel, *this);
NotifyObservers(event);
Release_Ref();
break;
}
PopupDialogClass::On_Command(ctrl, message, param);
}
/******************************************************************************
*
* NAME
* DlgWOLLogon::GetLogin
*
* DESCRIPTION
* Get the login information.
*
* INPUTS
* Name - On return; Name to login in with.
* Password - On return; Password to login with.
* Encrypted - Flag indicating if the password is encrypted.
*
* RESULT
* NONE
*
******************************************************************************/
void DlgWOLLogon::GetLogin(const wchar_t** name, const wchar_t** password,
bool& encrypted)
{
if (name)
{
*name = Get_Dlg_Item_Text(IDC_PERSONA_COMBO);
}
if (password)
{
*password = Get_Dlg_Item_Text(IDC_PASSWORD_EDIT);
}
encrypted = mIsPasswordEncrypted;
}
/******************************************************************************
*
* NAME
* DlgWOLLogon::IsRememberLoginChecked
*
* DESCRIPTION
* Get the "checked" state of the remember login checkbox.
*
* INPUTS
* NONE
*
* RESULT
* True if remember login checkbox is selected; false otherwise.
*
******************************************************************************/
bool DlgWOLLogon::IsRememberLoginChecked(void)
{
return Is_Dlg_Button_Checked(IDC_REMEMBER_LOGIN_CHECK);
}
/******************************************************************************
*
* NAME
* DlgWOLLogon::UpdatePersonas
*
* DESCRIPTION
* Update the persona combo box with cached logins.
*
* INPUTS
* NONE
*
* RESULT
* NONE
*
******************************************************************************/
void DlgWOLLogon::UpdatePersonas(void)
{
ComboBoxCtrlClass* combo = (ComboBoxCtrlClass*)Get_Dlg_Item(IDC_PERSONA_COMBO);
if (combo)
{
combo->Reset_Content();
const LoginInfoList& personas = LoginInfo::GetList();
const unsigned int count = personas.size();
for (unsigned int index = 0; index < count; ++index)
{
const WideStringClass& name = personas[index]->GetNickname();
combo->Add_String(name);
}
}
}
/******************************************************************************
*
* NAME
* DlgWOLLogon::SelectPersona
*
* DESCRIPTION
* Select the persona with the specified name.
*
* INPUTS
* Name - Name of persona.
*
* RESULT
* NONE
*
******************************************************************************/
void DlgWOLLogon::SelectPersona(const wchar_t* name)
{
ComboBoxCtrlClass* combo = (ComboBoxCtrlClass*)Get_Dlg_Item(IDC_PERSONA_COMBO);
if (combo)
{
// Select the specified persona or the first one in the list.
if (name && (wcslen(name) > 0))
{
int index = combo->Select_String(name);
// If the persona is not in the list then put it into the edit field
if (index == -1)
{
combo->Set_Text(name);
}
}
else
{
name = combo->Get_Text();
}
AutoComplete(name);
}
}
/******************************************************************************
*
* NAME
* DlgWOLLogon::AutoComplete
*
* DESCRIPTION
* Automatically complete the login dialog fields if an existing login
* matches the provided name.
*
* INPUTS
* Name - Login name to auto complete.
*
* RESULT
* NONE
*
******************************************************************************/
void DlgWOLLogon::AutoComplete(const wchar_t* name)
{
// If the persona has a valid login then fill in the dialog with
// the login information. Otherwise use the provided persona name.
RefPtr<LoginInfo> login = LoginInfo::Find(name);
if (login.IsValid() && login->IsStored())
{
// Fill in password
const WideStringClass& password = login->GetPassword();
Set_Dlg_Item_Text(IDC_PASSWORD_EDIT, password);
mIsPasswordEncrypted = login->IsPasswordEncrypted();
// WOL passwords must be exactly 8 characters
WWASSERT(password.Get_Length() == 8);
Enable_Dlg_Item(IDC_PASSWORD_EDIT, false);
Check_Dlg_Button(IDC_REMEMBER_LOGIN_CHECK, true);
Enable_Dlg_Item(IDC_REMEMBER_LOGIN_CHECK, false);
Enable_Dlg_Item(IDC_DELETE_ACCOUNT_BUTTON, true);
Enable_Dlg_Item(IDC_WOL_LOG_ON_BUTTON, true);
}
else
{
// Erase the password and enable the remember checkbox
Set_Dlg_Item_Text(IDC_PASSWORD_EDIT, L"");
mIsPasswordEncrypted = false;
Enable_Dlg_Item(IDC_PASSWORD_EDIT, true);
Enable_Dlg_Item(IDC_REMEMBER_LOGIN_CHECK, true);
Enable_Dlg_Item(IDC_DELETE_ACCOUNT_BUTTON, false);
Enable_Dlg_Item(IDC_WOL_LOG_ON_BUTTON, false);
}
}
/******************************************************************************
*
* NAME
* DlgWOLLogon::On_ComboBoxCtrl_Sel_Change
*
* DESCRIPTION
* Notification sent by a combobox when the selection is changed by user
* interaction.
*
* INPUTS
* Combo - Pointer to notifying combobox control.
* ID - ID of notifying combobox control.
* OldSel - Index of previous selection.
* NewSel - Index of new selection.
*
* RESULT
* NONE
*
******************************************************************************/
void DlgWOLLogon::On_ComboBoxCtrl_Sel_Change(ComboBoxCtrlClass* combo, int id, int, int)
{
if (IDC_PERSONA_COMBO == id)
{
const WCHAR* text = combo->Get_Text();
AutoComplete(text);
}
}
/******************************************************************************
*
* NAME
* DlgWOLLogon::On_ComboBoxCtrl_Edit_Change
*
* DESCRIPTION
* Notification sent by a combobox when the text in the edit field is
* changed by user interaction.
*
* INPUTS
* Combo - Pointer to notifying combobox control.
* ID - ID of notifying combobox control.
*
* RESULT
* NONE
*
******************************************************************************/
void DlgWOLLogon::On_ComboBoxCtrl_Edit_Change(ComboBoxCtrlClass* combo, int id)
{
if (IDC_PERSONA_COMBO == id)
{
const WCHAR* text = combo->Get_Text();
AutoComplete(text);
}
}
/******************************************************************************
*
* NAME
* DlgWOLLogon::On_EditCtrl_Change
*
* DESCRIPTION
* Notification sent by an edit control when the text in the edit field is
* changed by user interaction.
*
* INPUTS
* Edit - Pointer to notifying edit control.
* ID - ID of notifying edit control.
*
* RESULT
* NONE
*
******************************************************************************/
void DlgWOLLogon::On_EditCtrl_Change(EditCtrlClass* edit, int id)
{
if (IDC_PASSWORD_EDIT == id)
{
// If the user entered text then password is not encrypted.
mIsPasswordEncrypted = false;
// WOL passwords must be exactly 8 characters
int length = edit->Get_Text_Length();
bool enable = (8 == length);
Enable_Dlg_Item(IDC_WOL_LOG_ON_BUTTON, enable);
}
}
/******************************************************************************
*
* NAME
* DlgWOLLogon::On_EditCtrl_Enter_Pressed
*
* DESCRIPTION
* Notification sent by an edit control that the enter key was pressed.
*
* INPUTS
* Edit - Pointer to notifying edit control.
* ID - ID of notifying edit control.
*
* RESULT
* NONE
*
******************************************************************************/
void DlgWOLLogon::On_EditCtrl_Enter_Pressed(EditCtrlClass* edit, int id)
{
EditCtrlClass* passwordEdit = (EditCtrlClass*)Get_Dlg_Item(IDC_PASSWORD_EDIT);
if (passwordEdit)
{
const WCHAR* name = Get_Dlg_Item_Text(IDC_PERSONA_COMBO);
bool nameOK = (name && (wcslen(name) > 0));
bool passOK = (passwordEdit->Get_Text_Length() == 8);
if (nameOK && passOK)
{
Add_Ref();
DlgWOLLogonEvent event(DlgWOLLogonEvent::Login, *this);
NotifyObservers(event);
Release_Ref();
End_Dialog();
}
}
}

108
Code/Commando/DlgWOLLogon.h Normal file
View File

@@ -0,0 +1,108 @@
/*
** 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/>.
*/
/******************************************************************************
*
* FILE
* $Archive: /Commando/Code/Commando/DlgWOLLogon.h $
*
* DESCRIPTION
* Quick match dialog
*
* PROGRAMMER
* Denzil E. Long, Jr.
* $Author: Denzil_l $
*
* VERSION INFO
* $Revision: 14 $
* $Modtime: 1/18/02 11:44p $
*
******************************************************************************/
#ifndef __DLGWOLLOGON_H__
#define __DLGWOLLOGON_H__
#include "DlgWOLWait.h"
#include <wwui\popupdialog.h>
#include <WWLib\Notify.h>
#include <WWOnline\RefPtr.h>
class DlgWOLLogon;
class DlgWOLLogonEvent :
public TypedEvent<DlgWOLLogonEvent, DlgWOLLogon>
{
public:
enum Event {Cancel = 0, Login};
Event GetEvent(void) const
{return mEvent;}
DlgWOLLogonEvent(Event event, DlgWOLLogon& dialog) :
TypedEvent<DlgWOLLogonEvent, DlgWOLLogon>(dialog),
mEvent(event)
{}
~DlgWOLLogonEvent()
{}
private:
Event mEvent;
};
class DlgWOLLogon :
public PopupDialogClass,
public Notifier<DlgWOLLogonEvent>
{
public:
static bool DoDialog(const wchar_t* login, Observer<DlgWOLLogonEvent>* observer);
void GetLogin(const wchar_t** login, const wchar_t** password, bool& encrypted);
bool IsRememberLoginChecked(void);
protected:
DlgWOLLogon();
virtual ~DlgWOLLogon();
bool FinalizeCreate(const wchar_t* login);
void On_Init_Dialog(void);
void On_Command(int ctrl, int message, DWORD param);
void UpdatePersonas(void);
void SelectPersona(const wchar_t* name);
void AutoComplete(const wchar_t* name);
// Notifications
void On_ComboBoxCtrl_Sel_Change(ComboBoxCtrlClass* combo, int id, int oldsel, int newsel);
void On_ComboBoxCtrl_Edit_Change(ComboBoxCtrlClass* combo, int id);
void On_EditCtrl_Change(EditCtrlClass* edit, int id);
void On_EditCtrl_Enter_Pressed(EditCtrlClass* edit, int id);
DECLARE_NOTIFIER(DlgWOLLogonEvent)
private:
DlgWOLLogon(const DlgWOLLogon&);
const DlgWOLLogon& operator=(const DlgWOLLogon&);
WideStringClass mLogin;
bool mIsPasswordEncrypted;
};
#endif // __DLGWOLLOGON_H__

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,99 @@
/*
** 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/>.
*/
/******************************************************************************
*
* FILE
* $Archive: /Commando/Code/Commando/DlgWOLSettings.h $
*
* DESCRIPTION
* Quick match dialog
*
* PROGRAMMER
* Denzil E. Long, Jr.
* $Author: Denzil_l $
*
* VERSION INFO
* $Revision: 14 $
* $Modtime: 1/19/02 2:29p $
*
******************************************************************************/
#ifndef __DLGWOLSETTINGS_H__
#define __DLGWOLSETTINGS_H__
#include "DlgWOLWait.h"
#include <WWUI\MenuDialog.h>
#include <WWLib\Notify.h>
#include <WWOnline\RefPtr.h>
#include <WWOnline\WOLSession.h>
class LoginProfile;
class DlgWOLSettings :
public MenuDialogClass,
public Observer<DlgWOLWaitEvent>
{
public:
static bool DoDialog(void);
protected:
DlgWOLSettings();
virtual ~DlgWOLSettings();
bool FinalizeCreate(void);
void On_Init_Dialog(void);
void On_Destroy(void);
void On_Command(int ctrl, int message, DWORD param);
bool SaveSettings(void);
void InitPersonaCombo(void);
void ClearPersonaCombo(void);
void DeleteSelectedPersona(void);
void UpdateForPersona(void);
void InitServersCombo(const WWOnline::IRCServerList& servers);
void SetServerCombo(const char* serverName);
void InitSideCombo(void);
void SetSideCombo(int side);
void InitLocaleCombo(void);
void SetLocaleCombo(WOL::Locale locale);
void InitConnectionSpeedCombo(void);
void On_ComboBoxCtrl_Sel_Change(ComboBoxCtrlClass* combo, int ctrl, int oldSel, int newSel);
void HandleNotification(DlgWOLWaitEvent&);
LoginProfile* GetLoginProfile(void);
private:
DlgWOLSettings(const DlgWOLSettings&);
const DlgWOLSettings& operator=(const DlgWOLSettings&);
RefPtr<WWOnline::Session> mWOLSession;
bool DetectingBandwidth;
bool WaitingToExitDialog;
};
#endif // __DLGWOLSETTINGS_H__

View File

@@ -0,0 +1,467 @@
/*
** 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/>.
*/
/******************************************************************************
*
* FILE
* $Archive: /Commando/Code/Commando/DlgWOLWait.cpp $
*
* DESCRIPTION
*
* PROGRAMMER
* Denzil E. Long, Jr.
* $Author: Bhayes $
*
* VERSION INFO
* $Revision: 21 $
* $Modtime: 2/18/02 7:57p $
*
******************************************************************************/
#include "DlgWOLWait.h"
#include "DlgMessageBox.h"
#include "Resource.h"
#include "String_ids.h"
#include <WWOnline\WOLSession.h>
#include <WWUI\MouseMgr.h>
#include <WWTranslateDB\TranslateDB.h>
#include <WWDebug\WWDebug.h>
#include "gamespyadmin.h"
#ifdef _MSC_VER
#pragma warning (push,3)
#endif
#include "systimer.h"
#ifdef _MSC_VER
#pragma warning (pop)
#endif
using namespace WWOnline;
DlgWOLWait* DlgWOLWait::mTheInstance = NULL;
/******************************************************************************
*
* NAME
* DlgWOLWait::DoDialog
*
* DESCRIPTION
*
* INPUTS
* Title - Title of dialog
* Wait - Wait condition to process.
* Observer - DlgWOLWaitEvent observer
*
* RESULT
* Success - True if dialog successfully started.
*
******************************************************************************/
bool DlgWOLWait::DoDialog(const WCHAR* title, RefPtr<WaitCondition>& wait,
Observer<DlgWOLWaitEvent>* observer, unsigned long timeout, unsigned long dialog_timeout)
{
if (wait.IsValid())
{
DlgWOLWait* popup = new DlgWOLWait(wait, timeout, dialog_timeout);
if (popup)
{
WWDEBUG_SAY(("DlgWOLWait: Starting dialog '%S'\n", title));
popup->Start_Dialog();
popup->Set_Title(title);
if (observer)
{
popup->AddObserver(*observer);
}
popup->Release_Ref();
}
return (popup != NULL);
}
return false;
}
/******************************************************************************
*
* NAME
* DlgWOLWait::DoDialog
*
* DESCRIPTION
*
* INPUTS
* Title - Title of dialog
* Wait - Wait condition to process.
* Observer - DlgWOLWaitEvent observer
*
* RESULT
* Success - True if dialog successfully started.
*
******************************************************************************/
bool DlgWOLWait::DoDialog(const WCHAR* title, const WCHAR* button_text, RefPtr<WaitCondition>& wait,
Observer<DlgWOLWaitEvent>* observer, unsigned long timeout, unsigned long dialog_timeout)
{
if (wait.IsValid())
{
DlgWOLWait* popup = new DlgWOLWait(wait, timeout, dialog_timeout);
if (popup)
{
WWDEBUG_SAY(("DlgWOLWait: Starting dialog '%S'\n", title));
popup->Start_Dialog();
popup->Set_Dlg_Item_Text(IDCANCEL, button_text);
popup->Set_Title(title);
if (observer)
{
popup->AddObserver(*observer);
}
popup->Release_Ref();
}
return (popup != NULL);
}
return false;
}
/******************************************************************************
*
* NAME
* DlgWOLWait::DoDialog
*
* DESCRIPTION
*
* INPUTS
* Title - Title ID of dialog
* Wait - Wait condition to process.
* Observer - DlgWOLWaitEvent observer
*
* RESULT
* Success - True if dialog successfully started.
*
******************************************************************************/
bool DlgWOLWait::DoDialog(int titleID, RefPtr<WaitCondition>& wait,
Observer<DlgWOLWaitEvent>* observer, unsigned long timeout, unsigned long dialog_timeout)
{
const WCHAR* title = TranslateDBClass::Get_String(titleID);
return DoDialog(title, wait, observer, timeout, dialog_timeout);
}
/******************************************************************************
*
* NAME
* DlgWOLWait::DlgWOLWait
*
* DESCRIPTION
* Constructor
*
* INPUTS
* Wait - Wait condition to process.
*
* RESULT
* NONE
*
******************************************************************************/
DlgWOLWait::DlgWOLWait(RefPtr<WaitCondition>& wait, unsigned long timeout, unsigned long dialog_timeout) :
PopupDialogClass(IDD_WOL_WAIT),
mWait(wait),
mStartTime(0),
mTimeout(timeout),
mDialogTimeout(dialog_timeout),
mShowDialog(false)
{
mTheInstance = this;
}
/******************************************************************************
*
* NAME
* DlgWOLWait::~DlgWOLWait
*
* DESCRIPTION
* Destructor
*
* INPUTS
* NONE
*
* RESULT
* NONE
*
******************************************************************************/
DlgWOLWait::~DlgWOLWait()
{
mTheInstance = NULL;
}
/******************************************************************************
*
* NAME
* DlgWOLWait::On_Init_Dialog
*
* DESCRIPTION
* One time dialog initialization.
*
* INPUTS
* NONE
*
* RESULT
* NONE
*
******************************************************************************/
void DlgWOLWait::On_Init_Dialog(void)
{
if (mWait.IsValid())
{
if (!cGameSpyAdmin::Is_Gamespy_Game()) {
mWOLSession = Session::GetInstance(false);
WWASSERT(mWOLSession.IsValid());
}
// Start the wait condition
mWait->WaitBeginning();
// Set the dialogs wait text
Set_Dlg_Item_Text(IDC_WAITTEXT, mWait->GetWaitText());
mStartTime = TIMEGETTIME();
if (mDialogTimeout != SHOW_NEVER)
{
// Initially the dialog is not shown so bring up the wait cursor.
mShowDialog = false;
MouseMgrClass::Begin_Wait_Cursor();
}
}
PopupDialogClass::On_Init_Dialog();
}
/******************************************************************************
*
* NAME
* DlgWOLWait::On_Destroy
*
* DESCRIPTION
*
* INPUTS
* NONE
*
* RESULT
* NONE
*
******************************************************************************/
void DlgWOLWait::On_Destroy(void)
{
WWDEBUG_SAY(("DlgWOLWait: Ending dialog '%S'\n", (const WCHAR*)Title));
if (!mShowDialog && mDialogTimeout != SHOW_NEVER)
{
MouseMgrClass::End_Wait_Cursor();
}
}
/******************************************************************************
*
* NAME
* DlgWOLWait::On_Periodic
*
* DESCRIPTION
*
* INPUTS
* NONE
*
* RESULT
* NONE
*
******************************************************************************/
void DlgWOLWait::On_Periodic(void)
{
Add_Ref();
CheckCondition();
PopupDialogClass::On_Periodic();
Release_Ref();
}
/******************************************************************************
*
* NAME
* DlgWOLWait::CheckCondition
*
* DESCRIPTION
* Check the condition of the wait.
*
* INPUTS
* NONE
*
* RESULT
* NONE
*
******************************************************************************/
void DlgWOLWait::CheckCondition(void)
{
// Quit if there is nothing to wait on or there is not WWOnline session.
if (!mWait.IsValid() || (!mWOLSession.IsValid() && !cGameSpyAdmin::Is_Gamespy_Game()))
{
End_Dialog();
return;
}
// Check the status of the wait condition
WaitCondition::WaitResult waitStatus = mWait->GetResult();
// If we are no longer waiting then process the result.
if (waitStatus != WaitCondition::Waiting)
{
// If there are no observers and the wait timed out or errored then
// show a message dialog describing the failure.
if ((Notifier<DlgWOLWaitEvent>::HasObservers() == false)
&& ((waitStatus == WaitCondition::TimeOut) || (waitStatus == WaitCondition::Error)))
{
DlgMsgBox::DoDialog(mWait->GetWaitText(), mWait->GetResultText());
}
// Notify the observers about the status of the wait.
Add_Ref();
DlgWOLWaitEvent event(waitStatus, mWait.ReferencedObject());
NotifyObservers(event);
Release_Ref();
End_Dialog();
return;
}
// Change the waiting text if necessary.
const WCHAR* text = Get_Dlg_Item_Text(IDC_WAITTEXT);
const WideStringClass& waitText = mWait->GetWaitText();
if (waitText.Compare_No_Case(text) != 0)
{
Set_Dlg_Item_Text(IDC_WAITTEXT, waitText);
PopupDialogClass::Build_Background_Renderers();
}
// Watch for timeout
unsigned long currTime = TIMEGETTIME();
unsigned long timeout = mTimeout;
unsigned long dialog_timeout = mDialogTimeout;
if (dialog_timeout == 0)
{
dialog_timeout = 2000;
}
// If the dialog timeout is 0 then use the wait conditions timeout.
if (timeout == 0)
{
timeout = mWait->GetTimeout();
}
if ((currTime - mStartTime) > timeout)
{
mWait->EndWait(WaitCondition::TimeOut, TRANSLATE(IDS_WOL_TIMEDOUT));
}
// Do not render until sufficient time has elapsed. This will prevent the
// dialog from flashing in and out when the wait condition is satisfied quickly.
if (!mShowDialog && mStartTime && dialog_timeout != SHOW_NEVER && ((currTime - mStartTime) > 2000))
{
mShowDialog = true;
MouseMgrClass::End_Wait_Cursor();
}
// Allow time for WWOnline processing.
if (mWOLSession.IsValid()) mWOLSession->Process();
}
/******************************************************************************
*
* NAME
* DlgWOLWait::On_Command
*
* DESCRIPTION
* Process command message
*
* INPUTS
* Ctrl - ID of control
* Message -
* Param -
*
* RESULT
* NONE
*
******************************************************************************/
void DlgWOLWait::On_Command(int ctrl, int message, DWORD param)
{
if ((ctrl == IDCANCEL) && mWait.IsValid())
{
WWDEBUG_SAY(("DlgWOLWait: UserAborted '%S'\n", (const WCHAR*)mWait->GetWaitText()));
mWait->EndWait(WaitCondition::UserCancel, TRANSLATE(IDS_WOL_CANCELED));
}
}
/******************************************************************************
*
* NAME
* DlgWOLWait::Render
*
* DESCRIPTION
*
* INPUTS
* NONE
*
* RESULT
* NONE
*
******************************************************************************/
void DlgWOLWait::Render(void)
{
// Do not render until sufficient time has elapsed. This will prevent the
// dialog from flashing in and out when the wait condition is satisfied quickly.
if (mShowDialog)
{
PopupDialogClass::Render();
}
}

124
Code/Commando/DlgWOLWait.h Normal file
View File

@@ -0,0 +1,124 @@
/*
** 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/>.
*/
/******************************************************************************
*
* FILE
* $Archive: /Commando/Code/Commando/DlgWOLWait.h $
*
* DESCRIPTION
*
* PROGRAMMER
* Denzil E. Long, Jr.
* $Author: Bhayes $
*
* VERSION INFO
* $Revision: 14 $
* $Modtime: 2/18/02 7:51p $
*
******************************************************************************/
#ifndef __DLGWOLWAIT_H__
#define __DLGWOLWAIT_H__
#include <WWUI\PopupDialog.h>
#include <WWLib\Notify.h>
#include <WWOnline\RefPtr.h>
#include <WWOnline\WaitCondition.h>
namespace WWOnline
{
class Session;
}
class DlgWOLWait;
class DlgWOLWaitEvent :
public TypedEventPtr<DlgWOLWaitEvent, WaitCondition>
{
public:
typedef WaitCondition::WaitResult WaitResult;
inline WaitResult Result(void) const
{return mResult;}
DlgWOLWaitEvent(WaitResult result, WaitCondition* wait) :
TypedEventPtr<DlgWOLWaitEvent, WaitCondition>(wait),
mResult(result)
{}
protected:
// Prevent copy and assignment
DlgWOLWaitEvent(const DlgWOLWaitEvent&);
const DlgWOLWaitEvent& operator=(const DlgWOLWaitEvent&);
private:
WaitResult mResult;
};
class DlgWOLWait :
public PopupDialogClass,
public Notifier<DlgWOLWaitEvent>
{
public:
enum {SHOW_NEVER = 0xFFFFFFFF};
static bool DoDialog(const WCHAR* title, const WCHAR* button_text, RefPtr<WaitCondition>& wait,
Observer<DlgWOLWaitEvent>* observer = NULL, unsigned long timeout = 0, unsigned long dialog_timeout = 0);
static bool DoDialog(const WCHAR* title, RefPtr<WaitCondition>& wait,
Observer<DlgWOLWaitEvent>* observer = NULL, unsigned long timeout = 0, unsigned long dialog_timeout = 0);
static bool DoDialog(int titleID, RefPtr<WaitCondition>& wait,
Observer<DlgWOLWaitEvent>* observer = NULL, unsigned long timeout = 0, unsigned long dialog_timeout = 0);
const RefPtr<WaitCondition>& GetWait(void)
{return mWait;}
static DlgWOLWait *Get_Instance (void) { return mTheInstance; }
protected:
DlgWOLWait(RefPtr<WaitCondition>& wait, unsigned long timeout, unsigned long dialog_timeout = 0);
~DlgWOLWait();
// Prevent copy and assignment
DlgWOLWait(const DlgWOLWait&);
const DlgWOLWait& operator=(const DlgWOLWait&);
void CheckCondition(void);
void On_Init_Dialog(void);
void On_Destroy(void);
void On_Periodic(void);
void On_Command(int ctrl, int message, DWORD param);
void Render(void);
DECLARE_NOTIFIER(DlgWOLWaitEvent)
private:
RefPtr<WaitCondition> mWait;
RefPtr<WWOnline::Session> mWOLSession;
unsigned mStartTime;
unsigned long mTimeout;
unsigned long mDialogTimeout;
bool mShowDialog;
static DlgWOLWait * mTheInstance;
};
#endif // __DLGWOLLOGON_H__

View File

@@ -0,0 +1,361 @@
/*
** 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/>.
*/
/******************************************************************************
*
* NAME
* $Archive: /Commando/Code/Commando/DlgWebPage.cpp $
*
* DESCRIPTION
* Web Browser dialog
*
* PROGRAMMER
* Denzil E. Long, Jr.
* $Author: Denzil_l $
*
* VERSION INFO
* $Revision: 9 $
* $Modtime: 10/30/01 10:08p $
*
******************************************************************************/
#include "DlgWebPage.h"
#include "WebBrowser.h"
#include <WWUI\PopupDialog.h>
#include <WWUI\DialogControl.h>
#include <Combat\DirectInput.h>
#include <WW3D2\WW3D.h>
#include "DlgMessageBox.h"
#include "Resource.h"
#include <Combat\String_IDs.h>
#include "WWDebug.h"
/******************************************************************************
*
* NAME
* DlgWebPage::DoDialog
*
* DESCRIPTION
* Show the specified web page.
*
* INPUTS
* Page - Page to display.
*
* RESULT
* NONE
*
******************************************************************************/
void DlgWebPage::DoDialog(char* page)
{
WWASSERT_PRINT(page && (strlen(page) > 0), "Invalid parameter.\n");
if ((page == NULL) || (strlen(page) == 0))
{
return;
}
DlgWebPage* dialog = new DlgWebPage;
if (dialog)
{
bool success = dialog->FinalizeCreate();
if (success)
{
// If we are using the embedded browser then show the webpage. Otherwise
// ask the user if they want to launch an external browser to view the page.
if (dialog->mBrowser->UsingEmbeddedBrowser())
{
dialog->Start_Dialog();
dialog->mBrowser->ShowWebPage(page);
}
else
{
// Increment the dialog reference so the dialog will be around for the
// message box result.
dialog->Add_Ref();
dialog->mPage = page;
DlgMsgBox::DoDialog(0, IDS_WEB_LAUNCHBROWSER,
DlgMsgBox::YesNo, static_cast< Observer<DlgMsgBoxEvent>* >(dialog));
}
}
// The dialog manager keeps a referenece to the dialog.
dialog->Release_Ref();
}
}
/******************************************************************************
*
* NAME
* DlgWebPage::DlgWebPage
*
* DESCRIPTION
* Default constructor
*
* INPUTS
* NONE
*
* RESULT
* NONE
*
******************************************************************************/
DlgWebPage::DlgWebPage() :
DialogBaseClass(IDD_WEBPAGE),
mBrowser(NULL)
{
WWDEBUG_SAY(("Instantiating DlgWebPage\n"));
}
/******************************************************************************
*
* NAME
* DlgWebPage::~DlgWebPage
*
* DESCRIPTION
* Destructor
*
* INPUTS
* NONE
*
* RESULT
* NONE
*
******************************************************************************/
DlgWebPage::~DlgWebPage()
{
WWDEBUG_SAY(("Destroying DlgWebPage\n"));
if (mBrowser)
{
mBrowser->Release();
}
}
/******************************************************************************
*
* NAME
* DlgWebPage::FinalizeCreate
*
* DESCRIPTION
* Finalize object creation. (Initialize object)
*
* INPUTS
* NONE
*
* RESULT
* Success - True if successful; False if failed.
*
******************************************************************************/
bool DlgWebPage::FinalizeCreate(void)
{
mBrowser = WebBrowser::CreateInstance(MainWindow);
if (mBrowser)
{
Observer<WebEvent>::NotifyMe(*mBrowser);
return true;
}
return false;
}
/******************************************************************************
*
* NAME
* DlgWebPage::Start_Dialog
*
* DESCRIPTION
*
* INPUTS
* NONE
*
* RESULT
* NONE
*
******************************************************************************/
void DlgWebPage::Start_Dialog(void)
{
DirectInput::Unacquire();
WW3D::Flip_To_Primary();
DialogBaseClass::Start_Dialog();
}
/******************************************************************************
*
* NAME
* DlgWebPage::End_Dialog
*
* DESCRIPTION
*
* INPUTS
* NONE
*
* RESULT
* NONE
*
******************************************************************************/
void DlgWebPage::End_Dialog(void)
{
DirectInput::Acquire();
DialogBaseClass::End_Dialog();
SetFocus(MainWindow);
}
/******************************************************************************
*
* NAME
* DlgWebPage::On_Frame_Update
*
* DESCRIPTION
*
* INPUTS
* NONE
*
* RESULT
* NONE
*
******************************************************************************/
void DlgWebPage::On_Frame_Update(void)
{
DialogBaseClass::On_Frame_Update();
if (mBrowser)
{
bool usingEmbedded = mBrowser->UsingEmbeddedBrowser();
if (!usingEmbedded)
{
bool externalRunning = mBrowser->IsExternalBrowserRunning();
bool gameActivated = (GameInFocus || (GetTopWindow(NULL) == MainWindow)
|| (GetForegroundWindow() == MainWindow));
if (!externalRunning || gameActivated)
{
WWDEBUG_SAY(("***** Reactivating Game *****\n"));
HWND topWindow = GetTopWindow(NULL);
if (topWindow != MainWindow)
{
SetForegroundWindow(MainWindow);
ShowWindow(MainWindow, SW_RESTORE);
}
End_Dialog();
}
}
}
}
/******************************************************************************
*
* NAME
* DlgWebPage::HandleNotification(WebEvent)
*
* DESCRIPTION
* Handle web event notifications
*
* INPUTS
* WebEvent - WebEvent to handle
*
* RESULT
* NONE
*
******************************************************************************/
void DlgWebPage::HandleNotification(WebEvent& event)
{
switch (event.Event())
{
case WebEvent::Quit:
End_Dialog();
break;
case WebEvent::CertificationFailed:
{
WebBrowser* browser = event.Subject();
browser->Hide();
DlgMsgBox::DoDialog(IDS_WEB_ERROR, IDS_WEB_PAGEFAILED);
End_Dialog();
}
break;
default:
break;
}
}
/******************************************************************************
*
* NAME
* DlgWebPage::HandleNotification(DlgMsgBoxEvent)
*
* DESCRIPTION
* Handle message box dialog event notifications
*
* INPUTS
* DlgMsgBoxEvent - Message box event to handle.
*
* RESULT
* NONE
*
******************************************************************************/
void DlgWebPage::HandleNotification(DlgMsgBoxEvent& event)
{
switch (event.Event())
{
case DlgMsgBoxEvent::Yes:
// Start the dialog to monitor the external browser.
Start_Dialog();
mBrowser->ShowWebPage(mPage);
// Release the reference we added to keep the dialog alive until this point.
Release_Ref();
break;
case DlgMsgBoxEvent::No:
// Release the reference we added to keep the dialog alive until this point.
Release_Ref();
break;
default:
break;
}
}

View File

@@ -0,0 +1,85 @@
/*
** 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/>.
*/
/******************************************************************************
*
* NAME
* $Archive: /Commando/Code/Commando/DlgWebPage.h $
*
* DESCRIPTION
* Web Browser dialog
*
* PROGRAMMER
* Denzil E. Long, Jr.
* $Author: Denzil_l $
*
* VERSION INFO
* $Revision: 4 $
* $Modtime: 10/30/01 4:35p $
*
******************************************************************************/
#ifndef __DLGWEBPAGE_H__
#define __DLGWEBPAGE_H__
#include "DialogBase.h"
#include <atlbase.h>
#include <WWLib\Notify.h>
class WebBrowser;
class WebEvent;
class DlgMsgBoxEvent;
class DlgWebPage :
public DialogBaseClass,
public Observer<WebEvent>,
public Observer<DlgMsgBoxEvent>
{
public:
static void DoDialog(char* page);
protected:
DlgWebPage();
virtual ~DlgWebPage();
bool FinalizeCreate(void);
// Handle web browser events
void HandleNotification(WebEvent& event);
// Handle message box dialog events
void HandleNotification(DlgMsgBoxEvent& event);
// DialogBassClass methods
protected:
void Start_Dialog(void);
void End_Dialog(void);
void On_Frame_Update(void);
private:
// Declare private to prevent copy and assignment
DlgWebPage(const DlgWebPage&);
const DlgWebPage& operator=(const DlgWebPage&);
private:
WebBrowser* mBrowser;
char* mPage;
unsigned long mTimer;
};
#endif // __DLGWEBPAGE_H__

View File

@@ -0,0 +1,317 @@
/*
** 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/>.
*/
/******************************************************************************
*
* FILE
* $Archive: /Commando/Code/Commando/FirewallWait.cpp $
*
* DESCRIPTION
* Firewall negotiation wait condition.
*
* PROGRAMMER
* $Author: Tom_s $
*
* VERSION INFO
* $Revision: 16 $
* $Modtime: 3/04/02 11:45a $
*
******************************************************************************/
#include "always.h"
#include "FirewallWait.h"
#include "nat.h"
#include "string_ids.h"
#include "translatedb.h"
#include "natter.h"
#include <WWOnline\WOLSession.h>
#include <WWDebug\WWDebug.h>
#ifdef _MSC_VER
#pragma warning (push,3)
#endif
#include "systimer.h"
#ifdef _MSC_VER
#pragma warning (pop)
#endif
/*
** Wait code for firewall/NAT detection.
**
**
**
*/
RefPtr<FirewallDetectWait> FirewallDetectWait::Create(void)
{
return new FirewallDetectWait();
}
FirewallDetectWait::FirewallDetectWait(void) :
SingleWait(TRANSLATION(IDS_FIREWALL_NEGOTIATING_FIREWALL), 60000),
mEvent(NULL),
mPingsRemaining(UINT_MAX)
{
mWOLSession = WWOnline::Session::GetInstance(false);
assert(mWOLSession.IsValid());
}
FirewallDetectWait::~FirewallDetectWait()
{
WWDEBUG_SAY(("FirewallDetectWait: End - %S\n", mEndText));
mWOLSession->EnablePinging(true);
if (mEvent)
{
CloseHandle(mEvent);
}
}
void FirewallDetectWait::WaitBeginning(void)
{
WWDEBUG_SAY(("FirewallDetectWait: Beginning\n"));
mEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (mEvent == NULL)
{
WWDEBUG_SAY(("FirewallDetectWait: Can't create event\n"));
EndWait(Error, TRANSLATION(IDS_FIREWALL_CREATE_EVENT_FAILED));
}
else
{
mWOLSession->EnablePinging(false);
mTimeout = 15000;
}
}
WaitCondition::WaitResult FirewallDetectWait::GetResult(void)
{
if (mEndResult == Waiting)
{
// Wait for pending pings to finish first
unsigned int pingsWaiting = mWOLSession->GetPendingPingCount();
if (mPingsRemaining != pingsWaiting)
{
mPingsRemaining = pingsWaiting;
mTimeout = 60000;
FirewallHelper.Detect_Firewall(mEvent);
}
if (mPingsRemaining == 0)
{
DWORD result = WaitForSingleObject(mEvent, 0);
if (result == WAIT_OBJECT_0)
{
WWDEBUG_SAY(("FirewallDetectWait: ConditionMet\n"));
WOLNATInterface.Save_Firewall_Info_To_Registry();
EndWait(ConditionMet, TRANSLATION(IDS_FIREWALL_NEGOTIATION_COMPLETE));
}
else if (result == WAIT_FAILED)
{
WWDEBUG_SAY(("FirewallDetectWait: WAIT_FAILED\n"));
EndWait(Error, TRANSLATION(IDS_FIREWALL_NEGOTIATION_FAILED));
}
}
}
if (mEndResult != Waiting)
{
mWOLSession->EnablePinging(true);
}
return mEndResult;
}
/*
** Wait code for clients when trying to open up a firewall for a server connection.
**
*/
RefPtr<FirewallConnectWait> FirewallConnectWait::Create(void)
{
return new FirewallConnectWait;
}
FirewallConnectWait::FirewallConnectWait(void) :
SingleWait(TRANSLATION(IDS_FIREWALL_NEGOTIATING_WITH_SERVER)),
mEvent(NULL),
mCancelEvent(NULL),
mSuccessFlag(FirewallHelperClass::FW_RESULT_UNKNOWN),
mQueueCount(0),
mLastQueueCount(0),
mPingsRemaining(UINT_MAX)
{
mWOLSession = WWOnline::Session::GetInstance(false);
assert(mWOLSession.IsValid());
}
FirewallConnectWait::~FirewallConnectWait()
{
WWDEBUG_SAY(("FirewallConnectWait: End - %S\n", mEndText));
mWOLSession->EnablePinging(true);
if (mEvent)
{
CloseHandle(mEvent);
}
if (mCancelEvent)
{
CloseHandle(mCancelEvent);
}
}
void FirewallConnectWait::WaitBeginning(void)
{
WWDEBUG_SAY(("FirewallConnectWait: Beginning\n"));
mEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
mCancelEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (mEvent == NULL)
{
WWDEBUG_SAY(("FirewallConnectWait: Can't create event\n"));
EndWait(Error, TRANSLATION(IDS_FIREWALL_CREATE_EVENT_FAILED));
}
else
{
mWOLSession->EnablePinging(false);
WOLNATInterface.Tell_Server_That_Client_Is_In_Channel();
mTimeout = 15000;
mStartTime = TIMEGETTIME();
}
}
WaitCondition::WaitResult FirewallConnectWait::GetResult(void)
{
if (mEndResult == Waiting)
{
// Wait for pending pings to finish first
unsigned int pingsWaiting = mWOLSession->GetPendingPingCount();
if (mPingsRemaining != pingsWaiting)
{
mPingsRemaining = pingsWaiting;
if (mPingsRemaining == 0)
{
FirewallHelper.Set_Client_Connect_Event(mEvent, mCancelEvent, &mSuccessFlag, (int*)&mQueueCount);
mTimeout = 32000;
mStartTime = TIMEGETTIME();
}
}
if (mPingsRemaining == 0)
{
if ((TIMEGETTIME() - mStartTime) > mTimeout)
{
EndWait(TimeOut, TRANSLATION(IDS_FIREWALL_PORT_NEGOTIATION_TIMEOUT));
}
else
{
// Maybe change the wait text if there are players queued in front of us.
if (mQueueCount != mLastQueueCount)
{
wchar_t temp[256];
swprintf(temp, TRANSLATION(IDS_FIREWALL_QUEUE_NOTIFICATION), mQueueCount);
WideStringClass text(temp, true);
SetWaitText(text);
mLastQueueCount = mQueueCount;
mTimeout = max((unsigned)32000, ((mQueueCount * 32000) + 32000));
mStartTime = TIMEGETTIME();
}
DWORD result = WaitForSingleObject(mEvent, 0);
if (result == WAIT_OBJECT_0)
{
if (mSuccessFlag == FirewallHelperClass::FW_RESULT_SUCCEEDED)
{
WWDEBUG_SAY(("FirewallConnectWait: ConditionMet\n"));
EndWait(ConditionMet, TRANSLATION(IDS_FIREWALL_PORT_NEGOTIATION_COMPLETE));
}
else
{
assert(mSuccessFlag == FirewallHelperClass::FW_RESULT_FAILED);
WWDEBUG_SAY(("FirewallConnectWait: ConditionMet\n"));
EndWait(Error, TRANSLATION(IDS_FIREWALL_PORT_NEGOTIATION_FAILED));
}
}
else if (result == WAIT_FAILED)
{
WWDEBUG_SAY(("FirewallConnectWait: WAIT_FAILED\n"));
EndWait(Error, TRANSLATION(IDS_FIREWALL_PORT_NEGOTIATION_FAILED));
}
}
}
}
if (mEndResult != Waiting)
{
mWOLSession->EnablePinging(true);
}
return mEndResult;
}
//
// Override base class end wait to check for cancel being pressed.
//
void FirewallConnectWait::EndWait(WaitResult result, const wchar_t* endText)
{
WWDEBUG_SAY(("FirewallConnectWait: EndWait\n"));
if (result == UserCancel || result == TimeOut)
{
// Tell the firewall negotiation code to give up.
SetEvent(mCancelEvent);
}
// Give the firewall code a little time to respond then remove it's cancel event anyway. It'll figure it out.
for (int i=0 ; i<100 ; i++)
{
if (mSuccessFlag == FirewallHelperClass::FW_RESULT_CANCELLED)
{
break;
}
Sleep(1);
}
FirewallHelper.Set_Client_Connect_Event(NULL, NULL, NULL, NULL);
SingleWait::EndWait(result, endText);
}

View File

@@ -0,0 +1,119 @@
/*
** 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/>.
*/
/******************************************************************************
*
* FILE
* $Archive: /Commando/Code/Commando/FirewallWait.h $
*
* DESCRIPTION
* Firewall negotiation wait condition.
*
* PROGRAMMER
* $Author: Denzil_l $
*
* VERSION INFO
* $Revision: 6 $
* $Modtime: 8/28/01 3:22p $
*
******************************************************************************/
#ifndef __FIREWALLWAIT_H__
#define __FIREWALLWAIT_H__
#include <WWOnline\WaitCondition.h>
#include <windows.h>
namespace WWOnline
{
class Session;
}
/*
** Wait code for firewall/NAT detection.
**
**
**
*/
class FirewallDetectWait :
public SingleWait
{
public:
static RefPtr<FirewallDetectWait> Create(void);
void WaitBeginning(void);
WaitResult GetResult(void);
protected:
FirewallDetectWait();
virtual ~FirewallDetectWait();
FirewallDetectWait(const FirewallDetectWait&);
const FirewallDetectWait& operator=(const FirewallDetectWait&);
RefPtr<WWOnline::Session> mWOLSession;
unsigned int mPingsRemaining;
HANDLE mEvent;
};
/*
** Wait class for clients when trying to open up a firewall for a server connection.
**
*/
class FirewallConnectWait :
public SingleWait
{
public:
static RefPtr<FirewallConnectWait> Create(void);
void WaitBeginning(void);
WaitResult GetResult(void);
virtual void EndWait(WaitResult, const wchar_t* endText);
protected:
FirewallConnectWait();
virtual ~FirewallConnectWait();
FirewallConnectWait(const FirewallConnectWait&);
const FirewallConnectWait& operator=(const FirewallConnectWait&);
RefPtr<WWOnline::Session> mWOLSession;
unsigned int mPingsRemaining;
HANDLE mEvent;
HANDLE mCancelEvent;
/*
** Did the port negotiation succeed?
*/
int mSuccessFlag;
/*
** How many players in the queue ahead of us?
*/
unsigned int mQueueCount;
unsigned int mLastQueueCount;
unsigned long mStartTime;
};
#endif // __FIREWALLWAIT_H__

View File

@@ -0,0 +1,416 @@
/*
** 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/>.
*/
/******************************************************************************
*
* FILE
* $Archive: /Commando/Code/Commando/GameResSend.cpp $
*
* DESCRIPTION
*
* PROGRAMMER
* $Author: Denzil_l $
*
* VERSION INFO
* $Revision: 25 $
* $Modtime: 1/14/02 10:40a $
*
******************************************************************************/
#include "GameResSend.h"
#include "GameData.h"
#include "Player.h"
#include "consolemode.h"
#include <Combat\PlayerType.h>
#include <WWOnline\GameResPacket.h>
#include <WWOnline\WOLSession.h>
#include <WWOnline\WOLProduct.h>
#include <WWOnline\WOLUser.h>
#include <WWLib\CPUDetect.h>
#include <WWLib\VerChk.h>
#include <WWLib\CPUDetect.h>
#include <WWLib\global.h>
#include <WWLib\md5.h>
#include <WW3D2\DX8Wrapper.h>
#include <windows.h>
using namespace WWOnline;
static void AddPlayerStats(GameResPacket& stats, cPlayer* player, WOL::Locale locale,
int winnerID, bool teamGame);
/******************************************************************************
*
* NAME
* SendGameResults
*
* DESCRIPTION
* Send game results for ladder ranking.
*
* INPUTS
* TheGame - The game played.
* Players - List of players.
*
* RESULT
* NONE
*
******************************************************************************/
void SendGameResults(unsigned long gameID, cGameData* theGame, SList<cPlayer>* playerList)
{
RefPtr<WWOnline::Session> session = WWOnline::Session::GetInstance(false);
if (!session.IsValid())
{
assert(session.IsValid() && "SendGameResults() WOLSession not instantiated.");
WWDEBUG_SAY(("ERROR: SendGameResults() WOLSession not instantiated.\n"));
return;
}
//---------------------------------------------------------------------------
// Gather game information
//---------------------------------------------------------------------------
GameResPacket stats;
// Unique identifier for this game session.
stats.Add_Field("IDNO", gameID);
// Product SKU
RefPtr<Product> product = Product::Current();
unsigned long gameSKU = product->GetSKU();
stats.Add_Field("GSKU", gameSKU);
// Version of executable.
char filename[MAX_PATH];
GetModuleFileName(NULL, filename, sizeof(filename));
VS_FIXEDFILEINFO version;
GetVersionInfo(filename, &version);
stats.Add_Field("VERS", version.dwFileVersionMS);
// Executable build date
FILETIME createTime;
GetFileCreationTime(filename, &createTime);
SYSTEMTIME time;
FileTimeToSystemTime(&createTime, &time);
char buildDate[20];
sprintf(buildDate, "%02d/%02d/%04d %02d:%02d:%02d",
time.wMonth, time.wDay, time.wYear, time.wHour, time.wMinute, time.wSecond);
stats.Add_Field("DATE", buildDate);
// Proocessor information
stats.Add_Field("PROC", (char*)CPUDetectClass::Get_Processor_String());
stats.Add_Field("PSPD", (unsigned long)CPUDetectClass::Get_Processor_Speed());
// Amount of system memory on server
MEMORYSTATUS memStatus;
GlobalMemoryStatus(&memStatus);
stats.Add_Field("SMEM", (unsigned long)memStatus.dwTotalPhys);
// Video card information
DWORD cardInfo[4];
if (ConsoleBox.Is_Exclusive()) {
strcpy((char*)&cardInfo[0], "ConsoleMode");
} else {
const D3DADAPTER_IDENTIFIER8& adapter = DX8Wrapper::Get_Current_Adapter_Identifier();
cardInfo[0] = adapter.VendorId;
cardInfo[1] = adapter.DeviceId;
cardInfo[2] = adapter.SubSysId;
cardInfo[3] = adapter.Revision;
}
stats.Add_Field("SVID", (void*)cardInfo, sizeof(cardInfo));
// WOL Name of server
const WideStringClass& owner = theGame->Get_Owner();
StringClass serverName(true);
owner.Convert_To(serverName);
stats.Add_Field("SNAM", (char*)serverName.Peek_Buffer());
// Type of game played (Deathmatch, Capture the flag, CNC...)
// char* gameMode = (char*)theGame->Get_Game_Type_Name();
stats.Add_Field("MODE", "CNC");
// Name of the map used.
char *map_name = (char*)(theGame->Get_Map_Name().Peek_Buffer());
stats.Add_Field("GMAP", map_name);
// Was this a dedicated server?
bool dedicatedServer = theGame->IsDedicated.Get();
stats.Add_Field("DSVR", (char)dedicatedServer);
// Time game started
LPSYSTEMTIME gameTime = theGame->Get_Game_Start_Time();
char startTime[20];
sprintf(startTime, "%02d/%02d/%04d %02d:%02d:%02d",
gameTime->wMonth, gameTime->wDay, gameTime->wYear, gameTime->wHour, gameTime->wMinute, gameTime->wSecond);
stats.Add_Field("TIME", startTime);
// Duration of game
unsigned long duration = theGame->Get_Duration_Seconds();
stats.Add_Field("DURA", duration);
// Average FPS
unsigned long fps = theGame->Get_Frame_Count();
if (duration > 1)
{
fps = (fps / duration);
}
stats.Add_Field("AFPS", fps);
// Type of tournament
/*
char gameType = 'I';
if (theGame->Is_Team_Game())
{
gameType = 'T';
}
*/
char gameType = 'T';
if (theGame->IsClanGame.Is_True())
{
gameType = 'C';
}
char ranked = (theGame->IsLaddered.Is_True() == true) ? 'Y' : 'N';
char tournament[5];
sprintf(tournament, "%c%c ", gameType, ranked);
stats.Add_Field("TRNY", tournament);
// Include clan information
if (theGame->IsClanGame.Is_True())
{
unsigned long winningClan = 0;
unsigned long losingClan = 0;
int winner = theGame->Get_Winner_ID();
SLNode<cPlayer>* playerNode = playerList->Head();
for (int index = 0; index < playerList->Get_Count(); index++)
{
cPlayer* player = playerNode->Data();
if (player->Is_Human())
{
RefPtr<UserData> user = session->FindUser(player->Get_Name());
if (user.IsValid() && (user->GetSquadID() != 0))
{
int playerType = player->Get_Player_Type();
if ((playerType == winner) && (winningClan == 0))
{
winningClan = user->GetSquadID();
}
else if (losingClan == 0)
{
losingClan = user->GetSquadID();
}
else
{
break;
}
}
}
}
stats.Add_Field("CLN1", winningClan);
stats.Add_Field("CLN2", losingClan);
}
//---------------------------------------------------------------------------
// Player information
//---------------------------------------------------------------------------
// Determine the number of players in the game
unsigned long numPlayers = 0;
SLNode<cPlayer>* playerNode = playerList->Head();
for (int index = 0; index < playerList->Get_Count(); index++)
{
cPlayer* player = playerNode->Data();
if (player->Is_Human())
{
numPlayers++;
}
}
stats.Add_Field("PLRS", numPlayers);
// Gather per-player information
int winnerID = theGame->Get_Winner_ID();
playerNode = playerList->Head();
for (index = 0; index < playerList->Get_Count(); index++)
{
cPlayer* player = playerNode->Data();
if (player)
{
const WideStringClass& playerName = player->Get_Name();
// Player Location
WOL::Locale locale = WOL::LOC_UNKNOWN;
RefPtr<UserData> user = session->FindUser((const WCHAR*)playerName);
if (user.IsValid())
{
locale = user->GetLocale();
}
AddPlayerStats(stats, player, locale, winnerID, true);
}
playerNode = playerNode->Next();
}
unsigned long packetSize = 0;
unsigned long sig_offset = 0;
unsigned char* packet = stats.Create_Comms_Packet(packetSize, NULL, sig_offset);
WWDEBUG_SAY(("Sending game results packet. Size = %lu\n", packetSize));
#if(0)
#ifdef _DEBUG
HANDLE file = CreateFile("GameRes.dat", GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL, NULL);
if (INVALID_HANDLE_VALUE != file)
{
// Write generic contents
DWORD written;
WriteFile(file, packet, packetSize, &written, NULL);
CloseHandle(file);
}
else
{
WWDEBUG_SAY(("Failed to create GameRes.dat file."));
}
#endif
#endif
session->SendGameResults(packet, packetSize);
}
/******************************************************************************
*
* NAME
* AddPlayerStats
*
* DESCRIPTION
*
* INPUTS
* Stats - Game result packet to add player stats to.
* Player - Player to add stats for.
*
* RESULT
* NONE
*
******************************************************************************/
void AddPlayerStats(GameResPacket& stats, cPlayer* player, WOL::Locale locale,
int winnerID, bool isTeamed)
{
if (player->Is_Human())
{
// Players WOL name
const WideStringClass& playerName = player->Get_Name();
char name[10];
int len = wcstombs(name, (const WCHAR*)playerName, 10);
name[len] = 0;
stats.Add_Field("PNAM", name);
stats.Add_Field("PLOC", (unsigned long)locale);
int playerType = player->Get_Player_Type();
// Team (bit 31:win/lose, bits 7-0:team (0 = none, 1 = GDI, 2= NOD)
unsigned long team = 0;
if (isTeamed)
{
if (playerType == PLAYERTYPE_GDI)
{
team = 1;
}
else if (playerType == PLAYERTYPE_NOD)
{
team = 2;
}
}
if ((isTeamed && playerType == winnerID) || (!isTeamed && player->Get_Id() == winnerID))
{
team |= 0x80000000;
}
stats.Add_Field("TEAM", team);
// Score and other information
unsigned long score = (unsigned long)max<int>(player->Get_Score(), 0);
stats.Add_Field("PSCR", score);
stats.Add_Field("PPTS", (long)player->Get_Ladder_Points());
stats.Add_Field("PTIM", (unsigned long)player->Get_Game_Time());
stats.Add_Field("PHLT", (unsigned long)player->Get_Final_Health());
stats.Add_Field("PKIL", (unsigned long)player->Get_Deaths());
stats.Add_Field("EKIL", (unsigned long)player->Get_Enemies_Killed());
stats.Add_Field("AKIL", (unsigned long)player->Get_Allies_Killed());
stats.Add_Field("SHOT", (unsigned long)player->Get_Shots_Fired());
stats.Add_Field("HEDF", (unsigned long)player->Get_Head_Shots());
stats.Add_Field("TORF", (unsigned long)player->Get_Torso_Shots());
stats.Add_Field("ARMF", (unsigned long)player->Get_Arm_Shots());
stats.Add_Field("LEGF", (unsigned long)player->Get_Leg_Shots());
stats.Add_Field("CRTF", (unsigned long)player->Get_Crotch_Shots());
stats.Add_Field("PUPS", (unsigned long)player->Get_Powerups_Collected());
stats.Add_Field("VKIL", (unsigned long)player->Get_Vehiclies_Destroyed());
stats.Add_Field("VTIM", (unsigned long)player->Get_Vehicle_Time());
stats.Add_Field("NKFV", (unsigned long)player->Get_Kills_From_Vehicle());
stats.Add_Field("SQUI", (unsigned long)player->Get_Squishes());
stats.Add_Field("PCRD", (unsigned long)player->Get_Credit_Grant());
stats.Add_Field("BKIL", (unsigned long)player->Get_Building_Destroyed());
stats.Add_Field("HEDR", (unsigned long)player->Get_Head_Hit());
stats.Add_Field("TORR", (unsigned long)player->Get_Torso_Hit());
stats.Add_Field("ARMR", (unsigned long)player->Get_Arm_Hit());
stats.Add_Field("LEGR", (unsigned long)player->Get_Leg_Hit());
stats.Add_Field("CRTR", (unsigned long)player->Get_Crotch_Hit());
stats.Add_Field("FLGC", (unsigned long)0);//no more CTF! (unsigned long)player->Get_Flag_Caps());
// Weapon usage
int numWeapons = min<int>(255, player->Get_Weapon_Fired_Count());
for (int wepIndex = 0; wepIndex < numWeapons; wepIndex++)
{
unsigned long weaponInfo[2] = {0,0};
player->Get_Weapon_Fired(wepIndex, weaponInfo[0], weaponInfo[1]);
char token[5];
sprintf(token, "WP%02X", wepIndex);
stats.Add_Field(token, (void*)weaponInfo, sizeof(weaponInfo));
}
}
}

View File

@@ -0,0 +1,49 @@
/*
** 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/>.
*/
/******************************************************************************
*
* FILE
* $Archive: /Commando/Code/Commando/GameResSend.h $
*
* DESCRIPTION
*
* PROGRAMMER
* $Author: Denzil_l $
*
* VERSION INFO
* $Revision: 2 $
* $Modtime: 8/16/01 7:03p $
*
******************************************************************************/
#ifndef __GAMERESSEND_H__
#define __GAMERESSEND_H__
#include <WWLib\SList.h>
class cGameData;
class cPlayer;
void SendGameResults(unsigned long gameID, cGameData* theGame, SList<cPlayer>* players);
#ifdef _DEBUG
void SendTestGameResults(void);
#endif
#endif // __GAMERESSEND_H__

View File

@@ -0,0 +1,345 @@
/*
** 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/>.
*/
/***********************************************************************************************
*** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : Renegade *
* *
* $Archive:: /Commando/Code/Commando/GameSpyBanList.cpp $*
* *
* Original Author:: Brian Hayes *
* *
* $Author:: Bhayes $*
* *
* $Modtime:: 3/15/02 2:55p $*
* *
* $Revision:: 3 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
//
// Filename: GameSpyBanList.cpp
// Author: Brian Hayes
// Date: Mar 2002
// Description: Maintains a list of banned nicknames/hashes/ipaddresses for GameSpy Servers
//
#include "cnetwork.h"
#include "listnode.h"
#include "GameSpyBanList.h"
#include "ini.h"
#include "registry.h"
#include "rawfile.h"
#include "gamespyauthmgr.h"
#include "sctextobj.h"
#include "consolemode.h"
#include "gamesideservercontrol.h"
cGameSpyBanList GameSpyBanList;
BanEntry::BanEntry(const char *name, const char *ip, const char *hash_id, const char *ip_mask, bool rtype) {
memset(nickname, 0, sizeof(nickname));
ipaddress = 0;
ipmask = 0xffffffff;
memset(hashid, 0, sizeof(hashid));
ruletype = rtype;
if (name) {
strncpy(nickname, name, sizeof(nickname) - 1);
}
if (ip) ipaddress = inet_addr(ip);
if (hash_id) {
strncpy(hashid, hash_id, sizeof(hashid) - 1);
}
if (ip_mask) {
ipmask = inet_addr(ip_mask);
if (!ipmask) ipmask = 0xffffffff;
}
}
cGameSpyBanList::cGameSpyBanList() : BanList(NULL) {
BanList = new List<BanEntry *> ();
}
cGameSpyBanList::~cGameSpyBanList() {
BanList->Delete();
delete BanList;
}
void cGameSpyBanList::Ban_User(const char *nickname, const char *challenge_response, DWORD ipaddr) {
char *buff = NULL;
char *q = NULL;
FILE *outf = NULL;
BanEntry *t = NULL;
if (nickname && !challenge_response) {
q = buff = new char[(strlen(nickname)*2)+1];
const char *n = nickname;
while (*n) {
if (*n == '%') *q++ = '%';
*q++ = *n++;
}
*q = 0;
t = new BanEntry(buff);
delete [] buff;
} else if (challenge_response) {
t = new BanEntry(NULL, NULL, challenge_response);
} else if (ipaddr) {
t = new BanEntry(NULL, cNetUtil::Address_To_String(ipaddr));
} else {
return;
}
BanList->Add_Tail(t);
outf = fopen("banlist.txt", "at");
if (outf) {
fprintf(outf, "\"%s\" \"%s\" \"%s\" \"%s\" \"%s\"; \"%s\" console BAN\n", t->Get_Rule_Type() ? "Allow" : "Deny",
t->Get_Nick_Name(), t->Get_Hash_ID(),
t->Get_Ip_Address() ? cNetUtil::Address_To_String(t->Get_Ip_Address()) : "",
t->Get_Ip_Address() ? "255.255.255.255" : "", nickname ? nickname : "");
fclose(outf);
}
}
void cGameSpyBanList::Think(void) {
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 ();
WWASSERT (player != NULL);
if (player->Get_Is_Active().Is_False() || !player->Is_Human()) {
continue;
}
if (player->Get_GameSpy_Kick_State() == GAMESPY_KICK_STATE_BEGIN &&
TIMEGETTIME() - player->Get_GameSpy_Kick_State_Entry_Time_Ms() > 3000) {
Final_Player_Kick(player->Get_Id());
} else if (player->Get_GameSpy_Kick_State() == GAMESPY_KICK_STATE_INITIAL &&
player->Get_GameSpy_Auth_State() == GAMESPY_AUTH_STATE_ACCEPTED) {
if (Is_User_Banned(StringClass(player->Get_Name()), player->Get_GameSpy_Hash_Id(),
player->Get_Ip_Address())) {
Begin_Player_Kick(player->Get_Id());
} else {
player->Set_GameSpy_Kick_State(GAMESPY_KICK_STATE_APPROVED);
}
}
}
}
bool cGameSpyBanList::Begin_Player_Kick(int id) {
cPlayer *player = cPlayerManager::Find_Player(id);
if (player && player->Get_Is_Active().Is_True() && player->Is_Human()) {
cScTextObj * p_message = new cScTextObj;
p_message->Init(L"You've been kicked from the server. Please quit.", TEXT_MESSAGE_PRIVATE, true, HOST_TEXT_SENDER, player->Get_Id());
player->Set_GameSpy_Kick_State(GAMESPY_KICK_STATE_BEGIN);
return true;
}
return false;
}
bool cGameSpyBanList::Final_Player_Kick(int id) {
cPlayer *player = cPlayerManager::Find_Player(id);
if (player && player->Get_Is_Active().Is_True() && player->Is_Human()) {
StringClass user_name = player->Get_Name();
ConsoleBox.Print("%s was kicked\n", user_name);
player->Set_GameSpy_Kick_State(GAMESPY_KICK_STATE_KICKED);
cNetwork::Server_Kill_Connection(id);
cNetwork::Cleanup_After_Client(id);
return true;
}
return false;
}
bool cGameSpyBanList::Is_User_Banned(const char *nickname, const char *challenge_response,
DWORD ipaddress) {
BanEntry *t = BanList->First();
bool ret = false;
for (;t && t->Is_Valid(); t = t->Next()) {
if (challenge_response && *challenge_response &&
strcmp(challenge_response, t->Get_Hash_ID()) == 0) {
ret = true;
} else if (t->Get_Hash_ID() && strlen(t->Get_Hash_ID())){
ret = false;
continue;
}
if (ipaddress && t->Get_Ip_Address() && ((ipaddress & t->Get_Ip_Netmask()) ==
(t->Get_Ip_Address() & t->Get_Ip_Netmask()))) {
ret = true;
} else if (t->Get_Ip_Address()) {
ret = false;
continue;
}
if (t->Get_Nick_Name() && nickname && strlen(t->Get_Nick_Name()) && strlen(nickname)) {
char *a = strdup(t->Get_Nick_Name());
char *b = strdup(nickname);
_strupr(a); _strupr(b);
//
// This code means that you can put a BAN name in as
// "%foo" == match on "foo" at the end of the string
// "foo%" == match on "foo" at the beginning of the string
// "%foo%" == match on "foo" anywhere in the string
//
// to match on a literal % in the nickname use %%
//
// Note the use of small var names to make it even more confusing
if ( ((a[0] == '%') && (a[1] != '%')) &&
((a[strlen(a)-1] == '%') && (a[strlen(a)-2] != '%')) ) {
a[0] = 0;
a[strlen(&a[1])] = 0;
Strip_Escapes(&a[1]);
ret = (strstr(b, &a[1]) != NULL);
} else if ((a[0] == '%') && (a[1] != '%')) {
a[0] = 0;
Strip_Escapes(&a[1]);
if (strlen(b) > (strlen(&a[1])-1)) {
ret = (strcmp(&b[strlen(b)-strlen(&a[1])], &a[1]) == 0);
}
} else if (strlen(a) > 1 && (a[strlen(a)-1] == '%') && (a[strlen(a)-2] != '%')) {
a[strlen(a)-1] = 0;
Strip_Escapes(a);
if (strlen(b) > (strlen(a)-1)) {
b[strlen(a)] = 0;
ret = (strcmp(b, a) == 0);
}
} else {
Strip_Escapes(a);
ret = (strcmp(b, a) == 0);
}
free(a); free(b);
}
if (ret) {
ret = !t->Get_Rule_Type();
break;
}
}
if (t && t->Is_Valid()) {
// matched on a rule
return ret;
} else {
// Everyone is good if they don't match a rule
return false;
}
}
void cGameSpyBanList::Strip_Escapes(char *var) {
char *q = (char *)var;
while ((q = strstr(q, "%%")) != NULL) {
memmove(q, q+1, strlen(q));
q++;
}
}
void cGameSpyBanList::LoadBans(void) {
char buff[512];
FILE *outf = NULL;
if (!BanList->Is_Empty()) BanList->Delete();
outf = fopen("banlist.txt", "rt");
if (!outf) return;
buff[sizeof(buff)-1] = 0;
while (fgets(buff, sizeof(buff)-1, outf)) {
// Format of each line "ruletype" "nickname" "hashid" "ip" "netmask"
char *nickname = NULL;
char *ruletype = NULL;
char *ip = NULL;
char *hashid = NULL;
char *ipmask = NULL;
if (strlen(buff) < 3) continue;
if (buff[0] == ';') continue;
char *s = strchr(buff, '"');
if (!s) continue;
*s++ = 0;
char *q = strchr(s, '"');
if (!q) continue;
*q++ = 0;
ruletype = s;
s = strchr(q, '"');
if (!s) continue;
*s++ = 0;
q = strchr(s, '"');
if (!q) continue;
*q++ = 0;
nickname = s;
while (q) {
s = strchr(q, '"');
if (!s) break;
*s++ = 0;
q = strchr(s, '"');
if (!q) break;
*q++ = 0;
hashid = s;
s = strchr(q, '"');
if (!s) break;
*s++ = 0;
q = strchr(s, '"');
if (!q) break;
*q++ = 0;
ip = s;
s = strchr(q, '"');
if (!s) break;
*s++ = 0;
q = strchr(s, '"');
if (!q) break;
*q++ = 0;
ipmask = s;
break;
}
BanEntry *t = new BanEntry(nickname, ip, hashid, ipmask, stricmp(ruletype, "Allow") == 0);
BanList->Add_Tail(t);
}
fclose(outf);
}

View File

@@ -0,0 +1,84 @@
/*
** 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/>.
*/
//
// Filename: GameSpyBanList.h
// Author: Brian Hayes
// Date: Mar 2002
// Description: Maintains a list of banned nicknames/hashes/ipaddresses for GameSpy Servers
//
#ifndef __GAMESPYBANLIST_H__
#define __GAMESPYBANLIST_H__
#include "bittype.h"
enum GAMESPY_KICK_STATE_ENUM
{
GAMESPY_KICK_STATE_INITIAL = 0, // Just connected
GAMESPY_KICK_STATE_APPROVED, // This user is not in the ban list
GAMESPY_KICK_STATE_BEGIN, // Give them a message before we boot him
GAMESPY_KICK_STATE_KICKED, // outta here.
GAMESPY_KICK_STATE_COUNT
};
class BanEntry : public Node<BanEntry *> {
public:
BanEntry(const char *name = NULL, const char *ip = NULL, const char *hash_id = NULL,
const char *ip_mask = NULL, bool rtype = false);
protected:
char hashid[33];
char nickname[40];
ULONG ipaddress;
ULONG ipmask;
bool ruletype;
public:
const char *Get_Nick_Name(void) {return (const char *)nickname;}
const char *Get_Hash_ID(void) {return (const char *)hashid;}
ULONG Get_Ip_Address(void) {return ipaddress;}
ULONG Get_Ip_Netmask(void) {return ipmask;}
bool Get_Rule_Type(void) {return ruletype;}
};
class cGameSpyBanList
{
public:
cGameSpyBanList();
~cGameSpyBanList();
protected:
List<BanEntry *> * BanList;
bool Final_Player_Kick(int id);
bool Begin_Player_Kick(int id);
void Strip_Escapes(char *var);
public:
void Think(void);
bool Kick_Player(int id) { return Begin_Player_Kick(id);}
void Ban_User(const char *nickname, const char *challenge_response = NULL,
ULONG ipaddress = 0xffffffff);
bool Is_User_Banned(const char *nickname, const char *challenge_response, ULONG ipaddress);
void LoadBans(void);
};
extern cGameSpyBanList GameSpyBanList;
#endif // __GAMESPYBANLIST_H__

View File

@@ -0,0 +1,782 @@
/*
** 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/GameSpy_QnR.cpp $*
* *
* $Author:: Greg_h $*
* *
* $Modtime:: 7/08/02 5:55p $*
* *
* $Revision:: 17 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include <Gamespy\gs_patch_usage.h>
#include <Gamespy\gcdkeyserver.h>
#include "specialbuilds.h"
#include "dlgcncteaminfo.h"
#include "resource.h"
#include "listctrl.h"
#include "imagectrl.h"
#include "playertype.h"
#include "combat.h"
#include "teammanager.h"
#include "playermanager.h"
#include "player.h"
#include "soldier.h"
#include "gameinitmgr.h"
#include "gamemode.h"
#include "gamedata.h"
#include "input.h"
#include "healthbarctrl.h"
#include "basecontroller.h"
#include "building.h"
#include "damage.h"
#include "vehicle.h"
#include "assets.h"
#include "translatedb.h"
#include "WOLGMode.h"
#include <WWOnline\WOLUser.h>
#include "string_ids.h"
#include "mousemgr.h"
#include "directinput.h"
#include "GameSpy_QnR.h"
#include "verchk.h"
#include "buildnum.h"
#include "serversettings.h"
#include "consolemode.h"
#include "useroptions.h"
#include "gdcnc.h"
#include "rawfile.h"
#include "shellapi.h"
#include "netutil.h"
#include "gamespybanlist.h"
CGameSpyQnR GameSpyQnR;
#if defined(MULTIPLAYERDEMO)
const char *CGameSpyQnR::gamename = "ccrenegadedemo";
const char *CGameSpyQnR::bname = "Demo";
const int CGameSpyQnR::prodid = 10063;
const int CGameSpyQnR::cdkey_id = 0;
#elif defined(FREEDEDICATEDSERVER)
const char *CGameSpyQnR::bname = "FDS";
const char *CGameSpyQnR::gamename = "ccrenegade";
const int CGameSpyQnR::prodid = 10064;
const int CGameSpyQnR::cdkey_id = 577;
#elif defined(BETACLIENT)
const char *CGameSpyQnR::bname = "Beta";
const char *CGameSpyQnR::gamename = "ccrenegade";
const int CGameSpyQnR::prodid = 10064;
const int CGameSpyQnR::cdkey_id = 0;
#else
const char *CGameSpyQnR::bname = "Retail";
const char *CGameSpyQnR::gamename = "ccrenegade";
const int CGameSpyQnR::prodid = 10064;
const int CGameSpyQnR::cdkey_id = 577;
#endif
const char *CGameSpyQnR::default_heartbeat_list = "master.gamespy.com:27900, master.udpsoft.com:27900";
/*********
These c-style callback stubs are used by the SDK. The current game object
(passed in qr_init) is given in userdata, so we know what object to reference
**********/
void c_players_callback(char *outbuf, int maxlen, void *userdata)
{
((CGameSpyQnR *)userdata)->players_callback(outbuf, maxlen);
}
void c_rules_callback(char *outbuf, int maxlen, void *userdata)
{
((CGameSpyQnR *)userdata)->rules_callback(outbuf, maxlen);
}
void c_info_callback(char *outbuf, int maxlen, void *userdata)
{
((CGameSpyQnR *)userdata)->info_callback(outbuf, maxlen);
}
void c_basic_callback(char *outbuf, int maxlen, void *userdata)
{
((CGameSpyQnR *)userdata)->basic_callback(outbuf, maxlen);
}
/***********
A simple game object. Consists of some data and a main loop function.
***********/
CGameSpyQnR::CGameSpyQnR(void) : m_GSInit(FALSE), m_GSEnabled(FALSE)
{
// Secret keys removed per Security review requirements. LFeenanEA - 27th January 2025
//set the secret key, in a semi-obfuscated manner
// tY1S8q = FULL , LsEwS3 = DEMO
#ifdef MULTIPLAYERDEMO
secret_key[3] = 'R'; if (secret_key[3])
secret_key[1] = 'E'; if (secret_key[1])
secret_key[0] = 'M'; if (secret_key[0])
secret_key[4] = 'O'; if (secret_key[4])
secret_key[5] = 'V'; if (secret_key[5])
secret_key[3] = 'E'; if (secret_key[3])
secret_key[2] = 'D'; if (secret_key[2])
secret_key[6] = '1'; if (secret_key[2])
secret_key[5] = '2'; if (secret_key[5])
secret_key[4] = '3';
#else
secret_key[5] = 'R'; if (secret_key[5])
secret_key[4] = 'E'; if (secret_key[4])
secret_key[6] = 'M'; if (secret_key[4])
secret_key[1] = 'O'; if (secret_key[1])
secret_key[5] = 'V'; if (secret_key[5])
secret_key[2] = 'E'; if (secret_key[2])
secret_key[3] = 'D'; if (secret_key[3])
secret_key[6] = '1'; if (secret_key[3])
secret_key[0] = '2'; if (secret_key[0])
secret_key[3] = '3';
#endif
}
CGameSpyQnR::~CGameSpyQnR()
{
Shutdown();
}
void CGameSpyQnR::LaunchArcade(void) {
char *akey = "Software\\GameSpy\\GameSpy Arcade";
BOOL launched = FALSE;
HKEY key = NULL;
int result = 0;
result = RegOpenKeyEx(HKEY_CURRENT_USER, akey, 0, KEY_READ, &key);
if (result == ERROR_SUCCESS) {
StringClass value(true);
//
// Get the size of the entry
//
DWORD data_size = 0;
DWORD type = 0;
result = ::RegQueryValueEx ((HKEY)key, "InstDir", NULL, &type, NULL, &data_size);
if (result == ERROR_SUCCESS && type == REG_SZ) {
//
// Read the entry from the registry
//
::RegQueryValueEx ((HKEY)key, "InstDir", NULL, &type,
(LPBYTE)value.Get_Buffer(data_size), &data_size);
}
if (!value.Is_Empty()) {
if (value[value.Get_Length()-1] == '\\') {
value += "Aphex.exe";
} else {
value += "\\Aphex.exe";
}
RawFileClass file(value);
if (file.Is_Available()) {
StringClass params("+svc ");
params += gamename;
if (((int)ShellExecute (NULL, "open", value, params, NULL, SW_SHOW)) > 32) {
launched = TRUE;
}
}
}
}
if (!launched) {
char url[1000] = "";
#ifdef MULTIPLAYERDEMO
::strcpy(url, "http://www.gamespyarcade.com/features/launch.asp?svcname=ccrenegadedemo&distID=432");
#else
::strcpy(url, "http://www.gamespyarcade.com/features/launch.asp?svcname=ccrenegade&distID=391");
#endif
ShellExecute (NULL, "open", url, NULL, NULL, SW_SHOW);
}
}
void CGameSpyQnR::Shutdown(void) {
#ifndef BETACLIENT
if (m_GSInit) {
/*
We don't really need to set the mode to exiting here, since we immediately
send the statechanged heartbeat and kill off the query sockets
gamemode = "exiting";*/
ConsoleBox.Print("Shutting down GameSpy Q&R\n");
qr_send_exiting(query_reporting_rec);
qr_shutdown(query_reporting_rec);
m_GSEnabled = m_GSInit = false;
}
#endif
}
void CGameSpyQnR::TrackUsage(void) {
#ifndef WWDEBUG
char filename[MAX_PATH];
GetModuleFileName(NULL, filename, sizeof(filename));
VS_FIXEDFILEINFO version;
GetVersionInfo(filename, &version);
int ver = version.dwFileVersionMS;
StringClass b(true);
b.Format("%s %s V%d.%3.3d(%s-%d)", "Win-X86", bname, (ver&0xffff0000)>>16, ver&0xffff,
BuildInfoClass::Get_Builder_Initials(), BuildInfoClass::Get_Build_Number());
// Send off usage Tracking info to GameSpy
ptTrackUsage(0, prodid, b.Peek_Buffer(), (cUserOptions::Sku.Get()&0xff)+438, false);
#endif // WWDEBUG
}
void CGameSpyQnR::Init(void) {
#ifndef BETACLIENT
if (m_GSEnabled && !m_GSInit && The_Game() && The_Game()->Get_Game_Type() == cGameData::GAME_TYPE_CNC) {
ConsoleBox.Print("Initializing GameSpy Q&R\n");
BOOL test = FALSE;
// Init the GameSpy QnR engine
extern ULONG g_ip_override;
char ipstr[32];
char *ip = ipstr;
if (g_ip_override == INADDR_NONE) {
if (cUserOptions::PreferredGameSpyNic.Get()) {
strcpy(ip, cNetUtil::Address_To_String(cUserOptions::PreferredGameSpyNic.Get()));
} else {
ip = NULL;
}
} else {
strcpy(ip, cNetUtil::Address_To_String(g_ip_override));
}
if (!get_master_count()) {
GameSpyQnR.Parse_HeartBeat_List(Get_Default_HeartBeat_List());
}
test = qr_init(&query_reporting_rec, ip, cUserOptions::GameSpyQueryPort.Get(),
gamename, secret_key, c_basic_callback, c_info_callback, c_rules_callback,
c_players_callback, this);
WWASSERT(!test);
gcd_init_qr(query_reporting_rec, cdkey_id);
StartTime = time(NULL);
m_GSInit = TRUE;
}
#endif
}
/*******
DoGameStuff
Simulate whatever else a game server does
********/
void CGameSpyQnR::DoGameStuff(void)
{
// Sleep(100);
}
#define BANLIST_RELOAD_TIME (1*60*1000)
/*******************
CGameSpyQnR::run
Simulates a main game loop
*****************/
void CGameSpyQnR::Think()
{
static DWORD stime = (DWORD)(0 - BANLIST_RELOAD_TIME);
static DWORD ttime = 0;
if (TIMEGETTIME() - stime > BANLIST_RELOAD_TIME) {
GameSpyBanList.LoadBans();
stime = TIMEGETTIME();
}
// check twice a second
if (TIMEGETTIME() - ttime > 500) {
GameSpyBanList.Think();
ttime = TIMEGETTIME();
}
#ifndef BETACLIENT
// DoGameStuff();
if (m_GSInit && m_GSEnabled && GameInitMgrClass::Is_LAN_Initialized() &&
!CombatManager::Is_Loading_Level()) {
qr_process_queries(query_reporting_rec);
gcd_think();
}
#endif
}
/*************
basic_callback
sends a (sample) response to the basic query
includes the following keys:
\gamename\
\gamever\
\location\
*************/
void CGameSpyQnR::basic_callback(char *outbuf, int maxlen)
{
WWDEBUG_SAY(("-->GS_QnR -- Basic callback\n"));
WWASSERT(!CombatManager::Is_Loading_Level());
if (!maxlen || !outbuf) return;
outbuf[0] = 0;
StringClass b(true);
b.Format("%d", BuildInfoClass::Get_Build_Number());
sprintf(outbuf, "\\gamename\\%s\\gamever\\%s", gamename, b.Peek_Buffer());
// sprintf(outbuf, "\\gamename\\%s\\gamever\\%s\\location\\%d", gamename, b.Peek_Buffer(), 1);
#ifdef WWDEBUG
StringClass tstr(true);
tstr.Format("GS_QnR -- Basic callback, sent: %s\n",outbuf);
OutputDebugString(tstr.Peek_Buffer());
#endif
WWDEBUG_SAY(("<--GS_QnR -- Basic callback\n"));
// printf("Basic callback, sent: %s\n\n",outbuf);
}
/************
info_callback
Sends a (sample) response to the info query
including the following keys:
\hostname\
\hostport\
\mapname\
\gametype\
\numplayers\
\maxplayers\
\gamemode\
************/
void CGameSpyQnR::info_callback(char *outbuf, int maxlen)
{
WWDEBUG_SAY(("-->GS_QnR -- Info callback\n"));
WWASSERT(!CombatManager::Is_Loading_Level());
if (!maxlen || !outbuf) return;
outbuf[0] = 0;
while(1) {
StringClass value(true);
WideStringClass(The_Game()->Get_Game_Title()).Convert_To(value);
if (value.Get_Length() > 25) {
value[25] = 0;
}
if (!Append_InfoKey_Pair(outbuf, maxlen, "hostname", value)) break;
value.Format("%d", The_Game()->Get_Port());
if (!Append_InfoKey_Pair(outbuf, maxlen, "hostport", value)) break;
value = The_Game()->Get_Map_Name();
char *s = value.Peek_Buffer();
char *t = strrchr(s, '.');
if (t) value.Erase(t-s, s+strlen(s)-t);
if (!Append_InfoKey_Pair(outbuf, maxlen, "mapname", value)) break;
value = The_Game()->Get_Mod_Name();
if (!value.Is_Empty()) {
s = value.Peek_Buffer();
t = strrchr(s, '.');
if (t) value.Erase(t-s, s+strlen(s)-t);
if (!Append_InfoKey_Pair(outbuf, maxlen, "gametype", value)) break;
} else {
if (!Append_InfoKey_Pair(outbuf, maxlen, "gametype", "C&C")) break;
}
int pcount = 0;
for (SLNode<cPlayer> *player_node = cPlayerManager::Get_Player_Object_List ()->Head ()
; player_node != NULL; player_node = player_node->Next ()) {
cPlayer *player = player_node->Data ();
WWASSERT (player != NULL);
if (player->Get_Is_Active().Is_False()) {
// if (player->Get_Is_Active().Is_False() || !player->Is_Human()) {
continue;
}
pcount++;
}
value.Format("%d", pcount);
if (!Append_InfoKey_Pair(outbuf, maxlen, "numplayers", value)) break;
value.Format("%d", The_Game()->Get_Max_Players());
if (!Append_InfoKey_Pair(outbuf, maxlen, "maxplayers", value)) break;
// if (!Append_InfoKey_Pair(outbuf, maxlen, "gamemode", "openplaying")) break;
break;
}
#ifdef WWDEBUG
StringClass tstr(true);
tstr.Format("GS_QnR -- Info callback, sent: %s\n",outbuf);
OutputDebugString(tstr.Peek_Buffer());
#endif
WWDEBUG_SAY(("<--GS_QnR -- Info callback\n"));
}
/***************
rules_callback
Sends a response to the rules query. You may
need to add custom fields for your game in here. Some are provided
as an example
The following rules are included:
\timelimit\
\fraglimit\
\teamplay\
\rankedserver\
****************/
void CGameSpyQnR::rules_callback(char *outbuf, int maxlen)
{
static StringClass b;
WWDEBUG_SAY(("-->GS_QnR -- Rules callback\n"));
WWASSERT(!CombatManager::Is_Loading_Level());
if (!maxlen || !outbuf) return;
outbuf[0] = 0;
while(1) {
StringClass value(true);
const char *zero = "0"; const char *one = "1";
// WideStringClass timelimit;
// The_Game()->Get_Time_Limit_Text(timelimit);
// if (!Append_InfoKey_Pair(outbuf, maxlen, "timeleft", timelimit)) break;
// value.Format("%d", The_Game()->Get_Time_Limit_Minutes());
// if (!Append_InfoKey_Pair(outbuf, maxlen, "timelimit", value)) break;
// if (b.Is_Empty()) {
// char filename[MAX_PATH];
// GetModuleFileName(NULL, filename, sizeof(filename));
// VS_FIXEDFILEINFO version;
// GetVersionInfo(filename, &version);
// int ver = version.dwFileVersionMS;
//
// b.Format("%s %s V%d.%3.3d(%s-%d)", "Win-X86", bname, (ver&0xffff0000)>>16, ver&0xffff,
// BuildInfoClass::Get_Builder_Initials(), BuildInfoClass::Get_Build_Number());
// }
// if (!Append_InfoKey_Pair(outbuf, maxlen, "Version", b)) break;
// if (!Append_InfoKey_Pair(outbuf, maxlen, "ServerMOTD", WideStringClass(The_Game()->Get_Motd()))) break;
// if (!Append_InfoKey_Pair(outbuf, maxlen, "OwnerName", The_Game()->Get_Owner())) break;
value.Format("%d", (int)cUserOptions::BandwidthBps.Get());
if (!Append_InfoKey_Pair(outbuf, maxlen, "BW", value)) break;
// int utime = time(NULL) - StartTime;
// value.Format("%d:%d:%d:%d", utime/60/60/24, (utime/60/60)%24, (utime/60)%60, utime%60);
// if (!Append_InfoKey_Pair(outbuf, maxlen, "Uptime", value)) break;
if (!Append_InfoKey_Pair(outbuf, maxlen, "CSVR", ConsoleBox.Is_Exclusive() ? one : zero)) break;
if (!Append_InfoKey_Pair(outbuf, maxlen, "DED", The_Game()->IsDedicated.Get() ? one : zero)) break;
if (!Append_InfoKey_Pair(outbuf, maxlen, "DG", The_Game()->DriverIsAlwaysGunner.Get() ? one : zero)) break;
if (!Append_InfoKey_Pair(outbuf, maxlen, "password", The_Game()->IsPassworded.Get() ? one : zero)) break;
if (!Append_InfoKey_Pair(outbuf, maxlen, "TC", The_Game()->IsTeamChangingAllowed.Get() ? one : zero)) break;
// if (!Append_InfoKey_Pair(outbuf, maxlen, "WeaponSpawning", The_Game()->SpawnWeapons.Get() ? one : zero)) break;
// if (!Append_InfoKey_Pair(outbuf, maxlen, "TeamRemix", The_Game()->RemixTeams.Get() ? one : zero)) break;
// if (!Append_InfoKey_Pair(outbuf, maxlen, "BuildingRepair", The_Game()->CanRepairBuildings.Get() ? one : zero)) break;
if (!Append_InfoKey_Pair(outbuf, maxlen, "FF", The_Game()->IsFriendlyFirePermitted.Get() ? one : zero)) break;
// if (!Append_InfoKey_Pair(outbuf, maxlen, "BaseDestructionEndsGame", The_Game()->As_Cnc()->BaseDestructionEndsGame.Get() ? one : zero)) break;
// if (!Append_InfoKey_Pair(outbuf, maxlen, "BeaconPlacementEndsGame", The_Game()->As_Cnc()->BeaconPlacementEndsGame.Get() ? one : zero)) break;
// value.Format("%d", (int)The_Game()->Get_Radar_Mode());
// if (!Append_InfoKey_Pair(outbuf, maxlen, "RadarMode", value)) break;
value.Format("%d", The_Game()->As_Cnc()->Get_Starting_Credits());
if (!Append_InfoKey_Pair(outbuf, maxlen, "SC", value)) break;
// cTeam * p_team;
// for (SLNode<cTeam> * objnode = cTeamManager::Get_Team_Object_List()->Head()
// ; objnode != NULL; objnode = objnode->Next()) {
//
// p_team = objnode->Data();
// WWASSERT(p_team != NULL);
//
// if (p_team->Get_Id() == PLAYERTYPE_GDI) {
// value.Format("%.0f", p_team->Get_Score());
// if (!Append_InfoKey_Pair(outbuf, maxlen, "GDI_Score", value)) break;
// } else if (p_team->Get_Id() == PLAYERTYPE_NOD) {
// value.Format("%.0f", p_team->Get_Score());
// if (!Append_InfoKey_Pair(outbuf, maxlen, "NOD_Score", value)) break;
// }
// }
// These don't apply to LAN/GameSpy Games
// if (!Append_InfoKey_Pair(outbuf, maxlen, "ClanMatch", The_Game()->IsClanGame.Get() ? one : zero)) break;
// if (!Append_InfoKey_Pair(outbuf, maxlen, "Laddered", The_Game()->IsLaddered.Get() ? one : zero)) break;
// if (!Append_InfoKey_Pair(outbuf, maxlen, "QuickMatch", The_Game()->Is_QuickMatch_Server() ? one : zero)) break;
break;
}
#ifdef WWDEBUG
StringClass tstr(true);
tstr.Format("GS_QnR -- Rules callback, sent: %s\n",outbuf);
OutputDebugString(tstr.Peek_Buffer());
#endif
WWDEBUG_SAY(("<--GS_QnR -- Rules callback\n"));
}
BOOL CGameSpyQnR::Parse_HeartBeat_List(const char *list) {
BOOL master_added = false;
char *str = new char[strlen(list)+1];
strcpy(str, list);
char *t = str;
clear_master_list();
while (t) {
WORD port = 27900;
struct sockaddr_in taddr;
memset(&taddr, 0, sizeof(taddr));
taddr.sin_family = AF_INET;
char *q = strchr(t, ',');
if (q) *q++ = 0;
char *s = strchr(t, ':');
if (s) {
// Parse off the port value
*s++ = 0;
char *p = s;
if (atoi(p)) port = atoi(p);
}
// skip white space
while (*t == ' ' || *t == '\t') t++;
// process the address
if (*t && get_sockaddrin(t, port, &taddr, NULL)) {
add_master(&taddr);
master_added = true;
}
t = q;
}
delete [] str;
if (!master_added) {
ConsoleBox.Print("Error processing HeartBeat List: <%s>\n", list);
ConsoleBox.Print("Assigning default HeartBeat List\n");
return false;
}
return true;
}
BOOL CGameSpyQnR::Append_InfoKey_Pair(char *outbuf, int maxlen, const char *key, const char *value) {
WWASSERT(value);
WWASSERT(outbuf);
WWASSERT(key);
int clen = strlen(outbuf);
if (clen + strlen(key) + strlen(value) + 3 > (unsigned int)maxlen) return FALSE;
char *s = new char[strlen(value)+1];
strcpy(s, value);
char *t = s;
while (*t) {
if (*t == '\\') *t = '/';
t++;
}
t = strtrim(s);
sprintf(&outbuf[clen], "\\%s\\%s", key, t);
delete [] s;
return TRUE;
}
BOOL CGameSpyQnR::Append_InfoKey_Pair(char *outbuf, int maxlen, const char *key, const WideStringClass &value) {
static StringClass text;
value.Convert_To(text);
return Append_InfoKey_Pair(outbuf, maxlen, key, text.Peek_Buffer());
}
BOOL CGameSpyQnR::Append_InfoKey_Pair(char *outbuf, int maxlen, const char *key, const StringClass &value) {
return Append_InfoKey_Pair(outbuf, maxlen, key, value.Peek_Buffer());
}
/***************
players_callback
sends the players and their information.
Note that \ characters are not stripped out of player names. If
your game allows players or team names with the \ character, you will need
to strip or change it here.
The following keys are included for each player:
\player_N\
\frags_N\
\deaths_N\
\skill_N\
\ping_N\
\team_N\
***************/
void CGameSpyQnR::players_callback(char *outbuf, int maxlen)
{
// Send the minimum for now to reduce Bandwidth usage.
outbuf[0] = 0;
return;
int pindex = 0;
WWDEBUG_SAY(("-->GS_QnR -- Players callback\n"));
WWASSERT(!CombatManager::Is_Loading_Level());
if (!maxlen || !outbuf) return;
outbuf[0] = 0;
for (SLNode<cPlayer> *player_node = cPlayerManager::Get_Player_Object_List ()->Head ();
player_node != NULL;
player_node = player_node->Next ()) {
cPlayer *player = player_node->Data ();
WWASSERT (player != NULL);
if (player->Get_Is_Active().Is_False()) {
// if (player->Get_Is_Active().Is_False() || !player->Is_Human()) {
continue;
}
StringClass keyval(true);
StringClass value(true);
// Set the Player's Name [Team]
value = player->Get_Name();
if (player->Get_Player_Type() == PLAYERTYPE_NOD) {
value += " [NOD]";
} else if (player->Get_Player_Type() == PLAYERTYPE_GDI) {
value += " [GDI]";
}
keyval.Format("player_%d", pindex);
if (!Append_InfoKey_Pair(outbuf, maxlen, keyval.Peek_Buffer(), value)) break;
// Set the Player's Score
keyval.Format("frags_%d", pindex);
value.Format("%.0f", player->Get_Score());
if (!Append_InfoKey_Pair(outbuf, maxlen, keyval.Peek_Buffer(), value)) break;
// Set the Player's Credits
// keyval.Format("credits_%d", pindex);
// value.Format("%.0f", player->Get_Money());
// if (!Append_InfoKey_Pair(outbuf, maxlen, keyval.Peek_Buffer(), value)) break;
// Set the Player's Ping to Server
keyval.Format("ping_%d", pindex);
value.Format("%d", player->Get_Ping());
if (!Append_InfoKey_Pair(outbuf, maxlen, keyval.Peek_Buffer(), value)) break;
// Set the Player's Kills
// keyval.Format("kills_%d", pindex);
// value.Format("%d", player->Get_Kills());
// if (!Append_InfoKey_Pair(outbuf, maxlen, keyval.Peek_Buffer(), value)) break;
// Set the Player's Deaths
// keyval.Format("deaths_%d", pindex);
// value.Format("%d", player->Get_Deaths());
// if (!Append_InfoKey_Pair(outbuf, maxlen, keyval.Peek_Buffer(), value)) break;
/* SmartGameObj *game_obj = player->Get_GameObj ();
if (game_obj != NULL && game_obj->As_SoldierGameObj () != NULL) {
// Set the Player's Class (ie: Technician,Sakura,Havok)
keyval.Format("class_%d", pindex);
if (!Append_InfoKey_Pair(outbuf, maxlen, keyval.Peek_Buffer(),
WideStringClass(TRANSLATE(game_obj->Get_Translated_Name_ID())) )) break;
SoldierGameObj *soldier = game_obj->As_SoldierGameObj();
VehicleGameObj *vehicle = soldier->Get_Vehicle ();
// If they're in a vehicle set the vehicle name
keyval.Format("vehicle_%d", pindex);
if (vehicle != NULL) {
if (!Append_InfoKey_Pair(outbuf, maxlen, keyval.Peek_Buffer(),
WideStringClass(TRANSLATE(vehicle->Get_Translated_Name_ID())) )) break;
} else {
if (!Append_InfoKey_Pair(outbuf, maxlen, keyval.Peek_Buffer(), "None")) break;
}
} else {
// If there's no gameobj then set vehicle/class to unknown
keyval.Format("class_%d", pindex);
if (!Append_InfoKey_Pair(outbuf, maxlen, keyval.Peek_Buffer(), "Unknown")) break;
keyval.Format("vehicle_%d", pindex);
if (!Append_InfoKey_Pair(outbuf, maxlen, keyval.Peek_Buffer(), "Unknown")) break;
} */
pindex++;
}
#ifdef WWDEBUG
StringClass tstr(true);
tstr.Format("GS_QnR -- Players callback, sent: %s\n",outbuf);
OutputDebugString(tstr.Peek_Buffer());
#endif
WWDEBUG_SAY(("<--GS_QnR -- Players callback\n"));
return;
}
/************
We'll actually start up two completely seperate "game servers"
Each one initializes the Query & Reporting SDK and calls processs on it during
their main loop
************/
/*
int main(int argc, char* argv[])
{
CGameSpyQnR mygame1("Test Game Server 1"), mygame2("Test Game Server 2");
srand( GetTickCount() );
printf("Press any key to quit\n");
while (!_kbhit())
{
mygame1.run();
mygame2.run();
}
return 0;
}
*/

View File

@@ -0,0 +1,75 @@
/*
** 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/>.
*/
#ifndef _GAMESPY_QNR_H_
#define _GAMESPY_QNR_H_
/********
INCLUDES
********/
#include <GameSpy\gqueryreporting.h>
#include <WWLib\WideString.h>
#include "trim.h"
/********
DEFINES
********/
class CGameSpyQnR
{
protected:
char secret_key[9];
BOOL m_GSInit;
BOOL m_GSEnabled;
qr_t query_reporting_rec;
void DoGameStuff(void);
BOOL Append_InfoKey_Pair(char *outbuf, int maxlen, const char *key, const char *value);
BOOL Append_InfoKey_Pair(char *outbuf, int maxlen, const char *key, const StringClass &value);
BOOL Append_InfoKey_Pair(char *outbuf, int maxlen, const char *key, const WideStringClass &value);
static const char *gamename;
static const char *bname;
static const int prodid;
static const int cdkey_id;
static const char *default_heartbeat_list;
int StartTime;
public:
void Init(void);
void LaunchArcade(void);
void TrackUsage(void);
void Shutdown(void);
BOOL Parse_HeartBeat_List(const char *list);
const char *Get_GameSpy_GameName(void) { return gamename; }
const char *Get_Default_HeartBeat_List(void) { return default_heartbeat_list; }
void Enable_Reporting(BOOL enable) { m_GSEnabled = enable; }
BOOL IsEnabled(void) { return m_GSEnabled; }
void Think();
void basic_callback(char *outbuf, int maxlen);
void info_callback(char *outbuf, int maxlen);
void rules_callback(char *outbuf, int maxlen);
void players_callback(char *outbuf, int maxlen);
CGameSpyQnR();
virtual ~CGameSpyQnR();
};
extern CGameSpyQnR GameSpyQnR;
#endif

3690
Code/Commando/NAT.cpp Normal file

File diff suppressed because it is too large Load Diff

BIN
Code/Commando/Renegade.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

View File

@@ -0,0 +1,892 @@
/*
** 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/ServerSettings.cpp $*
* *
* $Author:: Steve_t $*
* *
* $Modtime:: 8/09/02 2:12p $*
* *
* $Revision:: 17 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include "ServerSettings.h"
#include "slavemaster.h"
#include "wwdebug.h"
#include "gamedata.h"
#include "gdcnc.h"
#include "ini.h"
#include "registry.h"
#include "rawfile.h"
#include "consolemode.h"
#include "specialbuilds.h"
#include "_globals.h"
#include "bandwidth.h"
#include "mpsettingsmgr.h"
#include "wwonline\wolserver.h"
#include "useroptions.h"
#include "gamespyadmin.h"
#include "servercontrol.h"
#include "gamesideservercontrol.h"
#include "autostart.h"
#include "GameSpy_QnR.h"
#include "bandwidthcheck.h"
const char *ConfigSettingsName = "Config";
const char *MasterServerSection = "Server";
const char *SlaveServerSection = "Slave";
#define ENCRYPTION_STRING_LENGTH 128
#define KEY_SLAVE_SERIAL "Serial"
char ServerSettingsClass::SettingsFile[MAX_PATH];
bool ServerSettingsClass::IsActive = false;
char ServerSettingsClass::MasterPassword[128];
ServerSettingsClass::GameModeTypeEnum ServerSettingsClass::GameMode = MODE_NONE;
unsigned long ServerSettingsClass::MasterBandwidth = 0;
char ServerSettingsClass::PreferredLoginServer[256];
int ServerSettingsClass::DiskLogSize = -1;
const char *ServerListTag = "Available Westwood Servers:";
const char *ServerListEnd = "; End generated section.";
/***********************************************************************************************
* ServerSettingsClass::Set_Settings_File_Name -- Set the name of the settings file *
* *
* *
* *
* INPUT: File name *
* *
* OUTPUT: Nothing *
* *
* WARNINGS: None *
* *
* HISTORY: *
* 2/1/2002 12:07PM ST : Created *
*=============================================================================================*/
void ServerSettingsClass::Set_Settings_File_Name(char *filename)
{
if (strlen(filename) < sizeof(SettingsFile)) {
strcpy(SettingsFile, filename);
IsActive = true;
}
}
/***********************************************************************************************
* ServerSettingsClass::Parse -- Pull the server info out of the settings file *
* *
* *
* *
* INPUT: True if we should apply the settings. False to parse for errors only. *
* *
* OUTPUT: Nothing *
* *
* WARNINGS: None *
* *
* HISTORY: *
* 2/1/2002 12:07PM ST : Created *
*=============================================================================================*/
bool ServerSettingsClass::Parse(bool apply)
{
char master_settings[MAX_PATH];
char slave_settings[MAX_PATH];
char slave_section[256];
char slave_nick[128];
char slave_serial[128];
char slave_pass[128];
int slave_port;
int slave_bw;
char master_nick[128];
char master_serial[128];
int master_port;
int master_bw;
char master_pass[128];
char remote_admin_pass[128];
char game_type[32];
char heartbeat_list[512];
bool wol = true;
char remote_admin_ip[128];
MasterPassword[0] = 0;
/*
** IsActive is set when the settigns file name is set.
*/
if (IsActive) {
WWASSERT(The_Game() || !apply);
if (apply) {
WWDEBUG_SAY(("Applying server settings\n"));
ConsoleBox.Print("Applying server settings\n");
}
/*
** Make sure the server config file is there. It should be since it's verified at command line parsing time.
*/
RawFileClass file(SettingsFile);
if (!file.Is_Available()) {
WWDEBUG_SAY(("Server startup file '%s' not found\n", SettingsFile));
ConsoleBox.Print("Error - server startup file '%s' not found - aborting\n", SettingsFile);
ConsoleBox.Wait_For_Keypress();
return(false);
}
/*
** Get the name of the master server settings file.
*/
INIClass ini(file);
ini.Get_String(MasterServerSection, ConfigSettingsName, "", master_settings, sizeof(master_settings));
if (strlen(master_settings) == 0) {
if (apply) {
WWDEBUG_SAY(("No master server settings specified - using defaults\n"));
ConsoleBox.Print("No master server settings specified - using defaults\n");
}
}
/*
** Load the master server settings from the ini file.
*/
/*
** Game Type.
*/
ini.Get_String(MasterServerSection, "GameType", "WOL", game_type, sizeof(game_type));
if (cGameSpyAdmin::Get_Is_Server_Gamespy_Listed()) {
strcpy(game_type, "GameSpy");
}
if (stricmp(game_type, "WOL") == 0) {
GameMode = MODE_WOL;
} else if (stricmp(game_type, "LAN") == 0) {
wol = false;
GameMode = MODE_LAN;
} else if (stricmp(game_type, "GameSpy") == 0) {
wol = false;
cGameSpyAdmin::Set_Is_Server_Gamespy_Listed(true);
GameSpyQnR.Enable_Reporting(true);
GameMode = MODE_GAMESPY;
} else {
WWDEBUG_SAY(("Bad game type specified in server.ini\n"));
ConsoleBox.Print("Error - Unknown game type in server settings. Use 'LAN', 'WOL', or 'GameSpy' - aborting\n");
ConsoleBox.Wait_For_Keypress();;
return(false);
}
/*
** Parse the list of GameSpy Style Master servers from the HeartBeat List
*/
heartbeat_list[sizeof(heartbeat_list)-1] = 0;
ini.Get_String(MasterServerSection, "HeartBeatServers", GameSpyQnR.Get_Default_HeartBeat_List(), heartbeat_list, sizeof(heartbeat_list)-1);
if (!GameSpyQnR.Parse_HeartBeat_List(heartbeat_list)) {
GameSpyQnR.Parse_HeartBeat_List(GameSpyQnR.Get_Default_HeartBeat_List());
}
/*
** Make sure the master server settings file is there.
*/
char filename[MAX_PATH];
sprintf(filename, "data\\%s", master_settings);
file.Set_Name(filename);
if (!file.Is_Available()) {
WWDEBUG_SAY(("Server settings file '%s' not found\n", filename));
ConsoleBox.Print("Error - server settings file '%s' not found - aborting\n", filename);
ConsoleBox.Wait_For_Keypress();;
return(false);
} else {
if (!Check_Game_Settings_File(master_settings)) {
WWDEBUG_SAY(("Server settings file '%s' not usable\n", master_settings));
ConsoleBox.Print("Error - server settings file '%s' contains errors - aborting\n", master_settings);
ConsoleBox.Wait_For_Keypress();;
return(false);
}
if (apply && The_Game()) {
The_Game()->Set_Ini_Filename(master_settings);
}
}
/*
** Restart Flag
*/
RegistryClass restart_reg(APPLICATION_SUB_KEY_NAME_WOLSETTINGS);
if (restart_reg.Is_Valid ()) {
restart_reg.Set_Int(AutoRestartClass::REG_VALUE_AUTO_RESTART_FLAG, 1);
switch (GameMode) {
case MODE_WOL:
restart_reg.Set_Int(AutoRestartClass::REG_VALUE_AUTO_RESTART_TYPE, 1);
break;
case MODE_LAN:
case MODE_GAMESPY:
restart_reg.Set_Int(AutoRestartClass::REG_VALUE_AUTO_RESTART_TYPE, 0);
break;
}
}
/*
** Nickname.
*/
ini.Get_String(MasterServerSection, "Nickname", "", master_nick, sizeof(master_nick));
#ifdef FREEDEDICATEDSERVER
/*
** We only need to validate this for the FDS. The regular game can allow the login name to be specified in the registry.
*/
if (wol && strlen(master_nick) == 0) {
WWDEBUG_SAY(("Error - No login nickname specified for master server - aborting\n"));
ConsoleBox.Print("Error - No login nickname specified for master server - aborting\n");
ConsoleBox.Wait_For_Keypress();;
return(false);
}
#endif //FREEDEDICATEDSERVER
/*
** Password.
*/
ini.Get_String(MasterServerSection, "Password", "", master_pass, sizeof(master_pass));
#ifdef FREEDEDICATEDSERVER
/*
** We only need to validate this for the FDS. The regular game can allow the login name to be specified in the registry.
*/
if (wol && strlen(master_pass) == 0) {
WWDEBUG_SAY(("Error - No login password specified for master server - aborting\n"));
ConsoleBox.Print("Error - No login password specified for master server - aborting\n");
ConsoleBox.Wait_For_Keypress();;
return(false);
}
#endif //FREEDEDICATEDSERVER
/*
** Serial number.
*/
ini.Get_String(MasterServerSection, "Serial", "", master_serial, sizeof(master_serial));
#ifdef FREEDEDICATEDSERVER
/*
** We only need to validate the serial number if we are the FDS. For the regular game, the master serial will be stored
** in the registry.
*/
if (wol && strlen(master_serial) == 0) {
WWDEBUG_SAY(("Error - No serial number specified for master server - aborting\n"));
ConsoleBox.Print("Error - No serial number specified for master server - aborting\n");
ConsoleBox.Wait_For_Keypress();;
return(false);
}
#endif //FREEDEDICATEDSERVER
/*
** Get the port number.
*/
master_port = ini.Get_Int(MasterServerSection, "Port", 0xffffffff);
if (wol && master_port != 0xffffffff && (master_port < 0 || master_port > 0xffff)) {
WWDEBUG_SAY(("Error - Invalid port number %d specified for master server - aborting\n", master_port));
ConsoleBox.Print("Error - Invalid port number %d specified for master server - aborting\n", master_port);
ConsoleBox.Wait_For_Keypress();
return(false);
}
/*
** Get the GameSpy Query port number.
*/
int gsqport = cUserOptions::GameSpyQueryPort.Get();
gsqport = ini.Get_Int(MasterServerSection, "GameSpyQueryPort", gsqport);
if (!gsqport) gsqport = cUserOptions::GameSpyQueryPort.Get();
if (gsqport < 0 || gsqport > 0xffff) {
WWDEBUG_SAY(("Error - Invalid port number %d specified for GameSpy Query Port - aborting\n", gsqport));
ConsoleBox.Print("Error - Invalid port number %d specified for GameSpy Query Port - aborting\n", gsqport);
ConsoleBox.Wait_For_Keypress();;
return(false);
}
cUserOptions::GameSpyQueryPort.Set(gsqport);
/*
** Get the GameSpy Game port number.
*/
int gsgport = cUserOptions::GameSpyGamePort.Get();
gsgport = ini.Get_Int(MasterServerSection, "GameSpyGamePort", gsgport);
if (!gsgport) gsgport = cUserOptions::GameSpyGamePort.Get();
if (gsgport < 0 || gsgport > 0xffff || gsgport == gsqport) {
WWDEBUG_SAY(("Error - Invalid port number %d specified for GameSpy Game Port - aborting\n", gsgport));
ConsoleBox.Print("Error - Invalid port number %d specified for GameSpy Game Port - aborting\n", gsgport);
ConsoleBox.Wait_For_Keypress();;
return(false);
}
cUserOptions::GameSpyGamePort.Set(gsgport);
/*
** Get the bandwidth allowance.
*/
master_bw = ini.Get_Int(MasterServerSection, "BandwidthUp", 0xffffffff);
if (master_bw != 0 && master_bw != 0xffffffff && master_bw < 33600) {
WWDEBUG_SAY(("Error - Insufficient bandwidth specified for master server - aborting\n"));
ConsoleBox.Print("Error - Insufficient bandwidth specified for master server - aborting\n");
ConsoleBox.Wait_For_Keypress();;
return(false);
}
MasterBandwidth = master_bw;
/*
** Get the max size of the disk log in days.
*/
DiskLogSize = ini.Get_Int(MasterServerSection, "DiskLogSize", 7);
if (DiskLogSize > 365) {
WWDEBUG_SAY(("Error - Disk log size too large - aborting\n"));
ConsoleBox.Print("Error - Disk log size too large - aborting\n");
ConsoleBox.Wait_For_Keypress();;
return(false);
}
/*
** Get the preferred login server. No preference means use default from ping profile.
*/
ini.Get_String(MasterServerSection, "LoginServer", "", PreferredLoginServer, sizeof(PreferredLoginServer));
/*
** Get the Network Update Rate override.
*/
int nur = ini.Get_Int(MasterServerSection, "NetUpdateRate", 8);
if (nur < 5 || nur > 30) {
WWDEBUG_SAY(("Error - Bad NetUpdateRate specified - aborting\n"));
ConsoleBox.Print("Error - NetUpdateRate must be between 5 and 30 - aborting\n");
ConsoleBox.Wait_For_Keypress();;
return(false);
}
cUserOptions::NetUpdateRate.Set(nur);
/*
** Get the remote admin settings.
*/
bool allow_remote = ini.Get_Bool(MasterServerSection, "AllowRemoteAdmin", false);
RegistryClass reg_remote(APPLICATION_SUB_KEY_NAME_NET_SERVER_CONTROL);
if (allow_remote) {
ini.Get_String(MasterServerSection, "RemoteAdminPassword", "", remote_admin_pass, sizeof(remote_admin_pass));
int len = strlen(remote_admin_pass);
if (len == 0) {
ConsoleBox.Print("Error - Remote admin password must be specified - aborting\n");
ConsoleBox.Wait_For_Keypress();;
return(false);
} else {
if (len > 31) {
ConsoleBox.Print("Error - Remote admin password too long - aborting\n");
ConsoleBox.Wait_For_Keypress();;
return(false);
}
}
int admin_port = ini.Get_Int(MasterServerSection, "RemoteAdminPort", 0);
if (admin_port != 0 && (admin_port < 1024 || admin_port > 65535-8)) {
ConsoleBox.Print("Error - Remote admin port number out of range - aborting\n");
ConsoleBox.Wait_For_Keypress();;
return(false);
}
ServerControl.Allow_Remote_Admin(true);
/*
** Set the port number into the registry.
*/
if (admin_port == 0) {
admin_port = DEFAULT_SERVER_CONTROL_PORT;
}
reg_remote.Set_Int(SERVER_CONTROL_PORT_KEY, admin_port);
/*
** Set the password into the registry.
*/
reg_remote.Set_String(SERVER_CONTROL_PASSWORD_KEY, remote_admin_pass);
/*
** We need to bind to more than just the loopback address when listening for control messages.
*/
reg_remote.Set_Int(SERVER_CONTROL_LOOPBACK_KEY, 0);
/*
** There may be an IP override specified.
*/
ini.Get_String(MasterServerSection, "RemoteAdminIP", "0.0.0.0", remote_admin_ip, sizeof(remote_admin_ip));
unsigned long admin_ip_long = ntohl(inet_addr(remote_admin_ip));
reg_remote.Set_Int(SERVER_CONTROL_IP_KEY, admin_ip_long);
} else {
/*
** Only listen to control messages on the loopback address.
*/
reg_remote.Set_Int(SERVER_CONTROL_LOOPBACK_KEY, 1);
ServerControl.Allow_Remote_Admin(false);
}
/*
** Set the master settings into the registry.
*/
//if (apply) {
/*
** Serial number.
*/
if (wol) {
if (strlen(master_serial)) {
StringClass serial(master_serial, true);
StringClass encrypted_serial;
Encrypt_Serial(serial, encrypted_serial);
RegistryClass reg_base(APPLICATION_SUB_KEY_NAME);
if (reg_base.Is_Valid()) {
reg_base.Set_String(KEY_SLAVE_SERIAL, encrypted_serial.Peek_Buffer());
}
}
/*
** Nickname.
*/
if (strlen(master_nick)) {
RegistryClass reg_wol(APPLICATION_SUB_KEY_NAME_WOLSETTINGS);
if (reg_wol.Is_Valid()) {
reg_wol.Set_String("AutoLogin", master_nick);
reg_wol.Set_String("LastLogin", master_nick);
reg_wol.Set_Int("AutoLoginPrompt", 0);
MPSettingsMgrClass::Set_Auto_Login(master_nick);
}
}
/*
** Password.
*/
MPSettingsMgrClass::Set_Auto_Password(master_pass);
/*
** Port number.
*/
if (master_port != 0xffffffff) {
RegistryClass reg_fw(APPLICATION_SUB_KEY_NAME_NET_FIREWALL);
reg_fw.Set_Int("ForcePort", master_port);
}
}
/*
** Bandwidth.
*/
if (master_bw != 0xffffffff) {
RegistryClass reg_netopt(APPLICATION_SUB_KEY_NAME_NETOPTIONS);
if (reg_netopt.Is_Valid()) {
if (cGameSpyAdmin::Is_Gamespy_Game()) {
if (master_bw == 0) master_bw = 1000000;
cUserOptions::Set_Bandwidth_Bps(master_bw);
} else {
if (wol) {
reg_netopt.Set_Int("BandwidthType", BANDWIDTH_AUTO);
/*
** We want this to be set always on the first time through, but not neccessarily on the second, apply, pass.
*/
if (master_bw != 0 || !apply) {
RegistryClass reg_bw(APPLICATION_SUB_KEY_NAME_BANDTEST);
if (reg_bw.Is_Valid()) {
reg_bw.Set_Int("Up", master_bw);
reg_bw.Set_Int("Down", master_bw);
}
}
} else {
cUserOptions::Set_Bandwidth_Type(BANDWIDTH_LANT1);
}
}
}
}
//}
if (apply) {
SlaveMaster.Reset();
}
/*
** Read the slave server info.
*/
for (int i=0 ; i<MAX_SLAVES ; i++) {
slave_settings[0] = 0;
slave_nick[0] = 0;
slave_serial[0] = 0;
slave_port = 0;
slave_bw = 0xffffffff;
/*
** See if this slave is enabled in the .ini
*/
sprintf(slave_section, "%s%d", SlaveServerSection, i+1);
bool enabled = ini.Get_Bool(slave_section, "Enable", false);
if (enabled) {
/*
** Make sure the slaves config file is present.
*/
ini.Get_String(slave_section, ConfigSettingsName, "", slave_settings, sizeof(slave_settings));
if (strlen(slave_settings) != 0) {
sprintf(filename, "data\\%s", slave_settings);
file.Set_Name(filename);
if (!file.Is_Available()) {
WWDEBUG_SAY(("Slave server settings file '%s' not found\n", filename));
ConsoleBox.Print("Error - Slave server settings file '%s' not found - aborting\n", filename);
ConsoleBox.Wait_For_Keypress();;
return(false);
} else {
if (!Check_Game_Settings_File(slave_settings)) {
WWDEBUG_SAY(("Server settings file '%s' not usable\n", slave_settings));
ConsoleBox.Print("Error - server settings file '%s' contains errors - aborting\n", slave_settings);
ConsoleBox.Wait_For_Keypress();;
return(false);
}
}
}
/*
** Make sure there's a nickname and a serial.
*/
ini.Get_String(slave_section, "Nickname", "", slave_nick, sizeof(slave_nick));
if (wol && strlen(slave_nick) == 0) {
WWDEBUG_SAY(("Error - No login nickname specified for slave %d - aborting\n", i+1));
ConsoleBox.Print("Error - No login nickname specified for slave %d - aborting\n", i+1);
ConsoleBox.Wait_For_Keypress();;
return(false);
}
ini.Get_String(slave_section, "Serial", "", slave_serial, sizeof(slave_serial));
if (wol && strlen(slave_serial) == 0) {
WWDEBUG_SAY(("Error - No serial number specified for slave %d - aborting\n", i+1));
ConsoleBox.Print("Error - No serial number specified for slave %d - aborting\n", i+1);
ConsoleBox.Wait_For_Keypress();;
return(false);
}
/*
** Get the password.
*/
ini.Get_String(slave_section, "Password", "", slave_pass, sizeof(slave_pass));
#ifdef FREEDEDICATEDSERVER
if (wol && strlen(slave_pass) == 0) {
WWDEBUG_SAY(("Error - No login password specified for slave %d - aborting\n", i+1));
ConsoleBox.Print("Error - No login password specified for slave %d - aborting\n", i+1);
ConsoleBox.Wait_For_Keypress();;
return(false);
}
#endif //FREEDEDICATEDSERVER
/*
** Get the port number.
*/
slave_port = ini.Get_Int(slave_section, "Port", 0);
if (slave_port < 0 || slave_port > 0xffff) {
WWDEBUG_SAY(("Error - Invalid port number %d specified for slave %d - aborting\n", slave_port, i+1));
ConsoleBox.Print("Error - Invalid port number %d specified for slave %d - aborting\n", slave_port, i+1);
ConsoleBox.Wait_For_Keypress();;
return(false);
}
/*
** Get the bandwidth allowance.
*/
slave_bw = ini.Get_Int(slave_section, "BandwidthUp", 0xffffffff);
if (slave_bw != 0 && slave_bw != 0xffffffff && slave_bw < 33600) {
WWDEBUG_SAY(("Error - Insufficient bandwidth specified for slave %d - aborting\n", i+1));
ConsoleBox.Print("Error - Insufficient bandwidth specified for slave %d - aborting\n", i+1);
ConsoleBox.Wait_For_Keypress();;
return(false);
}
}
/*
** Apply the settings.
*/
if (apply) {
SlaveMaster.Add_Slave(enabled, slave_nick, slave_serial, (unsigned short)slave_port, slave_settings, slave_bw, slave_pass);
}
}
if (apply) {
SlaveMaster.Save();
}
}
return(true);
}
/***********************************************************************************************
* ServerSettingsClass::Encrypt_Serial -- Serial number encryption/decryption *
* *
* *
* *
* INPUT: Input serial number *
* Reference to output serial number *
* Encrypt flag - true to encrypt, false to decrypt *
* *
* OUTPUT: Nothing *
* *
* WARNINGS: None *
* *
* HISTORY: *
* 2/1/2002 12:08PM ST : Created *
*=============================================================================================*/
void ServerSettingsClass::Encrypt_Serial(StringClass serial_in, StringClass &serial_out, bool encrypt)
{
char *s;
int numberlength = serial_in.Get_Length();
unsigned long bytesread;
char stringbuffer[ENCRYPTION_STRING_LENGTH];
int p;
WWASSERT(numberlength);
s = new char [numberlength + 1];
memcpy(s, serial_in.Peek_Buffer(), numberlength + 1);
/*
** See if the key file is available. If not, don't bother encrypting.
*/
HANDLE handle = CreateFile ("woldata.key", GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
if (handle == INVALID_HANDLE_VALUE) {
delete [] s;
serial_out = serial_in;
return;
}
/*
** Read the key.
*/
if (!ReadFile(handle, stringbuffer, sizeof (stringbuffer), &bytesread, NULL)) {
WWDEBUG_SAY(("Unable to read serial encryption key file\n"));
delete [] s;
serial_out = serial_in;
return;
}
int sign = encrypt ? 1 : -1;
p = 0;
for (unsigned i = 0; i < ENCRYPTION_STRING_LENGTH; i++) {
int t;
char c;
t = s[p] - '0';
t %= 10;
t += (sign * stringbuffer[i]);
t += 1000;
t %= 10;
c = t + '0';
s[p] = c;
p++;
if (p == numberlength) {
p = 0;
}
}
serial_out = StringClass(s, true);
delete [] s;
}
/***********************************************************************************************
* ServerSettingsClass::Decrypt_Serial -- Serial number decryption *
* *
* *
* *
* INPUT: Input serial number *
* Reference to output serial number *
* *
* OUTPUT: Nothing *
* *
* WARNINGS: None *
* *
* HISTORY: *
* 2/1/2002 12:08PM ST : Created *
*=============================================================================================*/
void ServerSettingsClass::Decrypt_Serial(StringClass serial_in, StringClass &serial_out)
{
Encrypt_Serial(serial_in, serial_out, false);
}
/***********************************************************************************************
* ServerSettingsClass::Get_Preferred_Server -- Get the users specified server *
* *
* *
* *
* INPUT: Server list from servserv *
* *
* OUTPUT: Name of preferred server *
* *
* WARNINGS: None *
* *
* HISTORY: *
* 2/1/2002 1:18PM ST : Created *
*=============================================================================================*/
char *ServerSettingsClass::Get_Preferred_Server(const WWOnline::IRCServerList &server_list)
{
if (IsActive && server_list.size()) {
Write_Server_List(server_list);
}
return(PreferredLoginServer);
}
/***********************************************************************************************
* ServerSettingsClass::Write_Server_List -- Write the server list into the settings ini file *
* *
* *
* *
* INPUT: Server list *
* *
* OUTPUT: Nothing *
* *
* WARNINGS: None *
* *
* HISTORY: *
* 2/1/2002 1:19PM ST : Created *
*=============================================================================================*/
void ServerSettingsClass::Write_Server_List(const WWOnline::IRCServerList &server_list)
{
WWASSERT(server_list.size());
WWASSERT(strlen(SettingsFile) != 0);
char temp[256];
if (server_list.size()) {
RawFileClass file(SettingsFile);
/*
** This is a bit hacky. Basically we just want the .ini file commented with the latest server list.
**
** We will do this by reading in the file, looking for a tag that tells us where to write the server list, then writing
** the file back out with the server list in place.
*/
if (file.Is_Available()) {
unsigned long size = file.Size();
if (size) {
/*
** Read the file.
*/
char *file_buffer = new char[size + 8192];
#ifdef WWDEBUG
unsigned long read_size =
#endif //WWDEBUG
file.Read(file_buffer, size);
WWASSERT(read_size == size);
file.Close();
/*
** Find the placeholder tag.
*/
char *tag = strstr(file_buffer, ServerListTag);
char *end_tag = strstr(file_buffer, ServerListEnd);
if (tag && end_tag) {
/*
** Write out the first portion of the file unchanged.
*/
file.Open(FileClass::WRITE);
file.Write(file_buffer, (tag - file_buffer) + strlen(ServerListTag));
/*
** Insert the server list.
*/
char *server_list_text = new char [8192];
strcpy(server_list_text, "\r\n;\r\n");
for (unsigned int i = 0; i < server_list.size(); i++) {
const RefPtr<WWOnline::IRCServerData> &server = server_list[i];
if (server->HasLanguageCode()) {
const char *server_name = server->GetName();
sprintf(temp, "; %s\r\n", server_name);
strcat(server_list_text, temp);
}
}
strcat(server_list_text, ";\r\n");
file.Write(server_list_text, strlen(server_list_text));
/*
** Write out the post server list sections of the original file.
*/
file.Write(end_tag, (file_buffer + size) - end_tag);
file.Close();
}
}
}
}
}
/***********************************************************************************************
* ServerSettingsClass::Check_Game_Settings_File -- Check game settings for validity *
* *
* *
* *
* INPUT: Game settings .ini file name *
* *
* OUTPUT: True if valid. *
* *
* WARNINGS: None *
* *
* HISTORY: *
* 2/3/2002 9:37PM ST : Created *
*=============================================================================================*/
bool ServerSettingsClass::Check_Game_Settings_File(char *config_file)
{
cGameDataCnc *game_settings = (cGameDataCnc*) cGameData::Create_Game_Of_Type(cGameData::GAME_TYPE_CNC);
WWASSERT(game_settings != NULL);
if (game_settings) {
game_settings->Set_Ini_Filename(config_file);
game_settings->Load_From_Server_Config();
WideStringClass outMsg;
bool ok = game_settings->Is_Valid_Settings(outMsg, true);
delete game_settings;
return(ok);
}
return(false);
}

View File

@@ -0,0 +1,88 @@
/*
** 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/ServerSettings.h $*
* *
* $Author:: Steve_t $*
* *
* $Modtime:: 8/08/02 1:00p $*
* *
* $Revision:: 7 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include <win.h>
#include "wwonline\wolsession.h"
class StringClass;
class ServerSettingsClass
{
public:
enum GameModeTypeEnum {
MODE_NONE = 0,
MODE_LAN,
MODE_WOL,
MODE_GAMESPY
};
static void Set_Settings_File_Name(char *filename);
static bool Is_Server_Settings_File_Set(void) {return((SettingsFile[0] == 0) ? false : true);}
static bool Parse(bool apply = false);
static bool Is_Command_Line_Mode(void) {return(IsActive);}
static void Encrypt_Serial(StringClass serial_in, StringClass &serial_out, bool encrypt = true);
static void Decrypt_Serial(StringClass serial_in, StringClass &serial_out);
static const char *Get_Master_Server_Password(void) {return(MasterPassword);}
static unsigned long Get_Master_Bandwidth(void) {return(MasterBandwidth);}
static bool Is_Active(void) {return(IsActive);}
static char *Get_Settings_File_Name(void) {return(SettingsFile);}
static bool Check_Game_Settings_File(char *config_file);
static GameModeTypeEnum Get_Game_Mode(void) {return(GameMode);}
static int Get_Disk_Log_Size(void) {return(DiskLogSize);}
/*
** Populating ini file with server list.
*/
static char *Get_Preferred_Server(const WWOnline::IRCServerList &server_list);
static void Write_Server_List(const WWOnline::IRCServerList &server_listvoid);
private:
static char SettingsFile[MAX_PATH];
static bool IsActive;
static char MasterPassword[128];
static unsigned long MasterBandwidth;
static char PreferredLoginServer[256];
static GameModeTypeEnum GameMode;
static int DiskLogSize;
};

808
Code/Commando/WINMAIN.CPP Normal file
View File

@@ -0,0 +1,808 @@
/*
** 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/WINMAIN.CPP $*
* *
* $Author:: Steve_t $*
* *
* $Modtime:: 2/17/02 11:08a $*
* *
* $Revision:: 85 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* WinMain -- Win32 Program Entry Point! *
* WIN_resize -- Surrender-required function which resizes the main window *
* WIN_set_fullscreen -- Surrender-required function for toggling full-screen mode *
* Main_Window_Proc -- Windows Proc for the main game window *
* Create_Main_Window -- Creates the main game window *
* On_Focus_Loss -- this function is called when the application loses focus *
* On_Focus_Restore -- This function is called when the application gets focus *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include "winmain.h"
#define _WIN32_WINDOWS 0x0401
#include "win.h"
#include "resource.h"
#include "WW3D.H"
#include "miscutil.h"
#include "input.h"
#include "useroptions.h"
#include "WWAudio.H"
#include "FFactory.H"
#include "debug.h"
#include "verchk.h"
#include "devoptions.h"
#include "dialogmgr.h"
#include "renegadedialogmgr.h"
#include "except.h"
#include "DirectInput.h"
#include "WebBrowser.h"
#include "wwmemlog.h"
#include "datasafe.h"
#include "combatgmode.h"
#include "registry.h"
#include "init.h"
#include "_globals.h"
#include "buildnum.h"
#include "dx8wrapper.h"
#include "formconv.h"
#include "autostart.h"
#include "consolemode.h"
#include "specialbuilds.h"
#include "slavemaster.h"
#include "serversettings.h"
#ifdef _DEBUG
#include <crtdbg.h>
#endif //_DEBUG
#if (_MSC_VER >= 1200)
#pragma warning(push,1)
#endif
#include <iostream>
#include "singletoninstancekeeper.h"
#include "packetmgr.h"
#if (_MSC_VER >= 1200)
#pragma warning(pop)
#endif
//----------------------------------------------------------------------------
// Globals
//----------------------------------------------------------------------------
extern "C"
{
HWND hWndMain;
bool WIN_fullscreen = true;
}
//----------------------------------------------------------------------------
// Local functions
//----------------------------------------------------------------------------
static BOOL Create_Main_Window(HANDLE hInstance, int nCmdShow);
long FAR PASCAL Main_Window_Proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
void On_Focus_Loss(void);
void On_Focus_Restore(void);
void Split_Command_Line_Args(HINSTANCE instance, char *path_to_exe, char *command_line);
void Set_Working_Directory(char *old_path, char *new_path);
int Start_Application( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow );
void Set_Working_Directory(HINSTANCE hInstance);
#include "packet.h"
#ifndef _MSC_VER
long Top_Level_Exception_Filter(EXCEPTION_POINTERS *e_info)
{
return(Exception_Handler(e_info->ExceptionRecord->ExceptionCode, e_info));
}
#endif //_MSC_VER
/***********************************************************************************************
* WinMain -- Win32 Program Entry Point! *
* *
* INPUT: *
* *
* Standard WinMain inputs :-) *
* *
* OUTPUT: *
* *
* Standard WinMain output *
* *
* WARNINGS: *
* *
* HISTORY: *
* 07/18/1997 GH : Created. *
*=============================================================================================*/
int PASCAL WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow )
{
WWMemoryLogClass::Init(); // This switches memlog from static to dynamic allocations mode
#ifdef _DEBUG
/*
** Setup to track memory heap integrity and check for
** memory leaks. Output is dumped to the debug string console.
*/
if (cDevOptions::CrtDbgEnabled.Is_True()) {
_CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_DEBUG);
_CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_DEBUG);
_CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_DEBUG);
_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
}
/*
** Leak test
*/
//char *flibble = new char [1024];
//unsigned long *flibble2 = new unsigned long;
//void *flibble3 = malloc(128);
//flibble = flibble;
//flibble2 = flibble2;
//flibble3 = flibble3;
#endif //_DEBUG
#ifdef WWDEBUG
//
// If necessary, disable packet optimizations
//
if (cDevOptions::PacketOptimizationsEnabled.Is_False()) {
PacketManager.Disable_Optimizations();
}
#endif //WWDEBUG
#ifdef _DEBUG // Denzil - DO NOT COMPILE INTO FINAL BUILD
bool webInstalled = WebBrowser::InstallPrerequisites();
if (!webInstalled) {
::MessageBox(NULL, "Embedded browser prerequisites missing\n\nBrowser functionality questionable.\n\n(Please call Denzil @ 27272)",
"Renegade Warning!", MB_ICONWARNING|MB_OK);
}
#endif // WWDEBUG
if (!cUserOptions::Parse_Command_Line(lpCmdLine)) {
return(0);
}
//
// There's a couple of options we need for the FDS
//
#ifdef FREEDEDICATEDSERVER
if (!SlaveMaster.Am_I_Slave() && !ServerSettingsClass::Is_Server_Settings_File_Set()) {
cUserOptions::Set_Server_INI_File("STARTSERVER=server.ini");
}
ConsoleBox.Set_Exclusive(true);
#endif //FREEDEDICATEDSERVER
//
// Verify that we can execute (i.e. make sure there are no other instances running)
//
SingletonInstanceKeeperClass instance_keeper;
if (instance_keeper.Verify_Safe_To_Execute () == false) {
return 0;
}
//
// Start the game!
//
int retval = Start_Application( hInstance, hPrevInstance, lpCmdLine, nCmdShow );
return retval;
}
static bool Graphics_Settings_Trouble_Shooting()
{
RegistryClass registry( APPLICATION_SUB_KEY_NAME_DEBUG );
if (!registry.Is_Valid()) return true;
int progress=registry.Get_Int( VALUE_NAME_GAME_INITIALIZATION_IN_PROGRESS, 0 );
if (progress) {
StringClass options="wwconfig.exe ";
char* opts=options.Peek_Buffer();
STARTUPINFO startup_info;
ZeroMemory(&startup_info,sizeof(STARTUPINFO));
startup_info.cb=sizeof(STARTUPINFO);
PROCESS_INFORMATION process_info;
CreateProcess(
NULL,
opts,
NULL,
NULL,
FALSE,
0,
NULL,
NULL,
&startup_info,
&process_info);
unsigned long exit_code=STILL_ACTIVE;
unsigned res=0;
do {
res=GetExitCodeProcess(process_info.hProcess,&exit_code);
if (!res) {
return true;
}
Sleep(100);
}
while (exit_code==STILL_ACTIVE);
return !exit_code;
}
return true;
}
typedef IDirect3D8* (WINAPI *Direct3DCreate8Type) (UINT SDKVersion);
static Direct3DCreate8Type Direct3DCreate8Ptr = NULL;
static HINSTANCE D3D8Lib = NULL;
static bool Video_Card_Driver_Check()
{
RegistryClass render_registry(APPLICATION_SUB_KEY_NAME_RENDER);
if (!render_registry.Is_Valid()) return true;
int disabled=render_registry.Get_Int( "DriverVersionCheckDisabled" );
if (disabled>=87) return true;
IDirect3D8* d3d=NULL;
D3DCAPS8 tmp_caps;
const D3DCAPS8* d3dcaps=NULL;
D3DADAPTER_IDENTIFIER8 adapter_id;
// Init D3D
Init_D3D_To_WW3_Conversion();
D3D8Lib = LoadLibrary("D3D8.DLL");
if (D3D8Lib != NULL) {
Direct3DCreate8Ptr = (Direct3DCreate8Type) GetProcAddress(D3D8Lib, "Direct3DCreate8");
if (Direct3DCreate8Ptr) {
d3d=Direct3DCreate8Ptr(D3D_SDK_VERSION); // TODO: handle failure cases...
if (!d3d) {
FreeLibrary(D3D8Lib);
return true;
}
} else {
FreeLibrary(D3D8Lib);
return(true);
}
} else {
return(true);
}
// Select device. If there is already a device selected in the registry, use it.
int current_adapter_index=D3DADAPTER_DEFAULT;
//
// Load the render device settings from the registry
//
char device_name[256] = { 0 };
render_registry.Get_String( VALUE_NAME_RENDER_DEVICE_NAME, device_name, sizeof(device_name));
int adapter_count = d3d->GetAdapterCount();
for (int adapter_index=0; adapter_index<adapter_count; adapter_index++) {
D3DADAPTER_IDENTIFIER8 id;
::ZeroMemory(&id, sizeof(D3DADAPTER_IDENTIFIER8));
HRESULT res = d3d->GetAdapterIdentifier(adapter_index,D3DENUM_NO_WHQL_LEVEL,&id);
// If device ok, check if it matches the currently set adapter name
if (res == D3D_OK) {
StringClass name(id.Description,true);
if (name==device_name) {
current_adapter_index=adapter_index;
break;
}
}
}
if (FAILED(d3d->GetDeviceCaps(
current_adapter_index,
D3DDEVTYPE_HAL,
&tmp_caps))) {
d3d->Release();
FreeLibrary(D3D8Lib);
return true;
}
::ZeroMemory(&adapter_id, sizeof(D3DADAPTER_IDENTIFIER8));
if (FAILED( d3d->GetAdapterIdentifier(
current_adapter_index,
D3DENUM_NO_WHQL_LEVEL,
&adapter_id))) {
d3d->Release();
FreeLibrary(D3D8Lib);
return true;
}
d3dcaps=&tmp_caps;
DX8Caps caps(d3d,*d3dcaps,WW3D_FORMAT_UNKNOWN,adapter_id);
DX8Caps::DriverVersionStatusType status=caps.Get_Driver_Version_Status();
d3d->Release();
FreeLibrary(D3D8Lib);
switch (status) {
default:
case DX8Caps::DRIVER_STATUS_GOOD:
case DX8Caps::DRIVER_STATUS_OK:
case DX8Caps::DRIVER_STATUS_UNKNOWN:
render_registry.Set_Int( "DriverVersionCheckDisabled",87 );
return true;
break;
case DX8Caps::DRIVER_STATUS_BAD:
break;
}
StringClass options="wwconfig.exe -driverversion";
char* opts=options.Peek_Buffer();
STARTUPINFO startup_info;
ZeroMemory(&startup_info,sizeof(STARTUPINFO));
startup_info.cb=sizeof(STARTUPINFO);
PROCESS_INFORMATION process_info;
if (!CreateProcess(
NULL,
opts,
NULL,
NULL,
FALSE,
0,
NULL,
NULL,
&startup_info,
&process_info)) {
return true;
}
unsigned long exit_code=STILL_ACTIVE;
unsigned res=0;
do {
res=GetExitCodeProcess(process_info.hProcess,&exit_code);
if (!res) {
return true;
}
Sleep(100);
}
while (exit_code==STILL_ACTIVE);
return !exit_code;
}
/***********************************************************************************************
* Start_Application -- Handles WinMain execution. *
* *
* INPUT: *
* *
* Standard WinMain inputs :-) *
* *
* OUTPUT: *
* *
* Standard WinMain output *
* *
* WARNINGS: *
* *
* HISTORY: *
* 09/19/2001 PDS : Created. *
*=============================================================================================*/
int Start_Application( HINSTANCE hInstance, HINSTANCE /*hPrevInstance*/, LPSTR /*lpCmdLine*/, int nCmdShow )
{
{
WWMEMLOG(MEM_GAMEINIT);
//LPSTR command = lpCmdLine;
/*
** Set the working directory.
*/
Set_Working_Directory(hInstance);
//
// TEMP Dev code - check the working folder is correct!
//
char tmp_buffer[256];
char* tmp_ptr;
if (!SearchPath(
"data",
"always.dat",
NULL,
sizeof(tmp_buffer),
tmp_buffer,
&tmp_ptr)) {
MessageBox(NULL,"Set working folder and try again...","Invalid working folder",MB_OK);
return 0;
}
/*
** Only do these checks if this isn't an auto-restart. If we are restarting then we must have run once OK already. Right?
*/
if (AutoRestart.Get_Restart_Flag() == false && !ConsoleBox.Is_Exclusive()) {
if (!Video_Card_Driver_Check()) return 0;
if (!Graphics_Settings_Trouble_Shooting()) return 0;
}
//Debug_Say(("Started logging at time %s", cMiscUtil::Get_Text_Time()));
if (!Create_Main_Window(hInstance, nCmdShow)) return 0;
Register_Thread_ID(GetCurrentThreadId(), "Main Thread", true);
}
int exitCode = EXIT_SUCCESS;
#ifdef WWDEBUG
if (cDevOptions::EnableExceptionHandler.Is_False()) {
exitCode = Game_Main_Loop();
} else {
#endif //WWDEBUG
Register_Application_Exception_Callback(&Application_Exception_Callback);
Register_Application_Version_Callback(&BuildInfoClass::Composite_Build_Info);
#ifdef _MSC_VER
/*
** The __try/__except construct is part of the WIN32 interface. This is not the same
** as C++ exception handling. There is no additional code overhead required
** with this interface and the compilers exception handling options should be disabled
** to prevent the compiler generating additional stack unwinding code.
*/
__try {
#else
SetUnhandledExceptionFilter((LPTOP_LEVEL_EXCEPTION_FILTER) &Top_Level_Exception_Filter);
#endif
WWDEBUG_SAY(("Game_Main_Loop\n"));
exitCode = Game_Main_Loop();
#ifdef _MSC_VER
} __except(Exception_Handler(GetExceptionCode(), GetExceptionInformation())) {};
/*
** Set the exception filter to use on shutdown.
*/
#else
SetUnhandledExceptionFilter((LPTOP_LEVEL_EXCEPTION_FILTER) &Top_Level_Exception_Filter);
#endif
#ifdef WWDEBUG
}
#endif //WWDEBUG
Unregister_Thread_ID(GetCurrentThreadId(), "Main Thread");
//Debug_Say(("Finished logging at time %s", cMiscUtil::Get_Text_Time()));
return exitCode;
}
/***********************************************************************************************
* Main_Window_Proc -- Windows Proc for the main game window *
* *
* INPUT: *
* *
* Standard Windows Proc inputs *
* *
* OUTPUT: *
* *
* Standard Windows Proc output *
* *
* WARNINGS: *
* *
* HISTORY: *
* 07/18/1997 GH : Created. *
*=============================================================================================*/
long FAR PASCAL Main_Window_Proc( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam )
{
static bool _reset = false;
/*
** Pass this message through to the input handler. If the message
** was processed and requires no further action, then return with
** this information.
*/
if (_TheWWUIInput && Input::Is_Console_Enabled () == false) {
LRESULT result = 0;
//DialogWalker->Process_Message(hwnd, message, wParam, lParam, result);
if (_TheWWUIInput->ProcessMessage(hwnd, message, wParam, lParam, result)) {
return result;
}
}
switch (message )
{
/*
** basic management messages
*/
case WM_ACTIVATEAPP:
if (wParam && !GameInFocus) {
WWDEBUG_SAY(("***** FOCUS GAINED *****\n"));
GameInFocus = true;
On_Focus_Restore();
} else if (!wParam && GameInFocus) {
WWDEBUG_SAY(("***** FOCUS LOST *****\n"));
GameInFocus = false;
On_Focus_Loss();
}
return(0);
case WM_ERASEBKGND:
return 1;
case WM_PAINT:
ValidateRect(hwnd, NULL);
break;
/*
** minimize/maximize
*/
case WM_SYSKEYDOWN:
if (wParam == VK_RETURN && ((lParam>>16) & KF_ALTDOWN) && !((lParam>>16) & KF_REPEAT))
{
if (WIN_fullscreen) {
WIN_fullscreen = false;
} else {
WIN_fullscreen = true;
}
}
break;
/*
** getch()
*/
case WM_CHAR:
//Debug_Say(("WM_CHAR %d\n", wParam));
Input::Console_Add_Key( wParam );
break;
/*
** Main window creation
*/
case WM_CREATE:
break;
/*
** Main window destruction
*/
case WM_DESTROY:
ReleaseCapture ();
PostQuitMessage (0);
break;
case WM_SYSCOMMAND:
switch (wParam) {
case SC_CLOSE:
/*
** Windows sent us a close message. Probably in response to Alt-F4. Ignore it by
** pretending to handle the message and returning true;
*/
return (0);
case SC_KEYMENU:
/*
** Ignore all "menu-activation" commands.
*/
return (0);
case SC_SCREENSAVE:
/*
** Windoze is about to start the screen saver. If we just return without passing
** this message to DefWindowProc then the screen saver will not be allowed to start.
*/
return (0);
}
break;
// Denzil - Using WM_xxxFOCUS messages to switch to windowed / fullscreen fails.
#if(0)
case WM_KILLFOCUS:
{
if (WW3D::Is_Initted ()) {
// Get the current state of the redendering device
int width = 0;
int height = 0;
int bits = 0;
bool bwindowed = false;
WW3D::Get_Device_Resolution (width, height, bits, bwindowed);
// If we are running fullscreen, then toggle to 'windowed'
// and minimze the window.
if (bwindowed == false) {
//Debug_Say(("WM_KILLFOCUS minimize"));
WW3D::Set_Device_Resolution (-1, -1, -1, true);
::ShowWindow (hwnd, SW_MINIMIZE);
_reset = true;
}
}
}
break;
case WM_SETFOCUS:
// If we need to reset the app to 'fullscreen' mode then
// do so an restore the window.
if (_reset == true) {
WW3D::Set_Device_Resolution (-1, -1, -1, false);
::ShowWindow (hwnd, SW_RESTORE);
_reset = false;
}
break;
#endif
case WM_COMMAND:
if (LOWORD (wParam) == IDM_TOGGLE_FULLSCREEN) {
// Ask WW3D to toggle the fullscreen mode for us.
WW3D::Toggle_Windowed ();
}
break;
default:
break;
}
return DefWindowProc(hwnd, message, wParam, lParam);
}
/***********************************************************************************************
* Create_Main_Window -- Creates the main game window *
* *
* INPUT: *
* *
* hInstance -- Instance handle of the application *
* nCmdShow -- how the window is to be shown *
* *
* OUTPUT: *
* *
* TRUE = success, FALSE = failure *
* *
* WARNINGS: *
* *
* HISTORY: *
* 07/18/1997 GH : Created. *
*=============================================================================================*/
static BOOL Create_Main_Window(HANDLE hInstance, int nCmdShow)
{
WNDCLASS wc;
BOOL rc;
ProgramInstance = (HINSTANCE)hInstance;
if (!ConsoleBox.Is_Exclusive()) {
wc.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS;
wc.lpfnWndProc = Main_Window_Proc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = (HINSTANCE)hInstance;
wc.hIcon = LoadIcon( NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor( NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)GetStockObject( BLACK_BRUSH);
wc.lpszMenuName = NULL;
wc.lpszClassName = SingletonInstanceKeeperClass::Get_GUID ();
rc = RegisterClass( &wc);
if (!rc ) return FALSE;
// Assume windowed mode
MainWindow = CreateWindowEx(0, SingletonInstanceKeeperClass::Get_GUID(), "Renegade",
WS_SYSMENU|WS_CAPTION|WS_MINIMIZEBOX|WS_CLIPCHILDREN,
0, 0, 0, 0, NULL, NULL, ProgramInstance, NULL);
if (!MainWindow) {
return FALSE;
}
SetFocus(MainWindow);
}
return TRUE;
}
/***********************************************************************************************
* On_Focus_Loss -- this function is called when the application loses focus *
* *
* INPUT: Nothing *
* *
* OUTPUT: Nothing *
* *
* WARNINGS: None *
* *
* HISTORY: *
* 07/18/1997 GH : Created. *
*=============================================================================================*/
void On_Focus_Loss(void)
{
DirectInput::Unacquire();
}
/***********************************************************************************************
* On_Focus_Restore -- This function is called when the application gets focus *
* *
* INPUT: Nothing *
* *
* OUTPUT: Nothing *
* *
* WARNINGS: None *
* *
* HISTORY: *
* 07/18/1997 GH : Created. *
*=============================================================================================*/
void On_Focus_Restore(void)
{
if (WebBrowser::IsWebPageDisplayed() == false) {
DirectInput::Acquire();
}
GameModeManager::Hide_Render_Frames(1); // Hide the first rendered frame
}
void Prog_End(void)
{
}
/***********************************************************************************************
* Set_Working_Directory -- Sets current directory to be the same as the .exe *
* *
* *
* *
* INPUT: Program instance *
* *
* OUTPUT: Nothing *
* *
* WARNINGS: None *
* *
* HISTORY: *
* 11/6/2001 12:11PM ST : Created *
*=============================================================================================*/
void Set_Working_Directory(HINSTANCE instance)
{
char path_to_exe[256];
char drive[_MAX_DRIVE];
char dir[_MAX_DIR];
char path[_MAX_PATH];
GetModuleFileName(instance, path_to_exe, sizeof(path_to_exe));
_splitpath(path_to_exe, drive, dir, NULL, NULL);
_makepath(path, drive, dir, NULL, NULL);
SetCurrentDirectory(path);
}

47
Code/Commando/WINMAIN.H Normal file
View File

@@ -0,0 +1,47 @@
/*
** 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/>.
*/
/***********************************************************************************************
*** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : Commando *
* *
* $Archive:: /Commando/Code/Commando/WINMAIN.H $*
* *
* $Author:: Denzil_l $*
* *
* $Modtime:: 10/15/01 2:45p $*
* *
* $Revision:: 3 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#ifndef WINMAIN_H
#define WINMAIN_H
#ifndef ALWAYS_H
#include "always.h"
#endif
// This is the main entry point of the game, located in another library
extern int Game_Main_Loop(void);
#endif

File diff suppressed because it is too large Load Diff

225
Code/Commando/WOLBuddyMgr.h Normal file
View File

@@ -0,0 +1,225 @@
/*
** 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/>.
*/
/******************************************************************************
*
* FILE
* $Archive: /Commando/Code/Commando/WOLBuddyMgr.h $
*
* DESCRIPTION
*
* PROGRAMMER
* Denzil E. Long, Jr.
* $Author: Denzil_l $
*
* VERSION INFO
* $Revision: 14 $
* $Modtime: 1/31/02 2:52p $
*
******************************************************************************/
#ifndef __WOLBUDDYMGR_H__
#define __WOLBUDDYMGR_H__
#include <WWOnline\RefPtr.h>
#include <WWOnline\WOLSession.h>
#include <WWOnline\WOLPageMsg.h>
#include <WWLib\RefCount.h>
#include <WWLib\Notify.h>
#include <WWLib\Signaler.h>
#include <WWLib\WideString.h>
#if defined(_MSC_VER)
#pragma warning(push, 3)
#endif
#include <vector>
#if defined(_MSC_VER)
#pragma warning(pop)
#endif
class DlgPasswordPrompt;
class WOLBuddyMgr;
typedef enum
{
BUDDYLIST_CHANGED = 1,
IGNORELIST_CHANGED,
BUDDYINFO_CHANGED
} WOLBuddyMgrAction;
typedef TypedActionPtr<WOLBuddyMgrAction, WOLBuddyMgr> WOLBuddyMgrEvent;
typedef enum
{
PAGE_ERROR = 0,
PAGE_NOT_THERE = 1,
PAGE_TURNED_OFF,
PAGE_SENT,
PAGE_RECEIVED,
INVITATION_RECEIVED,
INVITATION_DECLINED
} WOLPagedAction;
typedef TypedActionPtr<WOLPagedAction, WWOnline::PageMessage> WOLPagedEvent;
class WOLBuddyMgr :
public RefCountClass,
public Notifier<WOLBuddyMgrEvent>,
public Notifier<WOLPagedEvent>,
protected Observer<WWOnline::BuddyEvent>,
protected Observer<WWOnline::UserEvent>,
protected Observer<WWOnline::PageMessage>,
protected Observer<WWOnline::PageSendStatus>,
protected Signaler<DlgPasswordPrompt>
{
public:
typedef std::vector< WideStringClass > IgnoreList;
typedef WWOnline::PageMessageList PageList;
typedef enum
{
DECLINE_MIN = 0,
DECLINE_BYUSER = 1,
DECLINE_NOTBUDDY,
DECLINE_NOTAPPLICABLE,
DECLINE_BUSY,
DECLINE_MAX
} DECLINE_REASON;
static WOLBuddyMgr* GetInstance(bool createOK);
// Get a description of a users location.
static void GetLocationDescription(const RefPtr<WWOnline::UserData>& user, WideStringClass& description);
// Request the buddy list anew.
void RefreshBuddyList(void);
// Get list of buddies
const WWOnline::UserList& GetBuddyList(void) const
{return mWOLSession->GetBuddyList();}
// Get a user from our buddy list
const RefPtr<WWOnline::UserData> FindBuddy(const WCHAR* name) const;
// Add a user to our buddy list
void AddBuddy(const WCHAR* name);
// Remove a user from our buddy list
void RemoveBuddy(const WCHAR* name);
// Check if a user is in our buddy list
bool IsBuddy(const WCHAR* name) const;
// Request update to the location of our buddies.
void RefreshBuddyInfo(void);
// Add a user to the ignore list
void AddIgnore(const WCHAR* name);
// Remove a user from the ignore list.
void RemoveIgnore(const WCHAR* name);
// Check if a user is in the ignore list.
bool IsIgnored(const WCHAR* name) const;
// Get a list of usernames we are ignoring
const IgnoreList& GetIngoreList(void) const
{return mIgnoreList;}
const PageList& GetPageList(void) const
{return mPageList;}
// Enable the display of a dialog when paged.
// This function sets an internal counter that determines whether a dialog
// should be displayed when a page message is received.
void ShowPagedDialog(void);
// Disable the display of a dialog when paged.
// This function sets an internal counter that determines whether a dialog
// should be displayed when a page message is received.
void HidePagedDialog(void);
// Clear all the queued pages.
void ClearPageList(void);
// Get the name of the last user who we received a page from.
const WCHAR* GetLastPagersName(void) const
{return mLastPagersName;}
// Send a page message to user
void PageUser(const WCHAR* name, const WCHAR* message);
// Join a user at his location
void JoinUser(const RefPtr<WWOnline::UserData>& user);
// Check if we are in a position to invite users.
bool CanInviteUsers(void) const;
// Invite a user to our location
void InviteUser(const WCHAR* username, const WCHAR* message);
// Decline an invitation to join a user.
void DeclineInvitation(const WCHAR* username, DECLINE_REASON reason = DECLINE_BYUSER);
protected:
WOLBuddyMgr();
~WOLBuddyMgr();
bool FinalizeCreate(void);
void LoadIgnoreList(void);
void SaveIgnoreList(void);
bool IsCommand(const WCHAR* message);
void ProcessPendingJoin(void);
void GotoPendingJoinLocation(const wchar_t* password);
void ReceiveSignal(DlgPasswordPrompt&);
bool IsInvitation(const WCHAR* message);
void InvitationReceived(WWOnline::PageMessage& page);
void DisplayInvitation(const RefPtr<WWOnline::UserData>& user, const WCHAR* message);
bool IsInvitationDeclined(const WCHAR* message);
void InvitationDeclined(const WCHAR* username, DECLINE_REASON reaon);
void HandleNotification(WWOnline::BuddyEvent&);
void HandleNotification(WWOnline::UserEvent&);
void HandleNotification(WWOnline::PageMessage&);
void HandleNotification(WWOnline::PageSendStatus&);
DECLARE_NOTIFIER(WOLBuddyMgrEvent)
DECLARE_NOTIFIER(WOLPagedEvent)
private:
static WOLBuddyMgr* _mInstance;
RefPtr<WWOnline::Session> mWOLSession;
IgnoreList mIgnoreList;
PageList mPageList;
PageList mInvitations;
WideStringClass mLastPagersName;
unsigned long mHidePagedDialog;
RefPtr<WWOnline::UserData> mPendingJoin;
};
#endif __WOLBUDDYMGR_H__

1560
Code/Commando/WOLChatMgr.cpp Normal file

File diff suppressed because it is too large Load Diff

151
Code/Commando/WOLChatMgr.h Normal file
View File

@@ -0,0 +1,151 @@
/*
** 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/>.
*/
/******************************************************************************
*
* FILE
* $Archive: /Commando/Code/Commando/WOLChatMgr.h $
*
* DESCRIPTION
*
* PROGRAMMER
* Denzil E. Long, Jr.
* $Author: Denzil_l $
*
* VERSION INFO
* $Revision: 18 $
* $Modtime: 11/08/01 2:31p $
*
******************************************************************************/
#ifndef __WOLCHATMGR_H__
#define __WOLCHATMGR_H__
#include <WWLib\RefCount.h>
#include <WWLib\Notify.h>
#include <WWLib\WideString.h>
#include <WWOnline\RefPtr.h>
#include <WWOnline\WOLSession.h>
#include <WWOnline\WOLChatMsg.h>
typedef std::vector< RefPtr<WWOnline::ChannelData> > LobbyList;
enum WOLChatMgrEvent
{
LobbyListChanged = 1,
LobbyChanged,
UserInListChanged,
UserOutListChanged,
MessageListChanged,
KickedFromChannel,
BannedFromChannel
};
class WOLChatMgr :
public RefCountClass,
public Notifier<WOLChatMgrEvent>,
public Observer<WWOnline::ServerError>,
public Observer<WWOnline::ChannelListEvent>,
public Observer<WWOnline::ChannelEvent>,
public Observer<WWOnline::UserEvent>,
public Observer<WWOnline::UserList>,
public Observer<WWOnline::ChatMessage>
{
public:
static WOLChatMgr* GetInstance(bool createOK);
void Start(void);
void Stop(void);
// Lobby Methods
void RefreshLobbyList(void);
const LobbyList& GetLobbyList(void);
const RefPtr<WWOnline::ChannelData>& GetCurrentLobby(void);
const RefPtr<WWOnline::ChannelData> FindLobby(const wchar_t* name);
void CreateLobby(const wchar_t* name, const wchar_t* password);
void JoinLobby(const RefPtr<WWOnline::ChannelData>& channel);
void LeaveLobby(void);
void GetLobbyDisplayName(const RefPtr<WWOnline::ChannelData>& lobby, WideStringClass& outName);
// User Methods
const RefPtr<WWOnline::UserData> FindUser(const wchar_t* name);
inline const WWOnline::UserList& GetUserInList(void)
{return mUserInList;}
void ClearUserInList(void);
inline const WWOnline::UserList& GetUserOutList(void)
{return mUserOutList;}
void ClearUserOutList(void);
bool SquelchUser(const RefPtr<WWOnline::UserData>& user, bool onoff);
void LocateUser(const wchar_t* name);
// Message Methods
inline const WWOnline::ChatMessageList& GetMessageList(void)
{return mMessageList;}
void ClearMessageList(void);
void SendPublicMessage(const wchar_t* message, bool isAction);
void SendPrivateMessage(const RefPtr<WWOnline::UserData>& user, const wchar_t* message, bool isAction);
void SendPrivateMessage(WWOnline::UserList& users, const wchar_t* message, bool isAction);
protected:
WOLChatMgr();
~WOLChatMgr();
// Delcare here to prevent copy and assignment
WOLChatMgr(const WOLChatMgr&);
const WOLChatMgr& operator=(const WOLChatMgr&);
bool FinalizeCreate(void);
bool IsLobbyValid(const RefPtr<WWOnline::ChannelData>& lobby);
void AddMessage(const wchar_t* sender, const wchar_t* message, bool isPrivate, bool isAction);
bool PassesFilters(const WWOnline::ChatMessage& msg);
void HandleNotification(WWOnline::ServerError&);
void HandleNotification(WWOnline::ChannelListEvent&);
void HandleNotification(WWOnline::ChannelEvent&);
void HandleNotification(WWOnline::UserEvent&);
void HandleNotification(WWOnline::UserList&);
void HandleNotification(WWOnline::ChatMessage&);
bool ProcessCommand(const wchar_t* message);
private:
static WOLChatMgr* _mInstance;
RefPtr<WWOnline::Session> mWOLSession;
WideStringClass mLobbyPrefix;
LobbyList mLobbyList;
WWOnline::UserList mUserInList;
WWOnline::UserList mUserOutList;
WideStringClass mLocatingUserName;
WWOnline::ChatMessageList mMessageList;
};
#endif __WOLCHATMGR_H__

134
Code/Commando/WOLDiags.cpp Normal file
View File

@@ -0,0 +1,134 @@
/*
** 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/>.
*/
#ifdef WWDEBUG
/******************************************************************************
*
* FILE
* $Archive: /Commando/Code/Commando/WOLDiags.cpp $
*
* DESCRIPTION
*
* PROGRAMMER
* $Author: Denzil_l $
*
* VERSION INFO
* $Revision: 4 $
* $Modtime: 1/11/02 5:43p $
*
******************************************************************************/
#include "WOLDiags.h"
#include <WWOnline\WOLSession.h>
#include <WWOnline\WOLServer.h>
using namespace WWOnline;
void ShowWOLVersion(const RefPtr<Session>& session)
{
unsigned long ver = 0;
session->GetChatObject()->GetVersion(&ver);
ConsoleFunctionClass::Print("WOLAPI V%u.%u\n", (ver >> 16), (ver & 0xFFFF));
}
void ShowServer(const RefPtr<Session>& session)
{
const RefPtr<IRCServerData>& server = session->GetCurrentServer();
if (server.IsValid())
{
WOL::Server& data = server->GetData();
ConsoleFunctionClass::Print("Server: %s:%s TimeZone: %d Position:: %f/%f\n",
(const char*)data.connlabel, (const char*)data.name, data.timezone, data.longitude, data.lattitude);
}
else
{
ConsoleFunctionClass::Print("WOL not connected\n");
}
}
void ShowTopic(const RefPtr<Session>& session)
{
ConsoleFunctionClass::Print("Channel Topic: %s\n", session->GetChannelTopic());
}
void ShowPingServers(const RefPtr<Session>& session)
{
const PingServerList& pingServers = session->GetPingServerList();
unsigned int count = pingServers.size();
for (unsigned int index = 0; index < count; index++)
{
const RefPtr<PingServerData>& ping = pingServers[index];
ConsoleFunctionClass::Print("%-18s %-4dms - %s\n",
ping->GetHostAddress(), ping->GetPingTime(), ping->GetName());
}
}
struct Dispatch
{
const char* Cmd;
void (*Func)(const RefPtr<Session>&);
};
const char* WOLConsoleFunctionClass::Get_Help(void)
{
return ("WOL <command> - Show WOL information");
}
void WOLConsoleFunctionClass::Activate(const char* input)
{
static Dispatch _dispatch[] =
{
{"pings", ShowPingServers},
{"server", ShowServer},
{"topic", ShowTopic},
{"ver", ShowWOLVersion},
{NULL, NULL}
};
RefPtr<Session> session = Session::GetInstance(false);
if (!session.IsValid())
{
ConsoleFunctionClass::Print("Westwood Online not active\n");
return;
}
int index = 0;
const char* cmd = _dispatch[0].Cmd;
while (cmd != NULL)
{
if (stricmp(cmd, input) == 0)
{
_dispatch[index].Func(session);
return;
}
++index;
cmd = _dispatch[index].Cmd;
}
}
#endif // WWDEBUG

51
Code/Commando/WOLDiags.h Normal file
View File

@@ -0,0 +1,51 @@
/*
** 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/>.
*/
#ifdef WWDEBUG
#ifndef __WOLDIAGS_H__
#define __WOLDIAGS_H__
/******************************************************************************
*
* FILE
* $Archive: /Commando/Code/Commando/WOLDiags.h $
*
* DESCRIPTION
*
* PROGRAMMER
* $Author: Denzil_l $
*
* VERSION INFO
* $Revision: 2 $
* $Modtime: 9/21/01 3:14p $
*
******************************************************************************/
#include "ConsoleFunction.h"
class WOLConsoleFunctionClass : public ConsoleFunctionClass {
public:
const char* Get_Name(void)
{return ("wol");}
const char* Get_Help(void);
void Activate(const char* input);
};
#endif // __WOLDIAGS_H__
#endif // WWDEBUG

View File

@@ -0,0 +1,654 @@
/*
** 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/>.
*/
/******************************************************************************
*
* FILE
* $Archive: /Commando/Code/Commando/WOLGameInfo.cpp $
*
* DESCRIPTION
*
* PROGRAMMER
* $Author: Steve_t $
*
* VERSION INFO
* $Revision: 18 $
* $Modtime: 10/31/02 4:30p $
*
******************************************************************************/
#include "WOLGameInfo.h"
#include "GameData.h"
#include "CNetwork.h"
#include <WWOnline\WOLUser.h>
#include <WWOnline\WOLChannel.h>
#include <WWOnline\PingProfile.h>
#include <WWLib\RealCRC.h>
#include "modpackagemgr.h"
using namespace WWOnline;
/******************************************************************************
*
* NAME
* WOLGameInfo::WOLGameInfo
*
* DESCRIPTION
* Default constructor
*
* INPUTS
* NONE
*
* RESULT
* NONE
*
******************************************************************************/
WOLGameInfo::WOLGameInfo(void) :
mIsDataValid(false),
mIsMapValid(true),
mPingTime(-1)
{
}
/******************************************************************************
*
* NAME
* WOLGameInfo::WOLGameInfo
*
* DESCRIPTION
* Import information about the game.
*
* INPUTS
* Game - Game to import information from.
*
* RESULT
* NONE
*
******************************************************************************/
WOLGameInfo::WOLGameInfo(const cGameData& theGame)
{
ImportFromGame(theGame);
}
/******************************************************************************
*
* NAME
* WOLGameInfo::WOLGameInfo
*
* DESCRIPTION
* Import information about the game from a channel.
*
* INPUTS
* Channel - Channel to import game information from.
*
* RESULT
* NONE
*
******************************************************************************/
WOLGameInfo::WOLGameInfo(const RefPtr<ChannelData>& channel)
{
ImportFromChannel(channel);
}
/******************************************************************************
*
* NAME
* WOLGameInfo::~WOLGameInfo
*
* DESCRIPTION
* Destructor
*
* INPUTS
* NONE
*
* RESULT
* NONE
*
******************************************************************************/
WOLGameInfo::~WOLGameInfo(void)
{
}
/******************************************************************************
*
* NAME
* WOLGameInfo::Reset
*
* DESCRIPTION
*
* INPUTS
* NONE
*
* RESULT
* NONE
*
******************************************************************************/
void WOLGameInfo::Reset(void)
{
mIsDataValid = false;
mIsMapValid = true;
mVersion = 0;
mGameType = 0;
mMapName[0] = 0;
mModName[0] = 0;
mTitle[0] = 0;
mMinPlayers = 0;
mMaxPlayers = 0;
mNumPlayers = 0;
mClanID1 = 0;
mClanID2 = 0;
mIsMod = false;
mIsLaddered = false;
mIsPassworded = false;
mIsQuickmatch = false;
mIsDedicated = false;
mIsFriendlyFire = false;
mIsFreeWeapons = false;
mIsTeamRemix = false;
mIsTeamChange = false;
mIsClanGame = false;
mIsRepairBuildings = false;
mIsDriverGunner = false;
mSpawnWeapons = false;
mPingTime = -1;
}
/******************************************************************************
*
* NAME
* WOLGameInfo::ImportFromGame
*
* DESCRIPTION
* Import information about the game.
*
* INPUTS
* Game - Game to import information from.
*
* RESULT
* NONE
*
******************************************************************************/
void WOLGameInfo::ImportFromGame(const cGameData& theGame)
{
Reset();
mIsDataValid = true;
mIsMapValid = true;
mVersion = theGame.Get_Version_Number();
mGameType = theGame.Get_Game_Type();
strncpy(mMapName, theGame.Get_Map_Name(), MAX_TEXT_LENGTH);
mMapName[MAX_TEXT_LENGTH - 1] = 0;
strncpy(mModName, theGame.Get_Mod_Name(), MAX_TEXT_LENGTH);
mModName[MAX_TEXT_LENGTH - 1] = 0;
wcstombs(mTitle, theGame.Get_Game_Title(), MAX_TEXT_LENGTH);
mTitle[MAX_TEXT_LENGTH - 1] = 0;
mMinPlayers = theGame.Get_Min_Players();
mMaxPlayers = theGame.Get_Max_Players();
mNumPlayers = theGame.Get_Current_Players();
mClanID1 = theGame.Get_Clan(0);
mClanID2 = theGame.Get_Clan(1);
const WCHAR* password = theGame.Get_Password();
mIsPassworded = ((password != NULL) && (wcslen(password) > 0));
mIsLaddered = theGame.IsLaddered.Get();
mIsQuickmatch = theGame.Is_QuickMatch_Server();
mIsDedicated = theGame.IsDedicated.Get();
mIsFriendlyFire = theGame.IsFriendlyFirePermitted.Get();
mIsFreeWeapons = theGame.IsFreeWeapons.Get();
mIsTeamRemix = theGame.RemixTeams.Get();
mIsTeamChange = theGame.IsTeamChangingAllowed.Get();
mIsClanGame = theGame.IsClanGame.Get();
// C&C mode flags
mIsRepairBuildings = theGame.CanRepairBuildings.Get();
mIsDriverGunner = theGame.DriverIsAlwaysGunner.Get();
mSpawnWeapons = theGame.SpawnWeapons.Get();
mIsMod = (theGame.Get_Mod_Name().Is_Empty() == false);
mPingTime = -1;
}
/******************************************************************************
*
* NAME
* WOLGameInfo::ImportFromChannel
*
* DESCRIPTION
* Import information about the game from a channel.
*
* INPUTS
* Channel - Channel to import game information from.
*
* RESULT
* NONE
*
******************************************************************************/
void WOLGameInfo::ImportFromChannel(const RefPtr<ChannelData>& channel)
{
Reset();
if (channel.IsValid() == false)
{
mIsDataValid = false;
return;
}
//ST - Test code
//if (channel->GetName() != WideStringClass(L"ladtest07")) {
// mIsDataValid = false;
// return;
//}
const char* exInfo = channel->GetExtraInfo();
if ((exInfo == NULL) || (exInfo && (strlen(exInfo) != 36)))
{
WWDEBUG_SAY(("WOLERROR: Channel ExInfo NULL or wrong size\n"));
mIsDataValid = false;
return;
}
// Assume the data will be valid
mIsDataValid = true;
// Extract ExInfo settings
unsigned long fileCRC = 0;
unsigned long version = 0;
unsigned long clanID1 = 0;
unsigned long clanID2 = 0;
unsigned char gameType = 0;
unsigned char gameFlags1 = 0;
unsigned char gameFlags2 = 0;
unsigned char modMapIndex = 0;
int count = sscanf(exInfo, "%08lX%08lX%08lX%08lX%c%c%c%c", &version, &fileCRC,
&clanID1, &clanID2, &gameType, &gameFlags1, &gameFlags2, &modMapIndex);
// There should be 8 parameters in the exinfo
if (count != 8)
{
WWDEBUG_SAY(("WOLERROR: Channel ExInfo malformed\n"));
mIsDataValid = false;
}
if (version != cNetwork::Get_Exe_Key()) {
mIsDataValid = false;
return;
}
mVersion = version;
mGameType = (cGameData::GameTypeEnum)(gameType - '0');
if (mGameType != cGameData::GAME_TYPE_CNC)
{
WWDEBUG_SAY(("WOLERROR: GameType '%d' out of range\n", mGameType));
mIsDataValid = false;
}
// Extract game flags
mIsLaddered = (channel->GetTournament() != 0);
mIsPassworded = channel->IsPassworded();
mIsDedicated = ((gameFlags1 & 0x40) == 0x40);
mIsFriendlyFire = ((gameFlags1 & 0x10) == 0x10);
mIsFreeWeapons = ((gameFlags1 & 0x08) == 0x08);
mIsTeamRemix = ((gameFlags1 & 0x04) == 0x04);
mIsTeamChange = ((gameFlags1 & 0x02) == 0x02);
mIsClanGame = ((gameFlags1 & 0x01) == 0x01);
mIsMod = ((gameFlags2 & 0x40) == 0x40);
mSpawnWeapons = ((gameFlags2 & 0x04) == 0x04);
mIsRepairBuildings = ((gameFlags2 & 0x02) == 0x02);
mIsDriverGunner = ((gameFlags2 & 0x01) == 0x01);
// Find the mod and map names from their CRC
StringClass mapName(0, true);
mapName = "<Unknown>";
StringClass modName(0, true);
bool got_map_name = true;
if (mIsMod)
{
// Get the true index (+32 put the index into the printable range)
modMapIndex -= 32;
// Find mod based on its crc and get map filename based on the index.
if (ModPackageMgrClass::Get_Mod_Map_Name_From_CRC_Index(fileCRC, modMapIndex, &modName, &mapName) == false)
{
//mIsDataValid = false;
got_map_name = false;
}
}
else
{
// Find mod based on its crc and get map filename based on the index.
if (ModPackageMgrClass::Get_Mod_Map_Name_From_CRC (0, fileCRC, &modName, &mapName) == false)
{
//mIsDataValid = false;
got_map_name = false;
}
}
strncpy(mModName, modName, MAX_TEXT_LENGTH);
mModName[MAX_TEXT_LENGTH - 1] = 0;
strncpy(mMapName, mapName, MAX_TEXT_LENGTH);
mMapName[MAX_TEXT_LENGTH - 1] = 0;
mMinPlayers = channel->GetMinUsers();
mMaxPlayers = channel->GetMaxUsers();
mNumPlayers = channel->GetCurrentUsers();
// Do not count the host as a player for dedicated servers.
if (mIsDedicated)
{
WWASSERT(mNumPlayers > 0);
--mNumPlayers;
WWASSERT(mMaxPlayers > 0);
--mMaxPlayers;
}
mClanID1 = clanID1;
mClanID2 = clanID2;
const char* topic = channel->GetTopic();
if (topic == NULL)
{
WWDEBUG_SAY(("WOLERROR: Channel Topic is NULL\n"));
mIsDataValid = false;
}
// Quickmatch settings are marked by a pipe '|' character
mIsQuickmatch = (strchr(topic, '|') != NULL);
// Extract game title from topic
unsigned int titleLength = (topic[0] - 0x20);
WWASSERT(titleLength <= 32);
titleLength = min<unsigned int>(titleLength, 32);
++topic;
strncpy(mTitle, topic, titleLength);
mTitle[titleLength] = 0;
WWASSERT(strlen(mTitle) == titleLength);
topic += titleLength;
unsigned int mapLength = (topic[0] - 0x20);
WWASSERT(mapLength <= 16);
mapLength = min<unsigned int>(mapLength, 16);
++topic;
if (!got_map_name) {
strncpy(mMapName, topic, mapLength);
mMapName[mapLength] = 0;
WWASSERT(strlen(mMapName) == mapLength);
mIsMapValid = false;
}
topic += mapLength;
// Calculate ping
PingProfile pings;
DecodePingProfile(topic, pings);
const PingProfile& localPings = GetLocalPingProfile();
mPingTime = ComparePingProfile(localPings, pings);
}
/******************************************************************************
*
* NAME
* WOLGameInfo::ExportToChannel
*
* DESCRIPTION
* Export game information into a channel.
*
* INPUTS
* Channel - Channel to export game information into.
*
* RESULT
* NONE
*
******************************************************************************/
void WOLGameInfo::ExportToChannel(const RefPtr<ChannelData>& channel)
{
if (channel.IsValid() && mIsDataValid)
{
// If this is a dedicated server then the max players must be incremented
// by one to account for the host.
unsigned int maxPlayers = (mIsDedicated == true) ? (mMaxPlayers + 1) : mMaxPlayers;
// Set the channels min and max players
channel->SetMinMaxUsers(mMinPlayers, maxPlayers);
// Set the tournament type
unsigned int tournamentType = (mIsLaddered ? 1 : 0);
channel->SetTournament(tournamentType);
//-------------------------------------------------------------------------
// Encode ExInfo
//-------------------------------------------------------------------------
// For flags bit 6 must be set to keep the overall value at least a space character
unsigned char gameFlags1 = 0x20;
gameFlags1 |= mIsDedicated ? 0x40 : 0x00;
gameFlags1 |= mIsFriendlyFire ? 0x10 : 0x00;
gameFlags1 |= mIsFreeWeapons ? 0x08 : 0x00;
gameFlags1 |= mIsTeamRemix ? 0x04 : 0x00;
gameFlags1 |= mIsTeamChange ? 0x02 : 0x00;
gameFlags1 |= mIsClanGame ? 0x01 : 0x00;
unsigned char gameFlags2 = 0x20;
gameFlags2 |= mIsMod ? 0x40 : 0x00;
gameFlags2 |= mSpawnWeapons ? 0x04: 0x00;
gameFlags2 |= mIsRepairBuildings ? 0x02: 0x00;
gameFlags2 |= mIsDriverGunner ? 0x01: 0x00;
// The file CRC is either the map name or the mod name depending on if
// the mod flag is set.
unsigned long fileCRC = 0;
unsigned char modMapIndex = 0;
if (mIsMod)
{
ModPackageClass& package = ModPackageMgrClass::Get_Current_Package();
fileCRC = package.Get_CRC();
modMapIndex = package.Get_Map_Index(mMapName);
}
else
{
fileCRC = ::CRC_Stringi(mMapName);
}
// Put the map index into the printable ASCII range
modMapIndex += 32;
// WARNING: The channels ExInfo field has a maximum size of 40 bytes.
char exInfo[41];
sprintf(exInfo, "%08lX%08lX%08lX%08lX%c%c%c%c", mVersion, fileCRC,
mClanID1, mClanID2, (0x30 + mGameType), gameFlags1, gameFlags2, modMapIndex);
channel->SetExtraInfo(exInfo);
//-------------------------------------------------------------------------
// Encode topic
//-------------------------------------------------------------------------
unsigned int titleLength = min<unsigned int>(strlen(mTitle), 32);
titleLength += 0x20;
// WARNING: The channels topic field has a maximum size of 80 bytes.
// Ping profile and quickmatch settings are encoded in the topic in
// addition to the the game title. The combined maximum of ALL these
// entries MUST NEVER exceed 80 bytes.
char topic[81];
sprintf(topic, "%c%.32s", titleLength, mTitle);
//
// Only using 61 max right now. Room for a map name maybe? ST - 10/31/2002 2:55PM
//
unsigned int mapLength = min<unsigned int>(strlen(mMapName), 16);
mapLength += 0x20;
// WARNING: The channels topic field has a maximum size of 80 bytes.
// Ping profile and quickmatch settings are encoded in the topic in
// addition to the the game title. The combined maximum of ALL these
// entries MUST NEVER exceed 80 bytes.
char mapinfo[81];
sprintf(mapinfo, "%c%.16s", mapLength, mMapName);
strcat(topic, mapinfo);
// Add our ping profile
const PingProfile& localPings = GetLocalPingProfile();
EncodePingProfile(localPings, topic);
channel->SetTopic(topic);
}
}
/******************************************************************************
*
* NAME
* WOLGameInfo::
*
* DESCRIPTION
*
* INPUTS
*
* RESULT
*
******************************************************************************/
bool WOLGameInfo::IsValidGameChannel(const RefPtr<ChannelData>& channel)
{
WOLGameInfo gameInfo(channel);
return (gameInfo.IsDataValid() && (gameInfo.mVersion == (unsigned long)cNetwork::Get_Exe_Key()));
}
/******************************************************************************
*
* NAME
* WOLGameInfo::IsClanCompeting
*
* DESCRIPTION
* Check if the specified clan is competing in the game.
*
* INPUTS
* Clan - ID of clan to check.
*
* RESULT
* True if clan is competing.
*
******************************************************************************/
bool WOLGameInfo::IsClanCompeting(unsigned long clanID) const
{
return (mIsClanGame && (clanID != 0) && ((clanID == mClanID1) || (clanID == mClanID2)));
}
/******************************************************************************
*
* NAME
* WOLGameInfo::IsClanGameOpen
*
* DESCRIPTION
* Check if the clan game is open for new clans to join.
*
* INPUTS
* NONE
*
* RESULT
* True if the game is open to clans.
*
******************************************************************************/
bool WOLGameInfo::IsClanGameOpen(void) const
{
return (mIsClanGame && ((0 == mClanID1) || (0 == mClanID2)));
}
/******************************************************************************
*
* NAME
* WOLGameInfo::CanUserJoin
*
* DESCRIPTION
* Check if the user is able to join this game.
*
* INPUTS
* User
*
* RESULT
* True if user can join this game.
*
******************************************************************************/
bool WOLGameInfo::CanUserJoin(const RefPtr<UserData>& user)
{
if (!user.IsValid() || !mIsDataValid || !mIsMapValid)
{
return false;
}
if (mVersion != (unsigned long)cNetwork::Get_Exe_Key())
{
return false;
}
if (mIsClanGame)
{
unsigned long userClanID = user->GetSquadID();
return ((0 != userClanID) && (IsClanGameOpen() || IsClanCompeting(userClanID)));
}
return true;
}

194
Code/Commando/WOLGameInfo.h Normal file
View File

@@ -0,0 +1,194 @@
/*
** 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/>.
*/
/******************************************************************************
*
* FILE
* $Archive: /Commando/Code/Commando/WOLGameInfo.h $
*
* DESCRIPTION
*
* PROGRAMMER
* $Author: Steve_t $
*
* VERSION INFO
* $Revision: 11 $
* $Modtime: 10/31/02 3:07p $
*
******************************************************************************/
#ifndef __WOLGAMEINFO_H__
#define __WOLGAMEINFO_H__
#include <WWOnline\RefPtr.h>
class cGameData;
namespace WWOnline
{
class ChannelData;
class UserData;
}
// Game information used to describe the type of game.
class WOLGameInfo
{
public:
static bool IsValidGameChannel(const RefPtr<WWOnline::ChannelData>& channel);
enum {MAX_TEXT_LENGTH = 32};
WOLGameInfo(void);
WOLGameInfo(const cGameData& theGame);
WOLGameInfo(const RefPtr<WWOnline::ChannelData>& channel);
~WOLGameInfo(void);
void Reset(void);
bool IsDataValid(void) const
{return mIsDataValid;}
bool IsMapValid(void) const
{return mIsMapValid;}
void ImportFromGame(const cGameData& theGame);
void ImportFromChannel(const RefPtr<WWOnline::ChannelData>& channel);
void ExportToChannel(const RefPtr<WWOnline::ChannelData>& channel);
unsigned long Version(void) const
{return mVersion;};
unsigned int GameType(void) const
{return mGameType;}
const char* MapName(void) const
{return mMapName;}
const char* ModName(void) const
{return mModName;}
const char* Title(void) const
{return mTitle;}
unsigned int MinPlayers(void) const
{return mMinPlayers;}
unsigned int MaxPlayers(void) const
{return mMaxPlayers;}
unsigned int NumPlayers(void) const
{return mNumPlayers;}
unsigned long ClanID1(void) const
{return mClanID1;}
unsigned long ClanID2(void) const
{return mClanID2;}
bool IsLaddered(void) const
{return mIsLaddered;}
bool IsPassworded(void) const
{return mIsPassworded;}
bool IsQuickmatch(void) const
{return mIsQuickmatch;}
bool IsDedicated(void) const
{return mIsDedicated;}
bool IsFriendlyFire(void) const
{return mIsFriendlyFire;}
bool IsFreeWeapons(void) const
{return mIsFreeWeapons;}
bool IsTeamRemix(void) const
{return mIsTeamRemix;}
bool IsTeamChange(void) const
{return mIsTeamChange;}
bool IsClanGame(void) const
{return mIsClanGame;}
bool IsRepairBuildings(void) const
{return mIsRepairBuildings;}
bool IsDriverGunner(void) const
{return mIsDriverGunner;}
bool IsSpawnWeapons(void) const
{return mSpawnWeapons;}
int PingTime(void) const
{return mPingTime;}
// Is the clan competing in the game.
bool IsClanCompeting(unsigned long clanID) const;
bool IsClanGameOpen(void) const;
bool CanUserJoin(const RefPtr<WWOnline::UserData>& user);
protected:
// Prevent copy and assignment
WOLGameInfo(const WOLGameInfo&);
const WOLGameInfo& operator=(const WOLGameInfo&);
protected:
bool mIsDataValid;
bool mIsMapValid;
unsigned long mVersion;
unsigned int mGameType;
char mMapName[MAX_TEXT_LENGTH];
char mModName[MAX_TEXT_LENGTH];
char mTitle[MAX_TEXT_LENGTH];
unsigned int mMinPlayers;
unsigned int mMaxPlayers;
unsigned int mNumPlayers;
unsigned long mClanID1;
unsigned long mClanID2;
bool mIsMod;
bool mIsLaddered;
bool mIsPassworded;
bool mIsQuickmatch;
bool mIsDedicated;
bool mIsFriendlyFire;
bool mIsFreeWeapons;
bool mIsTeamRemix;
bool mIsTeamChange;
bool mIsClanGame;
bool mIsRepairBuildings;
bool mIsDriverGunner;
bool mSpawnWeapons;
int mPingTime;
};
#endif // __WOLGAMEINFO_H__

View File

@@ -0,0 +1,609 @@
/*
** 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/>.
*/
/******************************************************************************
*
* FILE
* $Archive: /Commando/Code/Commando/WOLJoinGame.cpp $
*
* DESCRIPTION
*
* PROGRAMMER
* $Author: Denzil_l $
*
* VERSION INFO
* $Revision: 18 $
* $Modtime: 1/17/02 11:43a $
*
******************************************************************************/
#include "WOLJoinGame.h"
#include "DlgWOLWait.h"
#include "DlgMessageBox.h"
#include "DlgMPConnect.h"
#include "Nat.h"
#include "Natter.h"
#include "FirewallWait.h"
#include "CNetwork.h"
#include "WOLGameInfo.h"
#include <WWOnline\WOLSession.h>
#include <WWOnline\WOLProduct.h>
#include <WWOnline\WOLChannel.h>
#include "String_IDs.h"
#include <WWTranslateDB\TranslateDB.h>
#include <WWDebug\WWDebug.h>
using namespace WWOnline;
/******************************************************************************
*
* NAME
* WOLJoinGame::JoinTheGame
*
* DESCRIPTION
* Join the specified game.
*
* INPUTS
* GameName - Name of the game to join
* Password - Game password
*
* RESULT
* NONE
*
******************************************************************************/
void WOLJoinGame::JoinTheGame(const wchar_t* gameName, const wchar_t* password, bool allowTeamSelect)
{
WWASSERT(gameName != NULL && "Invalid parameter");
if (gameName)
{
// Create the object to handle the game joining process.
WOLJoinGame* joinGame = new WOLJoinGame;
WWASSERT(joinGame && "WOLJoinGame failed to instantiate");
if (joinGame)
{
if (joinGame->FinalizeCreate())
{
// Start the join game process
if (joinGame->Join(gameName, password, allowTeamSelect))
{
return;
}
}
// This will delete the WOLJoinGame object
joinGame->Release_Ref();
}
// If we got here then the join failed. Show a dialog telling the user
// that we were unable to join the requested game.
WideStringClass message(255, true);
message.Format(TRANSLATE(IDS_GAME_JOINCHANNEL), gameName);
DlgMsgBox::DoDialog(TRANSLATE(IDS_WOL_ERROR), message);
}
}
/******************************************************************************
*
* NAME
* WOLJoinGame::WOLJoinGame
*
* DESCRIPTION
* Default constructor
*
* INPUTS
* NONE
*
* RESULT
* NONE
*
******************************************************************************/
WOLJoinGame::WOLJoinGame() :
mJoinState(IDLE_STATE),
mAllowTeamSelect(true),
mTeamChoice(-1),
mClanID(0)
{
WWDEBUG_SAY(("WOLJoinGame: Instantiated\n"));
}
/******************************************************************************
*
* NAME
* WOLJoinGame::~WOLJoinGame
*
* DESCRIPTION
* Destructor
*
* INPUTS
* NONE
*
* RESULT
* NONE
*
******************************************************************************/
WOLJoinGame::~WOLJoinGame()
{
WWDEBUG_SAY(("WOLJoinGame: Destroyed\n"));
}
/******************************************************************************
*
* NAME
* WOLJoinGame::FinalizeCreate
*
* DESCRIPTION
*
* INPUTS
* NONE
*
* RESULT
* True if successful
*
******************************************************************************/
bool WOLJoinGame::FinalizeCreate(void)
{
mWOLSession = Session::GetInstance(false);
return mWOLSession.IsValid();
}
/******************************************************************************
*
* NAME
* WOLJoinGame::CreateGameFromChannel
*
* DESCRIPTION
* Create a game data instance from a WWOnline game channel.
*
* INPUTS
* Channel - Game channel to create game data instance from.
*
* RESULT
* Game - Instance to game.
*
******************************************************************************/
cGameData* WOLJoinGame::CreateGameFromChannel(const RefPtr<ChannelData>& channel)
{
WWASSERT(channel.IsValid() && "Invalid paramter");
WWDEBUG_SAY(("WOLJoinGame: Create game from channel '%S'\n", (const WCHAR*)channel->GetName()));
// Extract game information from the channel
WOLGameInfo gameInfo(channel);
if (gameInfo.IsDataValid() == false)
{
return NULL;
}
// Create an instance of the correct type.
cGameData* theGame = cGameData::Create_Game_Of_Type((cGameData::GameTypeEnum)gameInfo.GameType());
if (theGame)
{
// The game owner is the name of the channel
const WideStringClass& channelName = channel->GetName();
theGame->Set_Owner(const_cast<WideStringClass&>(channelName));
if (gameInfo.IsPassworded())
{
theGame->Set_Password(mPassword);
}
theGame->Import_Tier_1_Data(gameInfo);
}
return theGame;
}
/******************************************************************************
*
* NAME
* WOLJoinGame::Join
*
* DESCRIPTION
* The steps to join a game successfully are as follows:
*
* 1) Join the game channel.
* 2) Allow user to select his team.
* 3) Receive team selection choice.
* 4) Create an instance of the game.
* 5) Perform firewall negotiation
* 6) Connect to the server.
*
* INPUTS
* Name - Name of game channel (This is usually the same as the hosts name).
* Password - Password to enter game; NULL if not passworded.
* AllowSelect - True if user is allowed to select their team.
*
* RESULT
* True if join request is successful.
*
******************************************************************************/
bool WOLJoinGame::Join(const wchar_t* gameName, const wchar_t* password, bool allowTeamSelect)
{
WWDEBUG_SAY(("WOLJoinGame: Joining game channel '%S' Password: '%S'\n", gameName, password));
mAllowTeamSelect = allowTeamSelect;
mGameName = gameName;
mPassword = password;
//---------------------------------------------------------------------------
// First we need to join the channel
//---------------------------------------------------------------------------
RefPtr<Product> product = Product::Current();
WWASSERT(product.IsValid());
if (!product.IsValid())
{
WWDEBUG_SAY(("ERROR: WWOnline product not initialized.\n"));
return false;
}
int gameType = product->GetGameCode();
RefPtr<WaitCondition> wait = mWOLSession->JoinChannel(gameName, password, gameType);
if (!wait.IsValid())
{
WWDEBUG_SAY(("ERROR: Couldn't create JoinChannellWait\n"));
return false;
}
// Tell the firewall code that we are connecting as a client.
WOLNATInterface.Set_Server(false);
// Listen for channel events. We will use this to obtain the channel
Observer<ChannelEvent>::NotifyMe(*mWOLSession);
// Generate message for user to see while we are attempting to join the channel.
WideStringClass message(255, true);
message.Format(TRANSLATE(IDS_GAME_JOINCHANNEL), gameName);
mJoinState = JOINING_STATE;
return DlgWOLWait::DoDialog((const WCHAR*)message, wait, this);
}
/******************************************************************************
*
* NAME
* WOLJoinGame::ProceedWithConnection
*
* DESCRIPTION
*
* INPUTS
*
* RESULT
* NONE
*
******************************************************************************/
void WOLJoinGame::ProceedWithConnection(int teamChoice)
{
WWDEBUG_SAY(("WOLJoinGame: Proceeding with connection\n"));
bool success = StartServerConnect();
// If the connection is underway then wait for it to complete.
if (success)
{
mTeamChoice = teamChoice;
return;
}
// An error has occured while attempting to connect.
DlgMsgBox::DoDialog(IDS_WOL_ERROR, IDS_MP_UNABLE_CONNECT_TO_SERVER);
Leave();
}
/******************************************************************************
*
* NAME
* WOLJoinGame::Leave
*
* DESCRIPTION
*
* INPUTS
*
* RESULT
*
******************************************************************************/
void WOLJoinGame::Leave(void)
{
WWDEBUG_SAY(("WOLJoinGame: Leaving channel\n"));
// If the user elected to leave the game or we encountered an error starting
// the connection then leave the channel.
RefPtr<WaitCondition> wait = mWOLSession->LeaveChannel();
DlgWOLWait::DoDialog(IDS_GAME_LEAVECHANNEL, wait);
// This will delete the WOLJoinGame object
Release_Ref();
}
/******************************************************************************
*
* NAME
* WOLJoinGame::StartServerConnect
*
* DESCRIPTION
* Start server connection negotiation
*
* INPUTS
* NONE
*
* RESULT
* True if negotiation successfully started.
*
******************************************************************************/
bool WOLJoinGame::StartServerConnect(void)
{
WWDEBUG_SAY(("WOLJoinGame: Start server connect\n"));
// If the channel is NOT valid then bad things have happened.
if (!mTheChannel.IsValid())
{
WWDEBUG_SAY(("WOLJoinGame: ERROR channel not valid when connecting to host\n"));
WWASSERT(mTheChannel.IsValid() && "Bad channel connecting to host");
return false;
}
// Verify that the user can join this game.
WOLGameInfo gameInfo(mTheChannel);
RefPtr<UserData> user = mWOLSession->GetCurrentUser();
if (gameInfo.CanUserJoin(user) == false)
{
WWDEBUG_SAY(("WOLJoinGame: ERROR - User cannot join this game\n"));
return false;
}
// If we are playing a clan game then we need the users clan ID in order to join.
if (gameInfo.IsClanGame())
{
mClanID = user->GetSquadID();
}
// Delete any existing game.
if (PTheGameData)
{
delete PTheGameData;
PTheGameData = NULL;
}
// Create a new game from the channel
cGameData* theGame = CreateGameFromChannel(mTheChannel);
WWASSERT(theGame && "WOLJoinGame failed to create cGameData");
if (theGame == NULL)
{
WWDEBUG_SAY(("WOLJoinGame: ERROR failed to create cGameData\n"));
return false;
}
// Assign the new game instance
PTheGameData = theGame;
// We are done with the channel
mTheChannel.Release();
//---------------------------------------------------------------------------
// Wait for the firewall negotiation. Will send DlgWOLWaitEvent when complete.
//---------------------------------------------------------------------------
RefPtr<WaitCondition> wait = FirewallConnectWait::Create();
if (!wait.IsValid())
{
WWDEBUG_SAY(("WOLJoinGame: ERROR couldn't create FireWallWait\n"));
return false;
}
mJoinState = FIREWALL_STATE;
return DlgWOLWait::DoDialog(TRANSLATE (IDS_MENU_CONNECTING), wait, this);
}
/******************************************************************************
*
* NAME
* WOLJoinGame::ConnectToServer
*
* DESCRIPTION
* Establish connection to game server.
*
* INPUTS
* NONE
*
* RESULT
* NONE
*
******************************************************************************/
void WOLJoinGame::ConnectToServer(void)
{
WWDEBUG_SAY(("WOLJoinGame: Connect to server\n"));
// Start the client
unsigned short my_port = FirewallHelper.Get_Client_Bind_Port();
cNetwork::Init_Client(my_port);
// Display the "connecting" dialog.
// Note: This dialog will close automatically when the connection has been
// successfully completed.
DlgMPConnect::DoDialog(mTeamChoice, mClanID);
// Our job is done. (This will delete the WOLJoinGame object)
Release_Ref();
}
/******************************************************************************
*
* NAME
* WOLJoinGame::HandleNotification(ChannelEvent)
*
* DESCRIPTION
* Handle channel events. Of particular interest during a join is the
* channel data event. This event tells us that there is information
* available from the channel encoded in the topic and exinfo fields that
* we can use to create the game from.
*
* INPUTS
* ChannelEvent
*
* RESULT
* NONE
*
******************************************************************************/
void WOLJoinGame::HandleNotification(ChannelEvent& event)
{
// The channel data is always updated immediately after a channel is joined.
// Therefore use this event to start the creation of the game we are joining.
if (event.GetStatus() == ChannelNewData)
{
// Get the channel that is the subject of this event.
const RefPtr<ChannelData>& channel = event.Subject();
WWASSERT(channel.IsValid());
// If the name of this channel is the name of the game we are joining
// then create the game from this channel.
const WideStringClass& channelName = channel->GetName();
if (channelName.Compare_No_Case(mGameName) == 0)
{
WWDEBUG_SAY(("WOLJoinGame: Joined game channel '%S'\n", (const WCHAR*)channelName));
// Keep a reference to the channel so we can create the game from it latter
mTheChannel = channel;
}
}
}
/******************************************************************************
*
* NAME
* WOLJoinGame::HandleNotification(DlgWOLWaitEvent)
*
* DESCRIPTION
* Handle result of channel join and firewall negotiation. If everything
* went okay then proceed with connecting to the game server. Otherwise
* tell the user what went wrong.
*
* INPUTS
* Event - Result event from joining WOL game wait condition.
*
* RESULT
* NONE
*
******************************************************************************/
void WOLJoinGame::HandleNotification(DlgWOLWaitEvent& event)
{
// If the wait condition completed with success.
if (event.Result() == WaitCondition::ConditionMet)
{
if (JOINING_STATE == mJoinState)
{
mJoinState = IDLE_STATE;
// If we just joined the channel we need to present the user with
// the team selection dialog. This dialog will allow them to view
// the current teams and / or change their team.
if (mAllowTeamSelect)
{
// DlgMPTeamSelect will send a signal indicating if the user has opted
// to continue with the game or to back out. See ReceiveSignal()
DlgMPTeamSelect::DoDialog(*this);
}
else
{
ProceedWithConnection(-1);
}
}
else if (FIREWALL_STATE == mJoinState)
{
// If we have finished the firewall negotiation then proceed with
// the server connection.
mJoinState = IDLE_STATE;
ConnectToServer();
}
}
else
{
// If the wait condition failed then report the reason for the failure and
// leave the channel.
const WideStringClass& text = event.Subject()->GetResultText();
WWDEBUG_SAY(("WOLJoinGame: Wait failed - %S\n", (const WCHAR*)text));
DlgMsgBox::DoDialog(TRANSLATE(IDS_WOL_ERROR), text);
Leave();
}
}
/******************************************************************************
*
* NAME
* WOLJoinGame::ReceiveSignal(MPChooseTeamSignal)
*
* DESCRIPTION
* The team selection dialog will send a signal indicating the users choice
* regarding his team preference.
*
* INPUTS
* Signal
*
* RESULT
* NONE
*
******************************************************************************/
void WOLJoinGame::ReceiveSignal(MPChooseTeamSignal& signal)
{
// If the user wants to proceed then connect to the server othewise leave
// the game channel.
if (signal.GetItemA() == true)
{
ProceedWithConnection(signal.GetItemB());
}
else
{
Leave();
}
}

104
Code/Commando/WOLJoinGame.h Normal file
View File

@@ -0,0 +1,104 @@
/*
** 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/>.
*/
/******************************************************************************
*
* FILE
* $Archive: /Commando/Code/Commando/WOLJoinGame.h $
*
* DESCRIPTION
*
* PROGRAMMER
* $Author: Denzil_l $
*
* VERSION INFO
* $Revision: 10 $
* $Modtime: 1/16/02 4:25p $
*
******************************************************************************/
#ifndef __WOLJOINGAME_H__
#define __WOLJOINGAME_H__
#include <WWLib\RefCount.h>
#include <WWLib\Notify.h>
#include <WWLib\Signaler.h>
#include <WWLib\WideString.h>
#include <WWOnline\RefPtr.h>
#include "DlgMPTeamSelect.h"
namespace WWOnline
{
class Session;
class ChannelData;
class ChannelEvent;
}
class cGameData;
class DlgWOLWaitEvent;
class WOLJoinGame :
public RefCountClass,
public Observer<WWOnline::ChannelEvent>,
public Observer<DlgWOLWaitEvent>,
public Signaler<MPChooseTeamSignal>
{
public:
static void JoinTheGame(const wchar_t* gameName, const wchar_t* password, bool allowTeamSelect);
protected:
WOLJoinGame();
~WOLJoinGame();
// Prevent copy and assignment
WOLJoinGame(const WOLJoinGame&);
const WOLJoinGame& operator=(const WOLJoinGame&);
bool FinalizeCreate(void);
cGameData* CreateGameFromChannel(const RefPtr<WWOnline::ChannelData>& channel);
bool Join(const wchar_t* gameName, const wchar_t* password, bool allowTeamSelect);
void ProceedWithConnection(int teamChoice);
void Leave(void);
bool StartServerConnect(void);
void ConnectToServer(void);
void HandleNotification(WWOnline::ChannelEvent&);
void HandleNotification(DlgWOLWaitEvent&);
void ReceiveSignal(MPChooseTeamSignal&);
private:
RefPtr<WWOnline::Session> mWOLSession;
typedef enum {IDLE_STATE = 0, JOINING_STATE, FIREWALL_STATE} JoinState;
JoinState mJoinState;
bool mAllowTeamSelect;
WideStringClass mGameName;
WideStringClass mPassword;
RefPtr<WWOnline::ChannelData> mTheChannel;
int mTeamChoice;
unsigned long mClanID;
};
#endif __WOLJOINGAME_H__

View File

@@ -0,0 +1,814 @@
/*
** 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/>.
*/
/******************************************************************************
*
* FILE
* $Archive: /Commando/Code/Commando/WOLLoginProfile.cpp $
*
* DESCRIPTION
* Login profile holds the users login preferences as well as other
* information that needs to be persistantly cached between game sessions.
*
* PROGRAMMER
* Denzil E. Long, Jr.
* $Author: Greg_h $
*
* VERSION INFO
* $Revision: 14 $
* $Modtime: 6/21/02 11:40a $
*
******************************************************************************/
#include "WOLLoginProfile.h"
#include "_globals.h"
#include "Resource.h"
#include <WWOnline\WOLLoginInfo.h>
#include <WWUI\DialogBase.h>
#include <WWUI\ListCtrl.h>
#include <WWLib\Registry.h>
#include "String_IDs.h"
#include <WWTranslateDB\TranslateDB.h>
#include <stdio.h>
using namespace WWOnline;
#define MAX_STRING_LEN 64;
static const char* REG_VALUE_SERVER = "Server";
static const char* REG_VALUE_SIDEPREF = "SidePref";
static const char* REG_VALUE_GAMESPLAYED = "Played";
static const char* REG_VALUE_TEAMRANK = "RankTeam";
static const char* REG_VALUE_CLANRANK = "RankClan";
// Profile ranking columns
static enum
{
COL_LADDERNAME = 0,
COL_WINS,
COL_DEATHS,
COL_POINTS,
COL_RANK,
COL_MAXCOUNT
};
static void ShowRanking(ListCtrlClass* list, LadderType type, const LoginProfile::Ranking* rank);
bool LoginProfile::_mSaveAllowed = true;
LoginProfile* LoginProfile::_mCurrentProfile = NULL;
/******************************************************************************
*
* NAME
* LoginProfile::EnableSaving
*
* DESCRIPTION
*
* INPUTS
*
* RESULT
* NONE
*
******************************************************************************/
void LoginProfile::EnableSaving(bool allowed)
{
_mSaveAllowed = allowed;
}
/******************************************************************************
*
* NAME
* LoginProfile::SetCurrent
*
* DESCRIPTION
*
* INPUTS
*
* RESULT
* NONE
*
******************************************************************************/
void LoginProfile::SetCurrent(LoginProfile* profile)
{
if (_mCurrentProfile != NULL)
{
_mCurrentProfile->Release_Ref();
_mCurrentProfile = NULL;
}
if (profile)
{
profile->Add_Ref();
_mCurrentProfile = profile;
}
}
/******************************************************************************
*
* NAME
* LoginProfile::Get
*
* DESCRIPTION
* Get the login profile for the specified user.
*
* INPUTS
* Name - Name of profile to get.
*
* RESULT
* Profile - Instance to login profile
*
******************************************************************************/
LoginProfile* LoginProfile::Get(const wchar_t* loginName, bool createOK)
{
if (loginName && wcslen(loginName))
{
// Check the current profile first
if (_mCurrentProfile)
{
if (wcsicmp(_mCurrentProfile->GetName(), loginName) == 0)
{
_mCurrentProfile->Add_Ref();
return _mCurrentProfile;
}
}
StringClass regKey(255, true);
regKey.Format("%s\\%S", APPLICATION_SUB_KEY_NAME_LOGINS, loginName);
if (RegistryClass::Exists(regKey) || createOK)
{
return Create(loginName);
}
}
return NULL;
}
/******************************************************************************
*
* NAME
* LoginProfile::Create
*
* DESCRIPTION
* Create an instance of a login profile.
*
* INPUTS
* Login - Login to create profile for.
*
* RESULT
* Profile - Instance to login profile
*
******************************************************************************/
LoginProfile* LoginProfile::Create(const wchar_t* loginName)
{
LoginProfile* profile = NULL;
if (loginName && wcslen(loginName))
{
profile = new LoginProfile;
if (profile)
{
if (profile->FinalizeCreate(loginName) == false)
{
profile->Release_Ref();
profile = NULL;
}
}
}
return profile;
}
/******************************************************************************
*
* NAME
* LoginProfile::Delete
*
* DESCRIPTION
* Delete a login profile.
*
* INPUTS
* Name - Name of login profile to delete.
*
* RESULT
* NONE
*
******************************************************************************/
void LoginProfile::Delete(const wchar_t* loginName)
{
if (loginName && wcslen(loginName))
{
RegistryClass registry(APPLICATION_SUB_KEY_NAME_LOGINS, false);
if (registry.Is_Valid())
{
char valueName[64];
wcstombs(valueName, loginName, sizeof(valueName));
registry.Delete_Value(valueName);
}
}
}
/******************************************************************************
*
* NAME
* LoginProfile::LoginProfile
*
* DESCRIPTION
* Constructor
*
* INPUTS
* NONE
*
* RESULT
* NONE
*
******************************************************************************/
LoginProfile::LoginProfile() :
mLocale(WOL::LOC_UNKNOWN),
mSidePref(-1),
mGamesPlayed(0)
{
memset(&mTeamRank, 0, sizeof(Ranking));
memset(&mClanRank, 0, sizeof(Ranking));
}
/******************************************************************************
*
* NAME
* LoginProfile::~LoginProfile
*
* DESCRIPTION
* Destructor
*
* INPUTS
* NONE
*
* RESULT
* NONE
*
******************************************************************************/
LoginProfile::~LoginProfile()
{
WWDEBUG_SAY(("LoginProfile destroyed (%S)\n", (const WCHAR*)mName));
}
/******************************************************************************
*
* NAME
* LoginProfile::FinalizeCreate
*
* DESCRIPTION
* Finalize object creation
*
* INPUTS
* Login - Login to initialize profile with.
*
* RESULT
* True if successfull
*
******************************************************************************/
bool LoginProfile::FinalizeCreate(const wchar_t* loginName)
{
WWDEBUG_SAY(("LoginProfile created %S\n", loginName));
mName = loginName;
LoadSettings();
return true;
}
/******************************************************************************
*
* NAME
* LoginProfile::GetName
*
* DESCRIPTION
* Get the name of this profile
*
* INPUTS
* NONE
*
* RESULT
* Name of profile
*
******************************************************************************/
const wchar_t* LoginProfile::GetName(void) const
{
return mName;
}
/******************************************************************************
*
* NAME
* LoginProfile::SetPreferredServer
*
* DESCRIPTION
* Set the preferred server for this login.
*
* INPUTS
* Server - Name of preferred server.
*
* RESULT
* NONE
*
******************************************************************************/
void LoginProfile::SetPreferredServer(const char* name)
{
mServer = name;
}
/******************************************************************************
*
* NAME
* LoginProfile::SetSidePreference
*
* DESCRIPTION
* Set the side preference
*
* INPUTS
* Side - Prefered side
*
* RESULT
* NONE
*
******************************************************************************/
void LoginProfile::SetSidePreference(int side)
{
mSidePref = side;
}
/******************************************************************************
*
* NAME
* LoginProfile::SetGamesPlayed
*
* DESCRIPTION
* Set the number of games played for this login.
*
* INPUTS
* Played - Number of games played.
*
* RESULT
* NONE
*
******************************************************************************/
void LoginProfile::SetGamesPlayed(unsigned long played)
{
mGamesPlayed = played;
}
/******************************************************************************
*
* NAME
* LoginProfile::SetLocale
*
* DESCRIPTION
* Set locale for this profile
*
* INPUTS
* Locale - New locale
*
* RESULT
* NONE
*
******************************************************************************/
void LoginProfile::SetLocale(WOL::Locale locale)
{
mLocale = max<WOL::Locale>(locale, WOL::LOC_UNKNOWN);
}
/******************************************************************************
*
* NAME
* LoginProfile::GetRanking
*
* DESCRIPTION
* Get ladder ranking information.
*
* INPUTS
* Ladder - Type of ladder to get ranking information for.
*
* RESULT
* Rank - Ladder ranking data
*
******************************************************************************/
const LoginProfile::Ranking* LoginProfile::GetRanking(LadderType type) const
{
if (type == LadderType_Team)
{
return &mTeamRank;
}
else if (type == LadderType_Clan)
{
return &mClanRank;
}
return NULL;
}
/******************************************************************************
*
* NAME
* LoginProfile::SetRanking
*
* DESCRIPTION
* Set ladder ranking information
*
* INPUTS
* Ladder - Type of ladder to set ranking for.
* Rank - Ranking data
*
* RESULT
* NONE
*
******************************************************************************/
void LoginProfile::SetRanking(WWOnline::LadderType type, Ranking& rank)
{
if (type == LadderType_Team)
{
memcpy(&mTeamRank, &rank, sizeof(Ranking));
}
else if (type == LadderType_Clan)
{
memcpy(&mClanRank, &rank, sizeof(Ranking));
}
}
/******************************************************************************
*
* NAME
* LoginProfile::LoadSettings
*
* DESCRIPTION
* Load cached profile settings.
*
* INPUTS
* NONE
*
* RESULT
* NONE
*
******************************************************************************/
void LoginProfile::LoadSettings(void)
{
// Get this logins locale
mLocale = WOL::LOC_UNKNOWN;
RefPtr<LoginInfo> login = LoginInfo::Find(GetName());
if (login.IsValid())
{
mLocale = login->GetLocale();
}
// Get login preferences
StringClass regKey(255, true);
regKey.Format("%s\\%S", APPLICATION_SUB_KEY_NAME_LOGINS, GetName());
RegistryClass registry(regKey, false);
if (registry.Is_Valid())
{
registry.Get_String(REG_VALUE_SERVER, mServer, "");
mSidePref = registry.Get_Int(REG_VALUE_SIDEPREF, -1);
mGamesPlayed = registry.Get_Int(REG_VALUE_GAMESPLAYED, 0);
}
LoadRank(REG_VALUE_TEAMRANK, mTeamRank);
LoadRank(REG_VALUE_CLANRANK, mClanRank);
}
/******************************************************************************
*
* NAME
* LoginProfile::SaveSettings
*
* DESCRIPTION
* Save current profile settings.
*
* INPUTS
* NONE
*
* RESULT
* NONE
*
******************************************************************************/
void LoginProfile::SaveSettings(void)
{
bool isStored = true;
RefPtr<LoginInfo> login = LoginInfo::Find(GetName());
if (login.IsValid())
{
isStored = login->IsStored();
// Save locale
login->SetLocale((WOL::Locale)mLocale);
}
// If we are allowed to
if (_mSaveAllowed && isStored)
{
// Save login preferences
StringClass regKey(255, true);
regKey.Format("%s\\%S", APPLICATION_SUB_KEY_NAME_LOGINS, GetName());
RegistryClass registry(regKey);
if (registry.Is_Valid())
{
registry.Set_String(REG_VALUE_SERVER, mServer);
registry.Set_Int(REG_VALUE_SIDEPREF, mSidePref);
registry.Set_Int(REG_VALUE_GAMESPLAYED, mGamesPlayed);
}
SaveRank(REG_VALUE_TEAMRANK, mTeamRank);
SaveRank(REG_VALUE_CLANRANK, mClanRank);
}
}
/******************************************************************************
*
* NAME
* LoginProfile::LoadRank
*
* DESCRIPTION
* Load cached ranking data.
*
* INPUTS
* Key - Registry key to load ranking from.
* Rank - Ranking data to initialize.
*
* RESULT
* NONE
*
******************************************************************************/
void LoginProfile::LoadRank(const char* valueName, LoginProfile::Ranking& rank)
{
WWASSERT(valueName);
StringClass regKey(255, true);
regKey.Format("%s\\%S", APPLICATION_SUB_KEY_NAME_LOGINS, GetName());
RegistryClass registry(regKey, false);
if (registry.Is_Valid())
{
char rankData[255];
registry.Get_String(valueName, rankData, sizeof(rankData), "");
sscanf(rankData, "%d,%d,%d,%d,%d,%d", &rank.Wins, &rank.Losses,
&rank.Deaths, &rank.Kills, &rank.Points, &rank.Rank);
}
else
{
rank.Wins = (unsigned)-1;
rank.Losses = (unsigned)-1;
rank.Deaths = (unsigned)-1;
rank.Kills = (unsigned)-1;
rank.Points = (unsigned)-1;
rank.Rank = (unsigned)-1;
}
}
/******************************************************************************
*
* NAME
* LoginProfile::SaveRank
*
* DESCRIPTION
* Save current ranking data.
*
* INPUTS
* Key - Registry key to save ranking data to.
* Rank - Ranking data to save.
*
* RESULT
* NONE
*
******************************************************************************/
void LoginProfile::SaveRank(const char* valueName, const LoginProfile::Ranking& rank)
{
WWASSERT(valueName);
StringClass regKey(255, true);
regKey.Format("%s\\%S", APPLICATION_SUB_KEY_NAME_LOGINS, GetName());
RegistryClass registry(regKey);
if (registry.Is_Valid())
{
char rankData[255];
sprintf(rankData, "%d,%d,%d,%d,%d,%d", rank.Wins, rank.Losses, rank.Deaths,
rank.Kills, rank.Points, rank.Rank);
registry.Set_String(valueName, rankData);
}
}
/******************************************************************************
*
* NAME
* ShowProfileRanking
*
* DESCRIPTION
*
* INPUTS
* Dialog - Dialog to display ranking on. (Must have neccessary controls)
* Profile - Profile to display
*
* RESULT
* NONE
*
******************************************************************************/
void ShowProfileRanking(DialogBaseClass* dialog, const LoginProfile* profile)
{
dialog->Set_Dlg_Item_Text(IDC_PROFILENAME, L"");
ListCtrlClass* list = (ListCtrlClass*)dialog->Get_Dlg_Item(IDC_PROFILERANK);
if (list)
{
list->Allow_Selection(false);
list->Delete_All_Entries();
if (list->Get_Column_Count() != COL_MAXCOUNT)
{
list->Delete_All_Columns();
// Configure the columns
Vector3 color(1, 1, 1);
list->Add_Column(TRANSLATE(IDS_MENU_RANKING), 0.2F, color);
list->Add_Column(TRANSLATE(IDS_MENU_WINS_LOSSES), 0.2F, color);
list->Add_Column(TRANSLATE(IDS_BUDDY_COL_DEATHS_KILLS), 0.2F, color);
list->Add_Column(TRANSLATE(IDS_BUDDY_COL_POINTS), 0.2F, color);
list->Add_Column(TRANSLATE(IDS_BUDDY_COL_RANK), 0.2F, color);
}
//(gth) Renegade day 120 Patch: re-translate these strings each time!
struct {const wchar_t* name; WWOnline::LadderType type;} _ladders[] =
{
{TRANSLATE(IDS_MENU_INDIVIDUAL), WWOnline::LadderType_Team},
{TRANSLATE(IDS_MENU_CLAN), WWOnline::LadderType_Clan}
};
// Initialize with unknown data
for (int index = 0; index < 2; ++index)
{
int item = list->Insert_Entry(index, _ladders[index].name);
if (item != -1)
{
list->Set_Entry_Data(item, COL_LADDERNAME, _ladders[index].type);
list->Set_Entry_Text(item, COL_WINS, L"- / -");
list->Set_Entry_Text(item, COL_DEATHS, L"- / -");
list->Set_Entry_Text(item, COL_POINTS, L"-");
list->Set_Entry_Text(item, COL_RANK, L"-");
}
}
// Show the profile's ranking
if (profile)
{
WideStringClass profileName(128, true);
profileName.Format(TRANSLATE(IDS_MENU_RANKING_PROFILE), profile->GetName());
dialog->Set_Dlg_Item_Text(IDC_PROFILENAME, profileName);
ShowRanking(list, WWOnline::LadderType_Team, profile->GetRanking(WWOnline::LadderType_Team));
ShowRanking(list, WWOnline::LadderType_Clan, profile->GetRanking(WWOnline::LadderType_Clan));
}
}
}
/******************************************************************************
*
* NAME
* ShowRanking
*
* DESCRIPTION
*
* INPUTS
* List - List control to show ranking in
* Type - Type of ladder
* Rank - Ladder ranking data
*
* RESULT
* NONE
*
******************************************************************************/
void ShowRanking(ListCtrlClass* list, WWOnline::LadderType type, const LoginProfile::Ranking* rank)
{
WWASSERT(list != NULL);
WWASSERT(rank != NULL);
int count = list->Get_Entry_Count();
for (int index = 0; index < count; index++)
{
if ((WWOnline::LadderType)list->Get_Entry_Data(index, COL_LADDERNAME) == type)
{
WideStringClass text(64, true);
if (rank->Wins != (unsigned)-1)
{
text.Format(L"%u / %u", rank->Wins, rank->Losses);
list->Set_Entry_Text(index, COL_WINS, text);
}
else
{
list->Set_Entry_Text(index, COL_WINS, L"- / -");
}
if ((rank->Deaths != (unsigned)-1) && (rank->Kills != (unsigned)-1))
{
text.Format(L"%u / %u", rank->Deaths, rank->Kills);
list->Set_Entry_Text(index, COL_DEATHS, text);
}
else
{
list->Set_Entry_Text(index, COL_DEATHS, L"- / -");
}
if (rank->Points != (unsigned)-1)
{
text.Format(L"%u", rank->Points);
list->Set_Entry_Text(index, COL_POINTS, text);
}
else
{
list->Set_Entry_Text(index, COL_POINTS, L"-");
}
if (rank->Rank != (unsigned)-1)
{
text.Format(L"%u", rank->Rank);
list->Set_Entry_Text(index, COL_RANK, text);
}
else
{
list->Set_Entry_Text(index, COL_RANK, L"-");
}
break;
}
}
}

View File

@@ -0,0 +1,134 @@
/*
** 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/>.
*/
/******************************************************************************
*
* FILE
* $Archive: /Commando/Code/Commando/WOLLoginProfile.h $
*
* DESCRIPTION
*
* PROGRAMMER
* Denzil E. Long, Jr.
* $Author: Denzil_l $
*
* VERSION INFO
* $Revision: 7 $
* $Modtime: 1/19/02 2:23p $
*
******************************************************************************/
#ifndef __WOLLOGINPROFILE_H__
#define __WOLLOGINPROFILE_H__
#include <WWLib\RefCount.h>
#include <WWLib\WWString.h>
#include <WWLib\WideString.h>
#include <WWOnline\WOLLadder.h>
class LoginProfile :
public RefCountClass
{
public:
struct Ranking
{
unsigned int Wins;
unsigned int Losses;
unsigned int Deaths;
unsigned int Kills;
unsigned int Points;
unsigned int Rank;
};
static void EnableSaving(bool);
static void SetCurrent(LoginProfile*);
// Get the profile for the specified login.
static LoginProfile* Get(const wchar_t* loginName, bool createOK = false);
// Create a login profile.
static LoginProfile* Create(const wchar_t* loginName);
// Delete the profile.
static void Delete(const wchar_t* loginName);
// Get login name
const wchar_t* GetName(void) const;
// Set the preferred game server
void SetPreferredServer(const char* name);
// Get the preferred game server
const char* GetPreferredServer(void) const
{return (const char*)mServer;}
void SetLocale(WOL::Locale locale);
WOL::Locale GetLocale(void) const
{return mLocale;}
// Set the side preference
void SetSidePreference(int side);
int GetSidePreference(void) const
{return mSidePref;}
void SetGamesPlayed(unsigned long);
unsigned long GetGamesPlayed(void) const
{return mGamesPlayed;}
// Get cached ranking
const Ranking* GetRanking(WWOnline::LadderType type) const;
void SetRanking(WWOnline::LadderType type, Ranking& rank);
// Load profile settings
void LoadSettings(void);
// Save profile settings
void SaveSettings(void);
protected:
LoginProfile();
virtual ~LoginProfile();
bool FinalizeCreate(const wchar_t* loginName);
void LoadRank(const char* valueName, Ranking& rank);
void SaveRank(const char* valueName, const Ranking& rank);
private:
static bool _mSaveAllowed;
static LoginProfile* _mCurrentProfile;
WideStringClass mName;
StringClass mServer;
WOL::Locale mLocale;
int mSidePref;
unsigned long mGamesPlayed;
Ranking mTeamRank;
Ranking mClanRank;
};
class DialogBaseClass;
void ShowProfileRanking(DialogBaseClass* dialog, const LoginProfile* profile);
#endif // __WOLLOGINPROFILE_H__

File diff suppressed because it is too large Load Diff

129
Code/Commando/WOLLogonMgr.h Normal file
View File

@@ -0,0 +1,129 @@
/*
** 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/>.
*/
/******************************************************************************
*
* FILE
* $Archive: /Commando/Code/Commando/WOLLogonMgr.h $
*
* DESCRIPTION
*
* PROGRAMMER
* Denzil E. Long, Jr.
* $Author: Denzil_l $
*
* VERSION INFO
* $Revision: 25 $
* $Modtime: 1/14/02 2:04p $
*
******************************************************************************/
#ifndef __WOLLOGONMGR_H__
#define __WOLLOGONMGR_H__
#include "DlgWOLLogon.h"
#include <WWLib\RefCount.h>
#include <WWLib\Notify.h>
#include <WWOnline\RefPtr.h>
#include <WWOnline\WOLSession.h>
class DlgWOLWaitEvent;
class DlgMsgBoxEvent;
typedef enum
{
WOLLOGON_FAILED = 0,
WOLLOGON_SUCCESS,
WOLLOGON_CANCEL,
WOLLOGON_PATCHREQUIRED
} WOLLogonAction;
class WOLLogonMgr :
public RefCountClass,
public Notifier<WOLLogonAction>,
public Observer<DlgWOLLogonEvent>,
public Observer<DlgWOLWaitEvent>,
public Observer<DlgMsgBoxEvent>,
public Observer<WWOnline::ServerError>,
public Observer<WWOnline::ConnectionStatus>,
public Observer<WWOnline::MessageOfTheDayEvent>
{
public:
// Log onto Westwood Online
static void Logon(Observer<WOLLogonAction>* observer);
// Log the current user off of Westwood Online.
static void Logoff(void);
// Get the name of the logged in user.
static bool GetLoginName(WideStringClass& name);
// Get the name of the server logged onto.
static bool GetServerName(WideStringClass& name);
static RefPtr<WWOnline::IRCServerData> GetDefaultServer(void);
static void ConfigureSession(void);
static void Set_Quiet_Mode(bool mode) {mQuietMode = mode;}
protected:
typedef enum {DISCONNECTED = 0, DETECTING_BANDWIDTH, FETCHING_SERVERLIST, WAITING_PINGS, WAITING_BANDWIDTH_DIALOG_OKAY, CONNECTING, CONNECTED} LogonState;
WOLLogonMgr();
~WOLLogonMgr();
WOLLogonMgr(const WOLLogonMgr&);
const WOLLogonMgr& operator=(const WOLLogonMgr&);
RefPtr<WWOnline::IRCServerData> GetPreferredServer(const wchar_t* loginname);
// Check if the user is connected to a server.
bool IsConnectedToServer(const wchar_t* loginname, RefPtr<WWOnline::IRCServerData>& server);
bool IsUserLoggedIn(const wchar_t* loginname);
bool IsAutoLogin(const wchar_t* loginname);
bool HasServerList(void);
bool HasValidPings(void);
void InitiateLogon(bool forced);
void RememberLogin(void);
DECLARE_NOTIFIER(WOLLogonAction)
void HandleNotification(DlgWOLLogonEvent&);
void HandleNotification(DlgWOLWaitEvent&);
void HandleNotification(DlgMsgBoxEvent&);
void HandleNotification(WWOnline::ServerError&);
void HandleNotification(WWOnline::ConnectionStatus&);
void HandleNotification(WWOnline::MessageOfTheDayEvent&);
private:
static bool mQuietMode;
RefPtr<WWOnline::Session> mWOLSession;
LogonState mState;
WideStringClass mLoginName;
WideStringClass mPassword;
bool mPasswordEncrypted;
bool mRememberLogin;
};
#endif // __WOLLOGONMGR_H__

View File

@@ -0,0 +1,610 @@
/*
** 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/>.
*/
/******************************************************************************
*
* FILE
* $Archive: /Commando/Code/Commando/WOLQuickMatch.cpp $
*
* DESCRIPTION
*
* PROGRAMMER
* $Author: Denzil_l $
*
* VERSION INFO
* $Revision: 37 $
* $Modtime: 2/20/02 5:30p $
*
******************************************************************************/
#include "WOLQuickMatch.h"
#include <WWOnline\PingProfile.h>
#include <WWOnline\WaitCondition.h>
#include <WWOnline\WOLProduct.h>
#include <WWOnline\WOLConnect.h>
#include <WWOnline\WOLServer.h>
#include <WWOnline\WOLLadder.h>
#include <WWLib\CPUDetect.h>
#include <WWDebug\WWDebug.h>
#include "cnetwork.h"
#include "translatedb.h"
#include "string_ids.h"
using namespace WWOnline;
typedef void (*QMDispatchFunc)(WOLQuickMatch*, const wchar_t*);
struct QMResponseDispatch
{
const wchar_t* Token;
QMDispatchFunc Dispatch;
};
#define QUICKMATCH_CHANNELNAME L"lob_39_0"
#define QUICKMATCH_BOTNAME L"matchbot"
/******************************************************************************
*
* NAME
* WOLQuickMatch::Create
*
* DESCRIPTION
* Create an instance to a quickmatch game matcher.
*
* INPUTS
* NONE
*
* RESULT
* Quickmatch - Quickmatch instance.
*
******************************************************************************/
WOLQuickMatch* WOLQuickMatch::Create(void)
{
WOLQuickMatch* match = new WOLQuickMatch;
if (match)
{
if (match->FinalizeCreate())
{
return match;
}
match->Release_Ref();
}
return NULL;
}
/******************************************************************************
*
* NAME
* WOLQuickMatch::WOLQuickMatch
*
* DESCRIPTION
* Default constructor
*
* INPUTS
* NONE
*
* RESULT
* NONE
*
******************************************************************************/
WOLQuickMatch::WOLQuickMatch()
{
WWDEBUG_SAY(("WOLQuickMatch: Instantiating\n"));
}
/******************************************************************************
*
* NAME
* WOLQuickMatch::~WOLQuickMatch
*
* DESCRIPTION
* Destructor
*
* INPUTS
* NONE
*
* RESULT
* NONE
*
******************************************************************************/
WOLQuickMatch::~WOLQuickMatch()
{
WWDEBUG_SAY(("WOLQuickMatch: Destructing\n"));
}
/******************************************************************************
*
* NAME
* WOLQuickMatch::FinalizeCreate
*
* DESCRIPTION
* Creation initializaton / finalization
*
* INPUTS
* NONE
*
* RESULT
* Success - True if successful
*
******************************************************************************/
bool WOLQuickMatch::FinalizeCreate(void)
{
mWOLSession = Session::GetInstance(false);
if (!mWOLSession.IsValid())
{
WWDEBUG_SAY(("WOLQuickMatch: ERROR - WWOnline not instantiated\n"));
return false;
}
return true;
}
/******************************************************************************
*
* NAME
* WOLQuickMatch::ConnectClient
*
* DESCRIPTION
* Connect a game client to the quickmatch bot.
*
* INPUTS
* ChannelName - Name of matching channel
* BotName - Name of matching bot
*
* RESULT
* Wait - Wait condition to process.
*
******************************************************************************/
RefPtr<WaitCondition> WOLQuickMatch::ConnectClient(void)
{
WWDEBUG_SAY(("WOLQuickMatch: Connecting client to '%S' '%S'\n",
QUICKMATCH_CHANNELNAME, QUICKMATCH_BOTNAME));
// Make sure that we are logged on to WWOnline
if (mWOLSession->GetConnectionStatus() != ConnectionConnected)
{
WWDEBUG_SAY(("WOLQuickMatch: ERROR - Not connected to WWOnline server\n"));
RefPtr<SingleWait> wait = SingleWait::Create(TRANSLATE(IDS_WOL_CONNECTING));
wait->EndWait(WaitCondition::Error, TRANSLATE(IDS_WOL_NOTCONNECTED));
return wait;
}
// Generate client connect wait condition
RefPtr<SerialWait> connectWait = SerialWait::Create();
if (connectWait.IsValid())
{
Observer<ServerError>::NotifyMe(*mWOLSession);
Observer<ChatMessage>::NotifyMe(*mWOLSession);
// Request channel list
RefPtr<WaitCondition> channelListWait = mWOLSession->GetNewChatChannelList();
connectWait->Add(channelListWait);
// Join the matching channel
RefPtr<Product> product = Product::Current();
WWASSERT(product.IsValid() && "WOLProduct not initialized.");
const wchar_t* password = product->GetChannelPassword();
RefPtr<WaitCondition> joinWait = mWOLSession->JoinChannel(QUICKMATCH_CHANNELNAME, password, 0);
connectWait->Add(joinWait);
// Make sure the matching bot is there.
RefPtr<WaitCondition> findBotWait = GetUserWait::Create(mWOLSession, QUICKMATCH_BOTNAME);
connectWait->Add(findBotWait);
}
return connectWait;
}
/******************************************************************************
*
* NAME
* WOLQuickMatch::Disconnect
*
* DESCRIPTION
* Disconnect from quickmatch
*
* INPUTS
* NONE
*
* RESULT
* Wait - Disconnect wait condition to process.
*
******************************************************************************/
RefPtr<WaitCondition> WOLQuickMatch::Disconnect(void)
{
WWDEBUG_SAY(("WOLQuickMatch: Disconnecting\n"));
Observer<ServerError>::StopObserving();
Observer<ChatMessage>::StopObserving();
// If we are in the matching channel then disconnect.
RefPtr<ChannelData> channel = mWOLSession->GetCurrentChannel();
if (channel.IsValid())
{
const WideStringClass& name = channel->GetName();
if (name.Compare_No_Case(QUICKMATCH_CHANNELNAME) == 0)
{
return mWOLSession->LeaveChannel();
}
}
return NULL;
}
/******************************************************************************
*
* NAME
* WOLQuickMatch::SendClientInfo
*
* DESCRIPTION
* Send client matching preferences to the quickmatch bot.
*
* INPUTS
* NONE
*
* RESULT
* True if successful.
*
******************************************************************************/
bool WOLQuickMatch::SendClientInfo(void)
{
unsigned long ver = cNetwork::Get_Exe_Key();
// Get CPU speed
int speed = CPUDetectClass::Get_Processor_Speed();
// Get amount of physical memory
MEMORYSTATUS memStatus;
GlobalMemoryStatus(&memStatus);
unsigned long memory = (memStatus.dwTotalPhys / 1048576);
//-------------------------------------------------------------------------
// Gather pings
//-------------------------------------------------------------------------
const PingProfile& pings = GetLocalPingProfile();
char pseudoPings[18] = {0};
EncodePingProfile(pings, pseudoPings);
//-------------------------------------------------------------------------
// Get clients ladder points
//-------------------------------------------------------------------------
RefPtr<UserData> client = mWOLSession->GetCurrentUser();
WWASSERT(client.IsValid());
if (client.IsValid() == false)
{
return false;
}
int tpoints = 0;
unsigned int played = 0;
RefPtr<LadderData> ladder = client->GetTeamLadder();
if (ladder.IsValid())
{
tpoints = ladder->GetPoints();
played = ladder->GetReserved2();
}
//-------------------------------------------------------------------------
// Generate client information message
//-------------------------------------------------------------------------
WideStringClass clientMsg(256, true);
clientMsg.Format(L"CINFO VER=%lu CPU=%lu MEM=%lu TPOINTS=%ld PLAYED=%lu PINGS=%S",
ver, speed, memory, tpoints, played, pseudoPings);
WWDEBUG_SAY(("WOLQuickMatch: '%S'\n", (const WCHAR*)clientMsg));
return mWOLSession->SendPrivateMessage(QUICKMATCH_BOTNAME, (const WCHAR*)clientMsg);
}
/******************************************************************************
*
* NAME
* WOLQuickMatch::SendServerInfo
*
* DESCRIPTION
* Send information describing the game,
*
* INPUTS
*
* RESULT
* NONE
*
******************************************************************************/
void WOLQuickMatch::SendServerInfo(const char* exInfo, const char* topic)
{
if (exInfo && topic)
{
#pragma message(__FILE__" *** HACK ALERT *** SINFO msg is imitating WOLAPI IRC topic!")
// *** WARNING *** DANGER *** HACK ALERT ****
//
// The SINFO message sent to the matching bot is assembled in such
// a way as to imitate the IRC topic string that WOLAPI produces.
WideStringClass botMsg(0, true);
botMsg.Format(L"SINFO %S%S", exInfo, topic);
WWDEBUG_SAY(("WOLQuickMatch: '%S'\n", (const WCHAR*)botMsg));
mWOLSession->SendPrivateMessage(QUICKMATCH_BOTNAME, botMsg);
}
}
/******************************************************************************
*
* NAME
* WOLQuickMatch::SendStatus
*
* DESCRIPTION
*
* INPUTS
*
* RESULT
* NONE
*
******************************************************************************/
void WOLQuickMatch::SendStatus(const wchar_t* statusMsg)
{
WWDEBUG_SAY(("WOLQuickMatch: Status '%S'\n", statusMsg));
WideStringClass msg(256, true);
msg = statusMsg;
QuickMatchEvent status(QuickMatchEvent::QMMSG, msg);
NotifyObservers(status);
}
/******************************************************************************
*
* NAME
* WOLQuickMatch::ParseResponse
*
* DESCRIPTION
* Handle response messages from the quickmatch bot.
*
* INPUTS
* Message - Response message from quickmatch bot.
*
* RESULT
* NONE
*
******************************************************************************/
void WOLQuickMatch::ParseResponse(const wchar_t* message)
{
if (message)
{
static QMResponseDispatch _dispatch[] =
{
{L"INFO ", WOLQuickMatch::ProcessInfo},
{L"ERROR ", WOLQuickMatch::ProcessError},
{L"START ", WOLQuickMatch::ProcessStart},
{NULL, WOLQuickMatch::ProcessUnknown}
};
int index = 0;
const wchar_t* token = _dispatch[index].Token;
while (token)
{
// Find the first occurance of the token in the message
wchar_t* cmd = wcsstr(message, token);
// If the token was found and it is at the start of the message
// then return the type of message this is.
if (cmd && cmd == message)
{
const wchar_t* data = (message + wcslen(token));
_dispatch[index].Dispatch(this, data);
}
index++;
token = _dispatch[index].Token;
}
}
}
/******************************************************************************
*
* NAME
* WOLQuickMatch::ProcessInfo
*
* DESCRIPTION
* Process information messages.
*
* INPUTS
* Message -
*
* RESULT
* NONE
*
******************************************************************************/
void WOLQuickMatch::ProcessInfo(WOLQuickMatch* quickmatch, const wchar_t* data)
{
WideStringClass msg(255, true);
msg = data;
QuickMatchEvent status(QuickMatchEvent::QMINFO, msg);
quickmatch->NotifyObservers(status);
}
/******************************************************************************
*
* NAME
* WOLQuickMatch::ProcessError
*
* DESCRIPTION
* Process error messages from the quickmatch bot.
*
* INPUTS
* Message - Error message
*
* RESULT
* NONE
*
******************************************************************************/
void WOLQuickMatch::ProcessError(WOLQuickMatch* quickmatch, const wchar_t* data)
{
WideStringClass msg(255, true);
msg = data;
QuickMatchEvent status(QuickMatchEvent::QMERROR, msg);
quickmatch->NotifyObservers(status);
}
/******************************************************************************
*
* NAME
* WOLQuickMatch::ProcessStart
*
* DESCRIPTION
* Process start message from the quickmatch bot.
*
* INPUTS
* Data - Start game parameters
*
* RESULT
* NONE
*
******************************************************************************/
void WOLQuickMatch::ProcessStart(WOLQuickMatch* quickmatch, const wchar_t* data)
{
// Send message indicating successful match
WideStringClass msg(255, true);
msg.Format(TRANSLATE(IDS_MENU_QM_MATCHED_WITH), data);
QuickMatchEvent status(QuickMatchEvent::QMMSG, msg);
quickmatch->NotifyObservers(status);
// Send message that we are matched.
msg = data;
QuickMatchEvent matchedEvent(QuickMatchEvent::QMMATCHED, msg);
quickmatch->NotifyObservers(matchedEvent);
}
/******************************************************************************
*
* NAME
* WOLQuickMatch::ProcessUnknown
*
* DESCRIPTION
* Process unknown messages from the quickmatch bot.
*
* INPUTS
* Message - Unknown message
*
* RESULT
* NONE
*
******************************************************************************/
void WOLQuickMatch::ProcessUnknown(WOLQuickMatch* quickmatch, const wchar_t* data)
{
WideStringClass msg(255, true);
msg = data;
QuickMatchEvent status(QuickMatchEvent::QMUNKNOWN, msg);
quickmatch->NotifyObservers(status);
}
/******************************************************************************
*
* NAME
* WOLQuickMatch::HandleNotification(ServerError)
*
* DESCRIPTION
* Handle server errors.
*
* INPUTS
* Error - Server error
*
* RESULT
* NONE
*
******************************************************************************/
void WOLQuickMatch::HandleNotification(ServerError& error)
{
const wchar_t* errorMsg = error.GetDescription();
WWDEBUG_SAY(("WOLQuickMatch: ERROR - ServerError '%S'\n", errorMsg));
QuickMatchEvent status(QuickMatchEvent::QMERROR, errorMsg);
NotifyObservers(status);
}
/******************************************************************************
*
* NAME
* WOLQuickMatch::HandleNotification(ChatMessageEvent)
*
* DESCRIPTION
* Handle private messages coming from the matchbot.
*
* INPUTS
* Message - Chat message
*
* RESULT
* NONE
*
******************************************************************************/
void WOLQuickMatch::HandleNotification(ChatMessage& message)
{
const WideStringClass& sender = message.GetSendersName();
if (sender.Compare_No_Case(QUICKMATCH_BOTNAME) == 0)
{
WWDEBUG_SAY(("WOLQuickMatch: BotMsg - '%S'\n", message.GetMessage()));
ParseResponse(message.GetMessage());
}
}

View File

@@ -0,0 +1,113 @@
/*
** 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/>.
*/
/******************************************************************************
*
* FILE
* $Archive: /Commando/Code/Commando/WOLQuickMatch.h $
*
* DESCRIPTION
*
* PROGRAMMER
* Denzil E. Long, Jr.
* $Author: Denzil_l $
*
* VERSION INFO
* $Revision: 18 $
* $Modtime: 2/20/02 5:07p $
*
******************************************************************************/
#ifndef __WOLQUICKMATCH_H__
#define __WOLQUICKMATCH_H__
#include <WWLib\RefCount.h>
#include <WWOnline\RefPtr.h>
#include <WWOnline\WOLSession.h>
#include <WWLib\Notify.h>
class WaitCondition;
class DlgWOLWaitEvent;
class QuickMatchEvent :
public TypedEvent<QuickMatchEvent, const WideStringClass>
{
public:
enum Event {QMERROR = 0, QMINFO, QMMSG, QMMATCHED, QMUNKNOWN};
Event GetEvent(void) const
{return mEvent;}
QuickMatchEvent(Event event, const WideStringClass& msg) :
TypedEvent<QuickMatchEvent, const WideStringClass>(msg),
mEvent(event)
{}
~QuickMatchEvent()
{}
private:
Event mEvent;
};
class WOLQuickMatch :
public RefCountClass,
public Notifier<QuickMatchEvent>,
public Observer<WWOnline::ServerError>,
public Observer<WWOnline::ChatMessage>
{
public:
static WOLQuickMatch* Create(void);
RefPtr<WaitCondition> ConnectClient(void);
RefPtr<WaitCondition> Disconnect(void);
bool SendClientInfo(void);
void SendServerInfo(const char* exInfo, const char* topic);
DECLARE_NOTIFIER(QuickMatchEvent)
protected:
WOLQuickMatch();
~WOLQuickMatch();
bool FinalizeCreate(void);
void SendStatus(const wchar_t* statusMsg);
void ParseResponse(const wchar_t* message);
void HandleNotification(WWOnline::ServerError&);
void HandleNotification(WWOnline::ChatMessage&);
private:
// Prevent copy and assignment
WOLQuickMatch(const WOLQuickMatch&);
const WOLQuickMatch& operator=(const WOLQuickMatch&);
static void ProcessInfo(WOLQuickMatch*, const wchar_t*);
static void ProcessError(WOLQuickMatch*, const wchar_t*);
static void ProcessStart(WOLQuickMatch*, const wchar_t*);
static void ProcessUnknown(WOLQuickMatch*, const wchar_t*);
protected:
RefPtr<WWOnline::Session> mWOLSession;
};
#endif // __WOLQUICKMATCH_H__

1150
Code/Commando/WebBrowser.cpp Normal file

File diff suppressed because it is too large Load Diff

177
Code/Commando/WebBrowser.h Normal file
View File

@@ -0,0 +1,177 @@
/*
** 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/>.
*/
/******************************************************************************
*
* NAME
* $Archive: /Commando/Code/Commando/WebBrowser.h $
*
* DESCRIPTION
* Web Browser
*
* PROGRAMMER
* Denzil E. Long, Jr.
* $Author: Denzil_l $
*
* VERSION INFO
* $Revision: 7 $
* $Modtime: 1/15/02 3:06p $
*
******************************************************************************/
#ifndef __WEBBROWSER_H__
#define __WEBBROWSER_H__
#include "WOLBrowser\WOLBrowser.h"
#include <WWLib\Notify.h>
#include <atlbase.h>
#include <windows.h>
class WebBrowser;
class WebEvent :
public TypedEventPtr<WebEvent, WebBrowser>
{
public:
typedef enum
{
None = 0, // NULL event
Quit, // User initiated quit
CertificationFailed, // Requested page failed certification.
} EventID;
//! Retrieve event
inline EventID Event(void) const
{return mEvent;}
WebEvent(EventID event, WebBrowser* object) :
TypedEventPtr<WebEvent, WebBrowser>(object),
mEvent(event)
{}
protected:
// Prevent copy and assignment
WebEvent(const WebEvent&);
const WebEvent& operator=(const WebEvent&);
private:
EventID mEvent;
};
class WebBrowser :
public IWOLBrowserEvent,
public Notifier<WebEvent>
{
public:
// Initialize browser prerequisites.
// NOTE: This is for development purpose only; The game installer should handle
// these tasks.
#ifdef _DEBUG
static bool InstallPrerequisites(void);
#endif
//! Test if a web page is currently displayed
static bool IsWebPageDisplayed(void);
//! Create an instance of the embedded browser for Dune Emperor.
static WebBrowser* CreateInstance(HWND window);
//! Check if browser is embedded or external (True if embedded)
bool UsingEmbeddedBrowser(void) const
{return (mWOLBrowser != NULL);}
//! Test if the external browser is running
bool IsExternalBrowserRunning(void) const;
//! Display the specified web content.
bool ShowWebPage(char* page);
//! Launch the external browser
bool LaunchExternal(const char* url);
//! Show the browser
void Show(void);
//! Hide the browser
void Hide(void);
//! Test if the browser is visible
bool IsVisible(void) const
{return mVisible;}
protected:
// Protected to prevent direct construction via new, use CreateInstance() instead.
WebBrowser();
virtual ~WebBrowser();
// Protected to prevent copy and assignment
WebBrowser(const WebBrowser&);
const WebBrowser& operator=(const WebBrowser&);
bool FinalizeCreate(HWND window);
bool RetrievePageURL(const char* page, char* url, int size);
bool RetrieveHTMLPath(char* path, int size);
DECLARE_NOTIFIER(WebEvent)
private:
static WebBrowser* _mInstance;
ULONG mRefCount;
CComPtr<IWOLBrowser> mWOLBrowser;
wchar_t mPendingURL[512];
bool mVisible;
PROCESS_INFORMATION mProcessInfo;
bool mSwitchedMode;
int mRestoreWidth;
int mRestoreHeight;
int mRestoreBits;
//---------------------------------------------------------------------------
// IUnknown methods
//---------------------------------------------------------------------------
public:
HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void** ppvObject);
ULONG STDMETHODCALLTYPE AddRef(void);
ULONG STDMETHODCALLTYPE Release(void);
//---------------------------------------------------------------------------
// IWOLBrowserEvent methods
//---------------------------------------------------------------------------
private:
STDMETHOD(OnScriptQuit)(void);
STDMETHOD(OnBeforeNavigate)(const wchar_t* url, const wchar_t* targetFrame);
STDMETHOD(OnDocumentComplete)(const wchar_t* url, BOOL topFrame);
STDMETHOD(OnDownloadBegin)(void);
STDMETHOD(OnProgressChange)(LONG progress, LONG progressMax);
STDMETHOD(OnDownloadComplete)(void);
STDMETHOD(OnNavigateComplete)(const wchar_t* url);
STDMETHOD(OnStatusTextChange)(const wchar_t* statusText);
STDMETHOD(OnTitleChange)(const wchar_t* title);
STDMETHOD(OnNewWindow)(void);
STDMETHOD(OnShowMessage)(const wchar_t* text, const wchar_t* caption, ULONG type, LONG* result);
STDMETHOD(OnFailedPageCertification)(void);
STDMETHOD(OnErrorMsg)(const wchar_t* error);
STDMETHOD(OnRegisterLogin)(const wchar_t* nick, const wchar_t* pass);
};
#endif // __WEBBROWSER_H__

107
Code/Commando/_globals.h Normal file
View File

@@ -0,0 +1,107 @@
/*
** 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/_globals.h $*
* *
* $Author:: Bhayes $*
* *
* $Modtime:: 3/06/02 5:36p $*
* *
* $Revision:: 25 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#ifndef _GLOBALS_H
#define _GLOBALS_H
#include "specialbuilds.h"
/*
#ifdef FREEDEDICATEDSERVER
#define APP_SUB_KEY "Software\\Westwood\\RenegadeFDS"
#else //FREEDEDICATEDSERVER
#ifdef MULTIPLAYERDEMO
#define APP_SUB_KEY "Software\\Westwood\\RenegadeMPDemo"
#else // MULTIPLAYERDEMO
#define APP_SUB_KEY "Software\\Westwood\\Renegade"
#endif //MULTIPLAYERDEMO
#endif //FREEDEDICATEDSERVER
*/
#if defined(FREEDEDICATEDSERVER)
#define APP_SUB_KEY "Software\\Westwood\\RenegadeFDS"
#elif defined(MULTIPLAYERDEMO)
#define APP_SUB_KEY "Software\\Westwood\\RenegadeMPDemo"
#elif defined(BETACLIENT)
#define APP_SUB_KEY "Software\\Westwood\\RenegadeBeta"
#elif defined(BETASERVER)
#define APP_SUB_KEY "Software\\Westwood\\RenegadeBeta"
#else
#define APP_SUB_KEY "Software\\Westwood\\Renegade"
#endif
extern char *Build_Registry_Location_String(char *base, char *modifier, char *sub);
#define APPLICATION_SUB_KEY_NAME Build_Registry_Location_String(APP_SUB_KEY, NULL, "")
#define APPLICATION_SUB_KEY_NAME_RENDER Build_Registry_Location_String(APP_SUB_KEY, NULL, "Render")
#define APPLICATION_SUB_KEY_NAME_OPTIONS Build_Registry_Location_String(APP_SUB_KEY, NULL, "Options")
#define APPLICATION_SUB_KEY_NAME_DEBUG Build_Registry_Location_String(APP_SUB_KEY, NULL, "Debug")
#define APPLICATION_SUB_KEY_NAME_SYSTEM_SETTINGS Build_Registry_Location_String(APP_SUB_KEY, NULL, "System Settings")
#define APPLICATION_SUB_KEY_NAME_CONTROLS Build_Registry_Location_String(APP_SUB_KEY, NULL, "Controls")
#define APPLICATION_SUB_KEY_NAME_SOUND Build_Registry_Location_String(APP_SUB_KEY, NULL, "Sound")
#define APPLICATION_SUB_KEY_NAME_MOVIES Build_Registry_Location_String(APP_SUB_KEY, NULL, "Movies")
#define APPLICATION_SUB_KEY_NAME_WOLSETTINGS Build_Registry_Location_String(APP_SUB_KEY, NULL, "WOLSettings")
#define APPLICATION_SUB_KEY_NAME_MISSION_RANKS Build_Registry_Location_String(APP_SUB_KEY, NULL, "Ranks")
#define APPLICATION_SUB_KEY_NAME_INPUT Build_Registry_Location_String(APP_SUB_KEY, NULL, "Input")
#define APPLICATION_SUB_KEY_NAME_GAMESPY Build_Registry_Location_String(APP_SUB_KEY, NULL, "GameSpy")
#define APPLICATION_SUB_KEY_NAME_WOLSETTINGS Build_Registry_Location_String(APP_SUB_KEY, NULL, "WOLSettings")
#define APPLICATION_SUB_KEY_NAME_URL Build_Registry_Location_String(APP_SUB_KEY, NULL, "WOLSettings\\URL")
#define APPLICATION_SUB_KEY_NAME_LOGINS Build_Registry_Location_String(APP_SUB_KEY, NULL, "WOLSettings\\Logins")
#define APPLICATION_SUB_KEY_NAME_QUICKMATCH Build_Registry_Location_String(APP_SUB_KEY, NULL, "WOLSettings\\QuickMatch")
#define APPLICATION_SUB_KEY_NAME_IGNORE_LIST Build_Registry_Location_String(APP_SUB_KEY, NULL, "WOLSettings\\Ignore List")
#define APPLICATION_SUB_KEY_NAME_SERVER_LIST Build_Registry_Location_String(APP_SUB_KEY, NULL, "WOLSettings\\Servers")
#define APPLICATION_SUB_KEY_NAME_SKIN_LIST Build_Registry_Location_String(APP_SUB_KEY, NULL, "MP Settings\\Skins")
#define APPLICATION_SUB_KEY_NAME_NETOPTIONS Build_Registry_Location_String(APP_SUB_KEY, NULL, "Networking\\Options")
#define APPLICATION_SUB_KEY_NAME_NETDEBUG Build_Registry_Location_String(APP_SUB_KEY, NULL, "Networking\\Debug")
#define APPLICATION_SUB_KEY_NAME_NET_FIREWALL Build_Registry_Location_String(APP_SUB_KEY, NULL, "Networking\\Firewall")
#define APPLICATION_SUB_KEY_NAME_NET_SLAVE Build_Registry_Location_String(APP_SUB_KEY, NULL, "Networking\\Slave")
#define APPLICATION_SUB_KEY_NAME_NET_SERVER_CONTROL Build_Registry_Location_String(APP_SUB_KEY, NULL, "Networking\\ServerControl")
#define COMBAT_SUB_KEY_NAME_DEBUG Build_Registry_Location_String(APP_SUB_KEY, NULL, "Debug")
#define APPLICATION_SUB_KEY_NAME_BANDTEST Build_Registry_Location_String(APP_SUB_KEY, NULL, "Bandtest")
#define RENEGADE_BASE_SKU 3072
#define RENEGADE_FDS_SKU 12288
#define RENEGADE_DEMO_SKU 13056
#endif

View File

@@ -0,0 +1,456 @@
/*
** 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/apppacketstats.cpp $*
* *
* $Author:: Tom_s $*
* *
* $Modtime:: 2/21/02 3:01p $*
* *
* $Revision:: 24 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include "apppacketstats.h"
#include <memory.h>
#include <string.h>
#include "wwdebug.h"
#include "mathutil.h"
#include "networkobjectmgr.h"
#include "wwprofile.h"
//
// Class statics
//
DWORD cAppPacketStats::PacketsSent[];
DWORD cAppPacketStats::BitsSent[];
DWORD cAppPacketStats::BitsSentTier[][PACKET_TIER_COUNT];
DWORD cAppPacketStats::ObjectTally[];
StringClass cAppPacketStats::WorkingString;
//-----------------------------------------------------------------------------
void
cAppPacketStats::Reset
(
void
)
{
::memset(&PacketsSent, 0, sizeof(PacketsSent));
::memset(&BitsSent, 0, sizeof(BitsSent));
::memset(&BitsSentTier, 0, sizeof(BitsSentTier));
::memset(&ObjectTally, 0, sizeof(ObjectTally));
}
//-----------------------------------------------------------------------------
void
cAppPacketStats::Dump_Diagnostics
(
void
)
{
WWDEBUG_SAY(("\n"));
WWDEBUG_SAY(("---------------------------------------------------------\n"));
WWDEBUG_SAY(("cAppPacketStats::Dump_Diagnostics:\n"));
WWDEBUG_SAY(("%s\n", Get_Heading()));
for (BYTE i = 0; i < APPPACKETTYPE_COUNT; i++)
{
WWDEBUG_SAY(("%s\n", Get_Description(i)));
}
WWDEBUG_SAY(("\n"));
WWDEBUG_SAY(("---------------------------------------------------------\n"));
}
//-----------------------------------------------------------------------------
void
cAppPacketStats::Increment_Packets_Sent
(
BYTE app_packet_type
)
{
WWASSERT(app_packet_type != APPPACKETTYPE_ALL && app_packet_type < APPPACKETTYPE_COUNT);
PacketsSent[app_packet_type]++;
PacketsSent[APPPACKETTYPE_ALL]++;
}
//-----------------------------------------------------------------------------
void
cAppPacketStats::Increment_Bits_Sent
(
BYTE app_packet_type,
DWORD bits
)
{
WWASSERT(app_packet_type != APPPACKETTYPE_ALL && app_packet_type < APPPACKETTYPE_COUNT);
WWASSERT(bits >= 0);
BitsSent[app_packet_type] += bits;
BitsSent[APPPACKETTYPE_ALL] += bits;
}
//-----------------------------------------------------------------------------
void
cAppPacketStats::Increment_Bits_Sent_Tier
(
BYTE app_packet_type,
PACKET_TIER_ENUM tier,
DWORD bits
)
{
WWASSERT(app_packet_type != APPPACKETTYPE_ALL && app_packet_type < APPPACKETTYPE_COUNT);
WWASSERT(bits >= 0);
BitsSentTier[app_packet_type][tier] += bits;
BitsSentTier[APPPACKETTYPE_ALL][tier] += bits;
}
//-----------------------------------------------------------------------------
DWORD
cAppPacketStats::Get_Packets_Sent
(
BYTE app_packet_type
)
{
WWASSERT(app_packet_type < APPPACKETTYPE_COUNT);
return PacketsSent[app_packet_type];
}
//-----------------------------------------------------------------------------
DWORD
cAppPacketStats::Get_Bits_Sent
(
BYTE app_packet_type
)
{
WWASSERT(app_packet_type < APPPACKETTYPE_COUNT);
return BitsSent[app_packet_type];
}
//-----------------------------------------------------------------------------
DWORD
cAppPacketStats::Get_Bits_Sent_Tier
(
BYTE app_packet_type,
PACKET_TIER_ENUM tier
)
{
WWASSERT(app_packet_type < APPPACKETTYPE_COUNT);
return BitsSentTier[app_packet_type][tier];
}
//-----------------------------------------------------------------------------
#define ADD_CASE(exp) case exp: return #exp;
LPCSTR
cAppPacketStats::Interpret_Type
(
BYTE app_packet_type
)
{
switch (app_packet_type)
{
//
// S->S
//
ADD_CASE(APPPACKETTYPE_UNKNOWN);
ADD_CASE(APPPACKETTYPE_SIMPLE);
ADD_CASE(APPPACKETTYPE_SOLDIER);
ADD_CASE(APPPACKETTYPE_VEHICLE);
ADD_CASE(APPPACKETTYPE_TURRET);
ADD_CASE(APPPACKETTYPE_BUILDING);
ADD_CASE(APPPACKETTYPE_PLAYER);
ADD_CASE(APPPACKETTYPE_TEAM);
ADD_CASE(APPPACKETTYPE_GAMEOPTIONSEVENT);
ADD_CASE(APPPACKETTYPE_PLAYERKILLEVENT);
ADD_CASE(APPPACKETTYPE_PURCHASERESPONSEEVENT);
ADD_CASE(APPPACKETTYPE_SCTEXTOBJ);
ADD_CASE(APPPACKETTYPE_SVRGOODBYEEVENT);
ADD_CASE(APPPACKETTYPE_WINEVENT);
ADD_CASE(APPPACKETTYPE_POWERUP);
ADD_CASE(APPPACKETTYPE_STATIC);
ADD_CASE(APPPACKETTYPE_DOOR);
ADD_CASE(APPPACKETTYPE_ELEVATOR);
ADD_CASE(APPPACKETTYPE_DSAPO);
ADD_CASE(APPPACKETTYPE_SERVERFPS);
ADD_CASE(APPPACKETTYPE_CONSOLECOMMANDEVENT);
ADD_CASE(APPPACKETTYPE_RESETWINSEVENT);
ADD_CASE(APPPACKETTYPE_EVICTIONEVENT);
ADD_CASE(APPPACKETTYPE_NETWEATHER);
ADD_CASE(APPPACKETTYPE_GAMEDATAUPDATEEVENT);
ADD_CASE(APPPACKETTYPE_SCPINGRESPONSEEVENT);
ADD_CASE(APPPACKETTYPE_BASECONTROLLER);
ADD_CASE(APPPACKETTYPE_CINEMATIC);
ADD_CASE(APPPACKETTYPE_C4);
ADD_CASE(APPPACKETTYPE_BEACON);
ADD_CASE(APPPACKETTYPE_SCEXPLOSIONEVENT);
ADD_CASE(APPPACKETTYPE_SCOBELISKEVENT);
ADD_CASE(APPPACKETTYPE_SCANNOUNCEMENT);
ADD_CASE(APPPACKETTYPE_NETBACKGROUND);
ADD_CASE(APPPACKETTYPE_GAMESPYSCCHALLENGEEVENT);
//
// C->S
//
ADD_CASE(APPPACKETTYPE_CLIENTCONTROL);
ADD_CASE(APPPACKETTYPE_CSTEXTOBJ);
ADD_CASE(APPPACKETTYPE_SUICIDEEVENT);
ADD_CASE(APPPACKETTYPE_CHANGETEAMEVENT);
ADD_CASE(APPPACKETTYPE_MONEYEVENT);
ADD_CASE(APPPACKETTYPE_WARPEVENT);
ADD_CASE(APPPACKETTYPE_PURCHASEREQUESTEVENT);
ADD_CASE(APPPACKETTYPE_CLIENTGOODBYEEVENT);
ADD_CASE(APPPACKETTYPE_BIOEVENT);
ADD_CASE(APPPACKETTYPE_LOADINGEVENT);
ADD_CASE(APPPACKETTYPE_GODMODEEVENT);
ADD_CASE(APPPACKETTYPE_VIPMODEEVENT);
ADD_CASE(APPPACKETTYPE_SCOREEVENT);
ADD_CASE(APPPACKETTYPE_CLIENTBBOEVENT);
ADD_CASE(APPPACKETTYPE_CLIENTFPS);
ADD_CASE(APPPACKETTYPE_CSPINGREQUESTEVENT);
ADD_CASE(APPPACKETTYPE_CSDAMAGEEVENT);
ADD_CASE(APPPACKETTYPE_REQUESTKILLEVENT);
ADD_CASE(APPPACKETTYPE_CSCONSOLECOMMANDEVENT);
ADD_CASE(APPPACKETTYPE_CSHINT);
ADD_CASE(APPPACKETTYPE_CSANNOUNCEMENT);
ADD_CASE(APPPACKETTYPE_DONATEEVENT);
ADD_CASE(APPPACKETTYPE_GAMESPYCSCHALLENGERESPONSEEVENT);
//
// Summation
//
ADD_CASE(APPPACKETTYPE_ALL);
default:
break;
}
return "ERROR";
DIE;
}
//-----------------------------------------------------------------------------
void
cAppPacketStats::Update_Object_Tally
(
void
)
{
::memset(&ObjectTally, 0, sizeof(ObjectTally));
int count = NetworkObjectMgrClass::Get_Object_Count();
for (int index = 0; index < count; index ++)
{
NetworkObjectClass * p_object = NetworkObjectMgrClass::Get_Object(index);
if (p_object != NULL)
{
BYTE type = p_object->Get_App_Packet_Type();
WWASSERT(type < APPPACKETTYPE_ALL);
ObjectTally[type]++;
ObjectTally[APPPACKETTYPE_ALL]++;
/*
if (type == APPPACKETTYPE_UNKNOWN)
{
WWDEBUG_SAY(("WTF is this?\n"));
}
*/
}
}
}
//-----------------------------------------------------------------------------
DWORD
cAppPacketStats::Get_Object_Tally
(
BYTE app_packet_type
)
{
WWASSERT(app_packet_type < APPPACKETTYPE_COUNT);
return ObjectTally[app_packet_type];
}
//-----------------------------------------------------------------------------
StringClass &
cAppPacketStats::Get_Heading
(
void
)
{
//StringClass description;
WorkingString.Format(
"%-30s %-8s %-10s %-10s %-7s %-7s %-7s %-7s %-7s %-7s",
"Type",
"Tally",
"Packets",
"Bytes",
"PC",
"Avg.",
"PC TC",
"PC TR",
"PC TO",
"PC TF"
);
return WorkingString;
}
//-----------------------------------------------------------------------------
StringClass &
cAppPacketStats::Get_Description
(
BYTE type
)
{
WWASSERT(type < APPPACKETTYPE_COUNT);
float num_bytes = BitsSent[type] / 8.0f;
DWORD average_bytes = 0;
if (PacketsSent[type] > 0)
{
average_bytes = cMathUtil::Round(num_bytes / (float) PacketsSent[type]);
}
float percentage = 0;
if (BitsSent[APPPACKETTYPE_ALL] > 0)
{
percentage = 100 * (BitsSent[type] / (float) BitsSent[APPPACKETTYPE_ALL]);
}
//
// Strip the leading "APPPACKETTYPE_"
//
WWASSERT(::strlen(Interpret_Type(type)) > 14);
char name[200] = "";
::strcpy(name, &Interpret_Type(type)[14]);
//
// Tier percentages
//
DWORD t0 = 0;
DWORD t1 = 0;
DWORD t2 = 0;
DWORD t3 = 0;
if (BitsSent[type] > 0)
{
float bits = BitsSent[type];
t0 = cMathUtil::Round(100 * (BitsSentTier[type][0] / bits));
t1 = cMathUtil::Round(100 * (BitsSentTier[type][1] / bits));
t2 = cMathUtil::Round(100 * (BitsSentTier[type][2] / bits));
t3 = cMathUtil::Round(100 * (BitsSentTier[type][3] / bits));
}
//StringClass description;
WorkingString.Format(
"%-30s %-8d %-10d %-10d %-7.1f %-7d %-7d %-7d %-7d %-7d",
name,
ObjectTally[type],
PacketsSent[type],
cMathUtil::Round(num_bytes),
percentage,
average_bytes,
t0,
t1,
t2,
t3
);
/**/
//
// Replace all solo zero's with a space.
//
char last = ' ';
char next = ' ';
char * p = WorkingString.Peek_Buffer();
for (int i = 0; i < WorkingString.Get_Length(); i++)
{
if (i == 0)
{
last = ' ';
}
else
{
last = p[i - 1];
}
if (i == WorkingString.Get_Length() - 1)
{
next = ' ';
}
else
{
next = p[i + 1];
}
if (last == ' ' && next == ' ' && p[i] == '0')
{
p[i] = ' ';
}
}
/**/
return WorkingString;
}
//ADD_CASE(APPPACKETTYPE_FLAGCAPEVENT);
//ADD_CASE(APPPACKETTYPE_STEALTHEVENT);

View File

@@ -0,0 +1,80 @@
/*
** 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/apppacketstats.h $*
* *
* $Author:: Tom_s $*
* *
* $Modtime:: 10/15/01 4:18p $*
* *
* $Revision:: 5 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#ifndef __APPPACKETSTATS_H__
#define __APPPACKETSTATS_H__
#include "bittype.h"
#include "apppackettypes.h"
#include "networkobject.h"
//-----------------------------------------------------------------------------
//
// Record and report app packet stats
//
class cAppPacketStats
{
public:
static void Reset(void);
static void Dump_Diagnostics(void);
static LPCSTR Interpret_Type(BYTE app_packet_type);
static void Update_Object_Tally(void);
static void Increment_Packets_Sent(BYTE app_packet_type);
static void Increment_Bits_Sent(BYTE app_packet_type, DWORD bits);
static void Increment_Bits_Sent_Tier(BYTE app_packet_type, PACKET_TIER_ENUM tier, DWORD bits);
static DWORD Get_Packets_Sent(BYTE app_packet_type);
static DWORD Get_Bits_Sent(BYTE app_packet_type);
static DWORD Get_Bits_Sent_Tier(BYTE app_packet_type, PACKET_TIER_ENUM tier);
static DWORD Get_Object_Tally(BYTE app_packet_type);
static StringClass & Get_Heading(void);
static StringClass & Get_Description(BYTE app_packet_type);
private:
static DWORD PacketsSent[APPPACKETTYPE_COUNT];
static DWORD BitsSent[APPPACKETTYPE_COUNT];
static DWORD BitsSentTier[APPPACKETTYPE_COUNT][PACKET_TIER_COUNT];
static DWORD ObjectTally[APPPACKETTYPE_COUNT];
static StringClass WorkingString;
};
//-----------------------------------------------------------------------------
#endif // __APPPACKETSTATS_H__

148
Code/Commando/bandwidth.cpp Normal file
View File

@@ -0,0 +1,148 @@
/*
** 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/bandwidth.cpp $*
* *
* $Author:: Bhayes $*
* *
* $Modtime:: 2/18/02 9:22p $*
* *
* $Revision:: 17 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include "bandwidth.h" // I WANNA BE FIRST!
#include "miscutil.h"
#include "wwdebug.h"
#include "translatedb.h"
#include "string_ids.h"
#include "useroptions.h"
#include "bandwidthcheck.h"
//-----------------------------------------------------------------------------
ULONG cBandwidth::Get_Bandwidth_Bps_From_Type(BANDWIDTH_TYPE_ENUM bandwidth_type)
{
/*
WWASSERT(bandwidth_type >= BANDWIDTH_FIRST &&
bandwidth_type <= BANDWIDTH_LAST);
*/
// WWASSERT(bandwidth_type != BANDWIDTH_CUSTOM);
switch (bandwidth_type) {
case BANDWIDTH_CUSTOM:
return cUserOptions::BandwidthBps.Get();
case BANDWIDTH_MODEM_288:
return 28800;
case BANDWIDTH_MODEM_336:
return 33600;
case BANDWIDTH_MODEM_56:
return 56000;
case BANDWIDTH_ISDN:
return 64000;
case BANDWIDTH_CABLE:
return 128000;
case BANDWIDTH_LANT1:
return 2000000;
case BANDWIDTH_AUTO:
{
ULONG bps = BandwidthCheckerClass::Get_Upstream_Bandwidth();
// WWASSERT(bps > 0);
return bps;
}
default:
DIE;
return 0xffffffff; // to avoid compiler warning
}
}
//-----------------------------------------------------------------------------
const unsigned short *cBandwidth::Get_Bandwidth_String_From_Type(BANDWIDTH_TYPE_ENUM bandwidth_type)
{
static char _bandwidth_auto_txt[128];
static WideStringClass s;
/*
WWASSERT(bandwidth_type >= BANDWIDTH_FIRST &&
bandwidth_type <= BANDWIDTH_LAST);
*/
switch (bandwidth_type) {
case BANDWIDTH_MODEM_288:
return TRANSLATE(IDS_MP_CONNECTION_288); //"BANDWIDTH_MODEM_288";
case BANDWIDTH_MODEM_336:
return TRANSLATE(IDS_MP_CONNECTION_336); //"BANDWIDTH_MODEM_336";
case BANDWIDTH_MODEM_56:
return TRANSLATE(IDS_MP_CONNECTION_56); //"BANDWIDTH_MODEM_56";
case BANDWIDTH_ISDN:
return TRANSLATE(IDS_MP_CONNECTION_ISDN); //"BANDWIDTH_ISDN";
case BANDWIDTH_CABLE:
return TRANSLATE(IDS_MP_CONNECTION_CABLE); //"BANDWIDTH_CABLE";
case BANDWIDTH_LANT1:
return TRANSLATE(IDS_MP_CONNECTION_T1); //"BANDWIDTH_LANT1";
case BANDWIDTH_CUSTOM:
return L"BANDWIDTH_CUSTOM";
case BANDWIDTH_AUTO:
{
//sprintf(_bandwidth_auto_txt, "BANDWIDTH_AUTO (%s)", BandwidthCheckerClass::Get_Bandwidth_As_String());
s.Format(TRANSLATE(IDS_MP_CONNECTION_T1), Get_Bandwidth_Bps_From_Type(bandwidth_type));
//wsprintf(_bandwidth_auto_txt, TRANSLATE(IDS_MP_CONNECTION_T1), Get_Bandwidth_Bps_From_Type(bandwidth_type));
//return ((const)_bandwidth_auto_txt);
return(s);
}
default:
DIE;
return L"ERROR"; // to avoid compiler warning
}
}
//-----------------------------------------------------------------------------
BANDWIDTH_TYPE_ENUM cBandwidth::Get_Bandwidth_Type_From_String(LPCSTR bandwidth_string)
{
WWASSERT(bandwidth_string != NULL);
if (cMiscUtil::Is_String_Same(bandwidth_string, "BANDWIDTH_MODEM_288")) {
return BANDWIDTH_MODEM_288;
} else if (cMiscUtil::Is_String_Same(bandwidth_string, "BANDWIDTH_MODEM_336")) {
return BANDWIDTH_MODEM_336;
} else if (cMiscUtil::Is_String_Same(bandwidth_string, "BANDWIDTH_MODEM_56")) {
return BANDWIDTH_MODEM_56;
} else if (cMiscUtil::Is_String_Same(bandwidth_string, "BANDWIDTH_ISDN")) {
return BANDWIDTH_ISDN;
} else if (cMiscUtil::Is_String_Same(bandwidth_string, "BANDWIDTH_CABLE")) {
return BANDWIDTH_CABLE;
} else if (cMiscUtil::Is_String_Same(bandwidth_string, "BANDWIDTH_LANT1")) {
return BANDWIDTH_LANT1;
} else if (cMiscUtil::Is_String_Same(bandwidth_string, "BANDWIDTH_CUSTOM")) {
return BANDWIDTH_CUSTOM;
} else if (strnicmp(bandwidth_string, "BANDWIDTH_AUTO ", 15) == 0) {
return BANDWIDTH_AUTO;
} else {
DIE;
return BANDWIDTH_CUSTOM; // to avoid compiler warning
}
}

75
Code/Commando/bandwidth.h Normal file
View File

@@ -0,0 +1,75 @@
/*
** 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/bandwidth.h $*
* *
* $Author:: Steve_t $*
* *
* $Modtime:: 12/17/01 12:30p $*
* *
* $Revision:: 6 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#if defined(_MSV_VER)
#pragma once
#endif
#ifndef BANDWIDTH_H
#define BANDWIDTH_H
#include "bittype.h"
enum BANDWIDTH_TYPE_ENUM {
BANDWIDTH_FIRST = 100,
BANDWIDTH_MODEM_288 = BANDWIDTH_FIRST,
BANDWIDTH_MODEM_336,
BANDWIDTH_MODEM_56,
BANDWIDTH_ISDN,
BANDWIDTH_CABLE,
BANDWIDTH_LANT1,
BANDWIDTH_AUTO,
BANDWIDTH_CUSTOM,
BANDWIDTH_LAST = BANDWIDTH_CUSTOM
};
//
//
//
class cBandwidth {
public:
cBandwidth(void);
~cBandwidth(void) {};
static ULONG Get_Bandwidth_Bps_From_Type(BANDWIDTH_TYPE_ENUM bandwidth_type);
static const unsigned short * Get_Bandwidth_String_From_Type(BANDWIDTH_TYPE_ENUM bandwidth_type);
static BANDWIDTH_TYPE_ENUM Get_Bandwidth_Type_From_String(LPCSTR bandwidth_string);
};
#endif // BANDWIDTH_H

View File

@@ -0,0 +1,979 @@
/*
** 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/>.
*/
/***********************************************************************************************
*** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : Command & Conquer *
* *
* $Archive:: /Commando/Code/Commando/bandwidthcheck.cpp $*
* *
* $Author:: Bhayes $*
* *
* $Modtime:: 3/06/02 11:48a $*
* *
* $Revision:: 25 $*
* *
* *
*---------------------------------------------------------------------------------------------*
* *
* *
*---------------------------------------------------------------------------------------------*
* *
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
/*
** Disable warning about exception handling not being enabled.
*/
#pragma warning(disable : 4530)
#include "always.h"
#include <windows.h>
#include "systimer.h"
#include <stddef.h>
#include "bandwidthcheck.h"
#include "autostart.h"
#include "registry.h"
#include "_globals.h"
#include "useroptions.h"
#include "translatedb.h"
#include "string_ids.h"
#include "consolemode.h"
#include "specialbuilds.h"
#include "gamespyadmin.h"
#include <WWOnline\WOLSession.h>
/*
** Class statics.
*/
BandwidthCheckerClass::BandwidthCheckerThreadClass BandwidthCheckerClass::Thread;
HANDLE BandwidthCheckerClass::EventNotify = NULL;
unsigned long BandwidthCheckerClass::UpstreamBandwidth = 0;
unsigned long BandwidthCheckerClass::ReportedUpstreamBandwidth = 0;
unsigned short *BandwidthCheckerClass::UpstreamBandwidthString = NULL;
unsigned long BandwidthCheckerClass::DownstreamBandwidth = 0;
unsigned long BandwidthCheckerClass::ReportedDownstreamBandwidth = 0;
unsigned short *BandwidthCheckerClass::DownstreamBandwidthString = NULL;
int BandwidthCheckerClass::FailureCode = BANDTEST_OK;
bool BandwidthCheckerClass::GotBandwidth = false;
const char *BandwidthCheckerClass::DefaultServerName = "www.westwood.com";
/*
** Possible error codes from the bandwidth test.
*/
char *BandwidthCheckerClass::ErrorList[13] = {
"BANDTEST_OK",
"BANDTEST_NO_WINSOCK2",
"BANDTEST_NO_RAW_SOCKET_PERMISSION",
"BANDTEST_NO_RAW_SOCKET_CREATE",
"BANDTEST_NO_UDP_SOCKET_BIND",
"BANDTEST_NO_TTL_SET",
"BANDTEST_NO_PING_RESPONSE",
"BANDTEST_NO_FINAL_PING_TIME",
"BANDTEST_NO_EXTERNAL_ROUTER",
"BANDTEST_NO_IP_DETECT",
"BANDTEST_UNKNOWN_ERROR",
"BANDTEST_WRONG_API_VERSION",
"BANDTEST_BAD_PARAM"
};
#define NUM_BANDS 12
#ifdef FREEDEDICATEDSERVER
#define DEFAULT_BAND 9
#else //FREEDEDICATEDSERVER
#define DEFAULT_BAND 3
#endif //FREEDEDICATEDSERVER
/*
** Lower and upper limits for each level of bandwidth.
*/
unsigned long BandwidthCheckerClass::Bandwidths[NUM_BANDS * 2] = {
12000, 14400,
28000, 28800,
29999, 33600,
53000, 57600,
62000, 67200,
105000, 115200,
125000, 128000,
250000, 256000,
500000, 512000,
999999, 1024000,
1999999, 2048000,
3999999, 4096000
};
/*
** Human readable names for each bandwidth level.
*/
unsigned short *BandwidthCheckerClass::BandwidthNames [NUM_BANDS+1] = {
L"14400",
L"28800",
L"33600",
L"57600",
L"67200",
L"115200",
L"128k",
L"256k",
L"512k",
L"1M",
L"2M",
L"4M",
L"> 4M"
};
/***********************************************************************************************
* BandwidthCheckerClass::Detect -- Create the bandwidth detect wait object *
* *
* *
* *
* INPUT: Nothing *
* *
* OUTPUT: Nothing *
* *
* WARNINGS: None *
* *
* HISTORY: *
* 11/21/2001 2:53PM ST : Created *
*=============================================================================================*/
RefPtr<WaitCondition> BandwidthCheckerClass::Detect(void)
{
return(BandwidthDetectWait::Create());
}
/***********************************************************************************************
* Start the bandwidth detection thread *
* *
* *
* *
* INPUT: Nothing *
* *
* OUTPUT: Nothing *
* *
* WARNINGS: None *
* *
* HISTORY: *
* 11/21/2001 2:53PM ST : Created *
*=============================================================================================*/
void BandwidthCheckerClass::Check_Now(HANDLE event)
{
EventNotify = event;
/*
** If the thread didn't finish for some reason then we need to take action.
** This will stall the dialogs but at least it won't crash.
*/
if (Thread.Is_Running()) {
unsigned long timeout = 10 * 1000;
unsigned long time = TIMEGETTIME();
while (Thread.Is_Running() && (TIMEGETTIME() - time) < timeout) {
Sleep(1);
}
}
if (Thread.Is_Running()) {
Thread.Stop(2000);
}
WWASSERT(!Thread.Is_Running());
Thread.Execute();
}
/***********************************************************************************************
* BandwidthCheckerClass::Get_Ping_Server_Name -- Get the name of a server to ping *
* *
* *
* *
* INPUT: Nothing *
* *
* OUTPUT: Ptr to server name *
* *
* WARNINGS: None *
* *
* HISTORY: *
* 11/27/2001 1:17PM ST : Created *
*=============================================================================================*/
const char *BandwidthCheckerClass::Get_Ping_Server_Name(void)
{
static char server_name_copy[128];
DynamicVectorClass<StringClass> list;
const char *server_name = DefaultServerName;
/*
** See if there are ping servers in the registry from a previous run.
*/
RegistryClass reg(APPLICATION_SUB_KEY_NAME_SERVER_LIST);
WWASSERT(list.Count() == 0);
reg.Get_Value_List(list);
if (list.Count() > 0) {
/*
** Get average and lowest ping server ping time.
*/
int num_times = 0;
unsigned long total = 0;
int lowest = 0xffff;
int lowest_index = -1;
for (int i=0 ; i<list.Count() ; i++) {
int time = reg.Get_Int(list[i].Peek_Buffer(), 0);
if (time > 0 && time < 0xffff) {
total += (unsigned long) time;
num_times++;
if (time < lowest) {
lowest = time;
lowest_index = i;
}
}
}
if (num_times) {
int average_time = (int) (total / (unsigned) num_times);
/*
** Pick one a little closer.
*/
average_time = average_time / 2;
/*
** Find the server closest to the average time.
*/
int closest_index = -1;
int closest_diff = 0x7fffffff;
for (i=0 ; i<list.Count() ; i++) {
int time = reg.Get_Int(list[i].Peek_Buffer(), 0);
if (time > 0 && time < 0xffff) {
int diff = abs(time - average_time);
if (diff < closest_diff) {
/*
** Ignore the nearest server.
*/
if (i != lowest_index) {
closest_diff = diff;
closest_index = i;
}
}
}
}
if (closest_index != -1) {
WWASSERT(closest_index >= 0);
WWASSERT(closest_index < list.Count());
strncpy(server_name_copy, list[closest_index].Peek_Buffer(), sizeof(server_name_copy));
server_name_copy[sizeof(server_name_copy) - 1] = 0;
server_name = (const char*) server_name_copy;
}
}
}
return(server_name);
}
/***********************************************************************************************
* BandwidthCheckerClass::Check -- Check bandwidth. This is called from bandwidth thread. *
* *
* *
* *
* INPUT: Nothing *
* *
* OUTPUT: Nothing *
* *
* WARNINGS: None *
* *
* HISTORY: *
* 11/21/2001 2:54PM ST : Created *
*=============================================================================================*/
void BandwidthCheckerClass::Check(void)
{
struct hostent *host;
struct sockaddr_in address;
int failure_code;
/*
** If we are auto starting then just use the previous settings from the registry.
*/
if (AutoRestart.Is_Active()) {
RegistryClass reg(APPLICATION_SUB_KEY_NAME_BANDTEST);
int up = reg.Get_Int("Up", 0);
int down = reg.Get_Int("Down", up);
UpstreamBandwidth = up;
DownstreamBandwidth = down;
if (up) {
GotBandwidth = true;
SetEvent(EventNotify);
return;
}
}
ConsoleBox.Print("Detecting bandwidth...\n");
const char *host_name = NULL;
if (cGameSpyAdmin::Is_Gamespy_Game()) {
// US West Ping server
host_name = "159.153.192.10";
} else {
host_name = Get_Ping_Server_Name();
}
WWDEBUG_SAY(("BandwidthCheckerClass::Check -- Trying server %s\n", host_name));
host = gethostbyname(host_name);
if (host == NULL) {
host_name = DefaultServerName;
WWDEBUG_SAY(("BandwidthCheckerClass::Check -- Trying server %s\n", host_name));
host = gethostbyname(host_name);
}
if (host == NULL) {
/*
** No DNS or no connection at all. Either way we are in trouble.
*/
WWDEBUG_SAY(("BandwidthCheckerClass - Unable to resolve host name\n"));
ConsoleBox.Print("Unable to resolve host name for bandwidth check\n");
#ifdef FREEDEDICATEDSERVER
UpstreamBandwidth = 1000000;
DownstreamBandwidth = 1000000;
ReportedUpstreamBandwidth = 1000000;
ReportedDownstreamBandwidth = 1000000;
#else //FREEDEDICATEDSERVER
UpstreamBandwidth = 55000;
DownstreamBandwidth = 55000;
ReportedUpstreamBandwidth = 57600;
ReportedDownstreamBandwidth = 57600;
#endif //FREEDEDICATEDSERVER
UpstreamBandwidthString = BandwidthNames[DEFAULT_BAND];
DownstreamBandwidthString = BandwidthNames[DEFAULT_BAND];
FailureCode = BANDTEST_NO_IP_DETECT;
GotBandwidth = false;
} else {
memcpy(&(address.sin_addr), host->h_addr, host->h_length);
/*
** Init the settings for the detection.
*/
BandtestSettingsStruct settings = {
0, //AlwaysICMP
0, //TTLScatter
50, //FastPingPackets
12, //SlowPingPackets
25, //Fast ping threshold
0 //PingProfile
};
/*
** Call the .dll function to do the actual detection.
*/
UpstreamBandwidth = Detect_Bandwidth(ntohl(address.sin_addr.s_addr), 0, 2, failure_code, DownstreamBandwidth, BANDTEST_API_VERSION, &settings, APPLICATION_SUB_KEY_NAME_BANDTEST);
/*
** If we failed due to a missing final ping then try again with fewer packets and no retries.
*/
if (UpstreamBandwidth == 0) {
if (failure_code == BANDTEST_NO_FINAL_PING_TIME ||
(cGameSpyAdmin::Is_Gamespy_Game() &&
failure_code == BANDTEST_NO_EXTERNAL_ROUTER)) {
BandtestSettingsStruct settings = {
0, //AlwaysICMP
0, //TTLScatter
25, //FastPingPackets
8, //SlowPingPackets
25, //Fast ping threshold
0 //PingProfile
};
if (cGameSpyAdmin::Is_Gamespy_Game()) {
// US East Ping server
address.sin_addr.s_addr = inet_addr("159.153.224.10");
}
UpstreamBandwidth = Detect_Bandwidth(ntohl(address.sin_addr.s_addr), 0, 0, failure_code, DownstreamBandwidth, BANDTEST_API_VERSION, &settings);
}
}
/*
** If it's 0, we failed.
*/
if (UpstreamBandwidth == 0) {
WWDEBUG_SAY(("Failed to get bandwidth - error code %s\n", ErrorList[failure_code]));
/*
** Default to 57600.
*/
#ifdef FREEDEDICATEDSERVER
ConsoleBox.Print("Failed to get bandwidth - error code %s, Setting 1Mbps bandwidth\n", ErrorList[failure_code]);
UpstreamBandwidth = 1000000;
DownstreamBandwidth = 1000000;
#else //FREEDEDICATEDSERVER
if (cGameSpyAdmin::Is_Gamespy_Game()) {
UpstreamBandwidth = 128000;
DownstreamBandwidth = 128000;
} else {
UpstreamBandwidth = 55000;
DownstreamBandwidth = 55000;
}
#endif //FREEDEDICATEDSERVER
FailureCode = failure_code;
GotBandwidth = true; //false;
} else {
GotBandwidth = true;
}
/*
** Fix up the upstream bandwidth into one of our connection type bands.
*/
if (UpstreamBandwidth > 0x7fffffff) {
WWDEBUG_SAY(("Upstream bandwidth is huge :-)\n"));
WWDEBUG_SAY(("Reported upstream connection bandwidth is > 4M bits per second\n"));
UpstreamBandwidth = 4096000;
ReportedUpstreamBandwidth = 4096000;
UpstreamBandwidthString = BandwidthNames[NUM_BANDS];
} else {
if (UpstreamBandwidth > 100000) {
#ifdef WWDEBUG
float floater = (float)UpstreamBandwidth / 1024;
#endif //WWDEBUG
WWDEBUG_SAY(("Upstream bandwidth to external router is %.1f kilobits per second\n", floater));
} else {
WWDEBUG_SAY(("Upstream bandwidth to external router is %d bits per second\n", UpstreamBandwidth));
}
bool got_bw_str = false;
for (int i=0 ; i<NUM_BANDS ; i++) {
if (UpstreamBandwidth < Bandwidths[(i*2) + 1]) {
//WWDEBUG_SAY(("\nReported upstream connection bandwidth is %s bits per second\n", BandwidthNames[i]));
UpstreamBandwidthString = BandwidthNames[i];
ReportedUpstreamBandwidth = Bandwidths[(i*2)+1];
got_bw_str = true;
break;
}
}
if (!got_bw_str) {
WWDEBUG_SAY(("\nReported upstream connection bandwidth is > 4M bits per second\n"));
ReportedUpstreamBandwidth = 4096000;
UpstreamBandwidthString = BandwidthNames[NUM_BANDS];
}
StringClass little_string;
WideStringClass(UpstreamBandwidthString, true).Convert_To(little_string);
ConsoleBox.Print("Upstream bandwidth of %s bps detected\n", little_string.Peek_Buffer());
}
/*
** Fix up the downstream bandwidth into one of our connection type bands.
*/
if (DownstreamBandwidth > 0x7fffffff) {
WWDEBUG_SAY(("Downstream bandwidth is huge :-)\n"));
WWDEBUG_SAY(("Reported downstream connection bandwidth is > 4M bits per second\n"));
DownstreamBandwidth = 4096000;
ReportedDownstreamBandwidth = 4096000;
DownstreamBandwidthString = BandwidthNames[NUM_BANDS];
} else {
if (DownstreamBandwidth > 100000) {
#ifdef WWDEBUG
float floater = (float)DownstreamBandwidth / 1024;
#endif //WWDEBUG
WWDEBUG_SAY(("Downstream bandwidth to external router is %.1f kilobits per second\n", floater));
} else {
WWDEBUG_SAY(("Downstream bandwidth to external router is %d bits per second\n", DownstreamBandwidth));
}
bool got_bw_str = false;
for (int i=0 ; i<NUM_BANDS ; i++) {
if (DownstreamBandwidth < Bandwidths[(i*2) + 1]) {
//WWDEBUG_SAY(("\nReported downstream connection bandwidth is %s bits per second\n", BandwidthNames[i]));
DownstreamBandwidthString = BandwidthNames[i];
ReportedDownstreamBandwidth = Bandwidths[(i*2)+1];
got_bw_str = true;
break;
}
}
if (!got_bw_str) {
WWDEBUG_SAY(("\nReported downstream connection bandwidth is > 4M bits per second\n"));
ReportedDownstreamBandwidth = 4096000;
DownstreamBandwidthString = BandwidthNames[NUM_BANDS];
}
}
/*
** Testy.
*/
#ifdef _DEBUG
PackedBandwidthType packed = Get_Packed_Bandwidth();
WWDEBUG_SAY(("Packed bandwidth as string = %s\n", Get_Bandwidth_As_String(packed)));
#endif //_DEBUG
}
SetEvent(EventNotify);
}
/***********************************************************************************************
* BandwidthCheckerClass::Force_Upstream_Bandwidth -- Set actual upstream bandwidth *
* *
* *
* *
* INPUT: Upstream bandwidth in buts per second *
* *
* OUTPUT: Nothing *
* *
* WARNINGS: None *
* *
* HISTORY: *
* 11/21/2001 2:54PM ST : Created *
*=============================================================================================*/
void BandwidthCheckerClass::Force_Upstream_Bandwidth(unsigned int up)
{
WWASSERT(up);
WWASSERT(cGameSpyAdmin::Is_Gamespy_Game());
UpstreamBandwidth = up;
}
/***********************************************************************************************
* BandwidthCheckerClass::Get_Upstream_Bandwidth -- Get actual upstream bandwidth *
* *
* *
* *
* INPUT: Nothing *
* *
* OUTPUT: Upstream bandwidth in buts per second *
* *
* WARNINGS: None *
* *
* HISTORY: *
* 11/21/2001 2:54PM ST : Created *
*=============================================================================================*/
unsigned long BandwidthCheckerClass::Get_Upstream_Bandwidth(void)
{
return(UpstreamBandwidth);
}
/***********************************************************************************************
* BandwidthCheckerClass::Get_Reported_Upstream_Bandwidth -- Get reported up bandwidth *
* *
* *
* *
* INPUT: Nothing *
* *
* OUTPUT: Reported upstream bandwidth in bits per second *
* *
* WARNINGS: None *
* *
* HISTORY: *
* 11/21/2001 2:55PM ST : Created *
*=============================================================================================*/
unsigned long BandwidthCheckerClass::Get_Reported_Upstream_Bandwidth(void)
{
return(ReportedUpstreamBandwidth);
}
/***********************************************************************************************
* BandwidthCheckerClass::Get_Upstream_Bandwidth_As_String -- Human readable upsream bw *
* *
* *
* *
* INPUT: Nothing *
* *
* OUTPUT: Ptr to bandwidth string *
* *
* WARNINGS: None *
* *
* HISTORY: *
* 11/21/2001 2:56PM ST : Created *
*=============================================================================================*/
unsigned short *BandwidthCheckerClass::Get_Upstream_Bandwidth_As_String(void)
{
return(UpstreamBandwidthString);
}
/***********************************************************************************************
* BandwidthCheckerClass::Get_Downstream_Bandwidth -- Get actual downstream bandwidth *
* *
* *
* *
* INPUT: Nothing *
* *
* OUTPUT: Actual down bw in bits per second *
* *
* WARNINGS: None *
* *
* HISTORY: *
* 11/21/2001 2:56PM ST : Created *
*=============================================================================================*/
unsigned long BandwidthCheckerClass::Get_Downstream_Bandwidth(void)
{
return(DownstreamBandwidth);
}
/***********************************************************************************************
* BandwidthCheckerClass::Get_Reported_Downstream_Bandwidth -- Get reported down bw *
* *
* *
* *
* INPUT: Nothing *
* *
* OUTPUT: Reported down bw in bits per second *
* *
* WARNINGS: None *
* *
* HISTORY: *
* 11/21/2001 2:57PM ST : Created *
*=============================================================================================*/
unsigned long BandwidthCheckerClass::Get_Reported_Downstream_Bandwidth(void)
{
return(ReportedDownstreamBandwidth);
}
/***********************************************************************************************
* BandwidthCheckerClass::Get_Downstream_Bandwidth_As_String -- Get down bw as a string *
* *
* *
* *
* INPUT: Nothing *
* *
* OUTPUT: Ptr to down bw string *
* *
* WARNINGS: None *
* *
* HISTORY: *
* 11/21/2001 2:57PM ST : Created *
*=============================================================================================*/
unsigned short *BandwidthCheckerClass::Get_Downstream_Bandwidth_As_String(void)
{
return(DownstreamBandwidthString);
}
/***********************************************************************************************
* BandwidthCheckerClass::Get_Bandwidth_As_String -- Get bandwidth description string *
* *
* *
* *
* INPUT: Nothing *
* *
* OUTPUT: Ptr to string *
* *
* WARNINGS: None *
* *
* HISTORY: *
* 11/21/2001 2:58PM ST : Created *
*=============================================================================================*/
unsigned short *BandwidthCheckerClass::Get_Bandwidth_As_String(void)
{
if (cUserOptions::Get_Bandwidth_Type() == BANDWIDTH_AUTO) {
static unsigned short _build_string[256];
swprintf(_build_string, L"%s,%s", DownstreamBandwidthString, UpstreamBandwidthString);
return(_build_string);
} else {
return((unsigned short*)cBandwidth::Get_Bandwidth_String_From_Type(
(BANDWIDTH_TYPE_ENUM)cUserOptions::Get_Bandwidth_Type()));
}
}
/***********************************************************************************************
* BandwidthCheckerClass::Get_Bandwidth_As_String -- Get bandwidth description string *
* *
* *
* *
* INPUT: Packed up/down bandwidth *
* *
* OUTPUT: Ptr to bandwidth description string *
* *
* WARNINGS: None *
* *
* HISTORY: *
* 11/21/2001 2:58PM ST : Created *
*=============================================================================================*/
unsigned short *BandwidthCheckerClass::Get_Bandwidth_As_String(PackedBandwidthType bandwidth)
{
static unsigned short _build_string[256];
assert(bandwidth.Bandwidth.Up < NUM_BANDS + 1);
assert(bandwidth.Bandwidth.Down < NUM_BANDS + 1);
swprintf(_build_string, L"%s,%s", BandwidthNames[bandwidth.Bandwidth.Down], BandwidthNames[bandwidth.Bandwidth.Up]);
return(_build_string);
}
/***********************************************************************************************
* BandwidthCheckerClass::Get_Packed_Bandwidth -- Get bandwidth packed into a byte *
* *
* *
* *
* INPUT: Nothing *
* *
* OUTPUT: Bandwidth as a byte *
* *
* WARNINGS: None *
* *
* HISTORY: *
* 11/21/2001 2:59PM ST : Created *
*=============================================================================================*/
BandwidthCheckerClass::PackedBandwidthType BandwidthCheckerClass::Get_Packed_Bandwidth(void)
{
PackedBandwidthType bandwidth = {0,0};
assert(sizeof(bandwidth) == 1);
unsigned long bwu = ReportedUpstreamBandwidth;
unsigned long bwd = ReportedDownstreamBandwidth;
bool automode = true;
if (cUserOptions::Get_Bandwidth_Type() != BANDWIDTH_AUTO) {
bwu = cBandwidth::Get_Bandwidth_Bps_From_Type((BANDWIDTH_TYPE_ENUM)cUserOptions::Get_Bandwidth_Type());
bwd = bwu;
automode = false;
}
/*
** Just return 0s if we haven't detected bandwidth yet.
*/
if (!automode || UpstreamBandwidth != 0) {
for (int i=0 ; i<NUM_BANDS+1 ; i++) {
if (bwu <= Bandwidths[(i*2)+1]) {
bandwidth.Bandwidth.Up = i;
break;
}
}
for (i=0 ; i<NUM_BANDS+1 ; i++) {
if (bwd <= Bandwidths[(i*2)+1]) {
bandwidth.Bandwidth.Down = i;
break;
}
}
}
return(bandwidth);
}
/***********************************************************************************************
* BandwidthCheckerClass::Get_Compact_Log -- Get basic log information to send to server *
* *
* *
* *
* INPUT: String to add info to *
* *
* OUTPUT: Nothing *
* *
* WARNINGS: None *
* *
* HISTORY: *
* 12/4/2001 1:12PM ST : Created *
*=============================================================================================*/
void BandwidthCheckerClass::Get_Compact_Log(StringClass &log_string)
{
char temp[128];
sprintf(temp, "%d\t%d\t%d\t", UpstreamBandwidth, DownstreamBandwidth, cUserOptions::Get_Bandwidth_Type());
log_string = temp;
}
/***********************************************************************************************
* BandwidthDetectWait::Create -- Create the wait object for bandwidth detection *
* *
* *
* *
* INPUT: Nothing *
* *
* OUTPUT: Ref Ptr to bandwidth wait *
* *
* WARNINGS: None *
* *
* HISTORY: *
* 11/21/2001 3:00PM ST : Created *
*=============================================================================================*/
RefPtr<BandwidthDetectWait> BandwidthDetectWait::Create(void)
{
return (new BandwidthDetectWait());
}
/***********************************************************************************************
* BandwidthDetectWait::BandwidthDetectWait -- BandwidthDetectWait constructor *
* *
* *
* *
* INPUT: Nothing *
* *
* OUTPUT: Nothing *
* *
* WARNINGS: None *
* *
* HISTORY: *
* 11/21/2001 3:22PM ST : Created *
*=============================================================================================*/
BandwidthDetectWait::BandwidthDetectWait(void) :
SingleWait(TRANSLATE (IDS_MENU_TESTING_BANDWIDTH), 60000),
mEvent(NULL),
mPingsRemaining(0xffffffff)
{
if (!cGameSpyAdmin::Is_Gamespy_Game()) {
WOLSession = WWOnline::Session::GetInstance(false);
assert(WOLSession.IsValid());
}
}
/***********************************************************************************************
* BandwidthDetectWait::~BandwidthDetectWait -- BandwidthDetectWait destructor *
* *
* *
* *
* INPUT: Nothing *
* *
* OUTPUT: Nothing *
* *
* WARNINGS: None *
* *
* HISTORY: *
* 11/21/2001 3:22PM ST : Created *
*=============================================================================================*/
BandwidthDetectWait::~BandwidthDetectWait()
{
WWDEBUG_SAY(("BandwidthDetectWait: End - %S\n", mEndText));
if (WOLSession.IsValid()) WOLSession->EnablePinging(true);
if (mEvent) {
CloseHandle(mEvent);
}
}
/***********************************************************************************************
* BandwidthDetectWait::WaitBeginning -- Called to init the wait *
* *
* *
* *
* INPUT: Nothing *
* *
* OUTPUT: Nothing *
* *
* WARNINGS: None *
* *
* HISTORY: *
* 11/21/2001 3:22PM ST : Created *
*=============================================================================================*/
void BandwidthDetectWait::WaitBeginning(void)
{
WWDEBUG_SAY(("BandwidthDetectWait: Beginning\n"));
mEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (mEvent == NULL) {
WWDEBUG_SAY(("BandwidthDetectWait: Can't create event\n"));
EndWait(Error, TRANSLATE (IDS_MENU_FAILED_TO_CREATE_BW_EVENT));
} else {
if (WOLSession.IsValid()) WOLSession->EnablePinging(false);
mTimeout = 15000;
}
}
/***********************************************************************************************
* BandwidthDetectWait::GetResult -- See if there is a result for the wait condition *
* *
* *
* *
* INPUT: Nothing *
* *
* OUTPUT: Result code *
* *
* WARNINGS: None *
* *
* HISTORY: *
* 11/21/2001 3:23PM ST : Created *
*=============================================================================================*/
WaitCondition::WaitResult BandwidthDetectWait::GetResult(void)
{
if (mEndResult == Waiting) {
/*
** Wait for pings to finish first.
*/
unsigned int pingsWaiting = 0;
if (!cGameSpyAdmin::Is_Gamespy_Game()) {
pingsWaiting = WOLSession->GetPendingPingCount();
}
if (mPingsRemaining != pingsWaiting) {
mPingsRemaining = pingsWaiting;
if (mPingsRemaining == 0) {
mTimeout = 60000;
BandwidthCheckerClass::Check_Now(mEvent);
}
}
if (mPingsRemaining == 0) {
DWORD result = WaitForSingleObject(mEvent, 0);
if (result == WAIT_OBJECT_0) {
WWDEBUG_SAY(("BandwidthDetectWait: ConditionMet\n"));
EndWait(ConditionMet, TRANSLATE (IDS_MENU_BW_DETECTION_COMPLETE));
} else {
if (result == WAIT_FAILED) {
WWDEBUG_SAY(("BandwidthDetectWait: WAIT_FAILED\n"));
EndWait(Error, TRANSLATE (IDS_MENU_BW_DETECTION_FAILED));
}
}
}
}
if (mEndResult != Waiting && WOLSession.IsValid()) {
WOLSession->EnablePinging(true);
}
return(mEndResult);
}

View File

@@ -0,0 +1,167 @@
/*
** 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/>.
*/
/***********************************************************************************************
*** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : Command & Conquer *
* *
* $Archive:: /Commando/Code/Commando/bandwidthcheck.h $*
* *
* $Author:: Bhayes $*
* *
* $Modtime:: 2/18/02 9:33p $*
* *
* $Revision:: 9 $*
* *
* *
*---------------------------------------------------------------------------------------------*
* *
* *
*---------------------------------------------------------------------------------------------*
* *
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#ifndef _BANDWIDTHCHECK_H
#define _BANDWIDTHCHECK_H
#include <WWOnline\WaitCondition.h>
#include <wwlib\except.h>
#include <windows.h>
#include <BandTest\BandTest.h>
namespace WWOnline {
class Session;
}
class BandwidthCheckerClass
{
public:
/*
** Struct for packing bandwidth levels into a single byte.
*/
#pragma pack(push)
#pragma pack(1)
typedef struct tInternalPackedBandwidthType {
unsigned char Up : 4;
unsigned char Down : 4;
} InternalPackedBandwidthType;
typedef union tPackedBandwidthType {
InternalPackedBandwidthType Bandwidth;
unsigned char RawBandwidth;
} PackedBandwidthType;
#pragma pack(pop)
static RefPtr<WaitCondition> Detect(void);
static void Check_Now(HANDLE event);
static bool Got_Bandwidth(void) {return(GotBandwidth);};
static void Force_Upstream_Bandwidth(unsigned int up);
static unsigned long Get_Upstream_Bandwidth(void);
static unsigned long Get_Reported_Upstream_Bandwidth(void);
static unsigned short *Get_Upstream_Bandwidth_As_String(void);
static unsigned long Get_Downstream_Bandwidth(void);
static unsigned long Get_Reported_Downstream_Bandwidth(void);
static unsigned short *Get_Downstream_Bandwidth_As_String(void);
static unsigned short *Get_Bandwidth_As_String(void);
static unsigned short *Get_Bandwidth_As_String(PackedBandwidthType bandwidth);
static PackedBandwidthType Get_Packed_Bandwidth(void);
static bool Failed_Due_To_No_Connection(void) {return(FailureCode == BANDTEST_NO_IP_DETECT);}
static void Get_Compact_Log(StringClass &log_string);
static bool Is_Thread_Running(void) { return Thread.Is_Running(); }
private:
static void Check(void);
static const char *Get_Ping_Server_Name(void);
static class BandwidthCheckerThreadClass : public ThreadClass {
public:
BandwidthCheckerThreadClass(const char *thread_name = "Bandwidth checker thread") : ThreadClass(thread_name, &Exception_Handler) {}
void Thread_Function(void) {BandwidthCheckerClass::Check();};
} Thread;
friend BandwidthCheckerThreadClass;
static HANDLE EventNotify;
static unsigned long UpstreamBandwidth;
static unsigned long ReportedUpstreamBandwidth;
static unsigned long DownstreamBandwidth;
static unsigned long ReportedDownstreamBandwidth;
static unsigned short *UpstreamBandwidthString;
static unsigned short *DownstreamBandwidthString;
#define NUM_BANDS 12
static char *ErrorList[13];
static unsigned long Bandwidths[NUM_BANDS * 2];
static unsigned short *BandwidthNames[NUM_BANDS + 1];
static int FailureCode;
static bool GotBandwidth;
static const char *DefaultServerName;
};
/*
** Wait code for bandwidth detection.
**
**
**
*/
class BandwidthDetectWait : public SingleWait
{
public:
static RefPtr<BandwidthDetectWait> Create(void);
void WaitBeginning(void);
WaitResult GetResult(void);
protected:
BandwidthDetectWait();
virtual ~BandwidthDetectWait();
BandwidthDetectWait(const BandwidthDetectWait&);
const BandwidthDetectWait& operator = (const BandwidthDetectWait&);
RefPtr<WWOnline::Session> WOLSession;
unsigned int mPingsRemaining;
HANDLE mEvent;
};
#endif //_BANDWIDTHCHECK_H

View File

@@ -0,0 +1,336 @@
/*
** 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/bandwidthgraph.cpp $*
* *
* $Author:: Steve_t $*
* *
* $Modtime:: 1/02/02 2:29a $*
* *
* $Revision:: 9 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include "bandwidthgraph.h"
#include "assets.h"
#include "font3d.h"
#include "render2d.h"
#include "cnetwork.h"
#include "devoptions.h"
#include "packetmgr.h"
#include "serversettings.h"
#include "consolemode.h"
//
// Class statics
//
Render2DTextClass * cBandwidthGraph::PTextRenderer = NULL;
Font3DInstanceClass * cBandwidthGraph::PFont = NULL;
int cBandwidthGraph::BandwidthScaler = 50000;
float cBandwidthGraph::YPosition = 0;
float cBandwidthGraph::BarHeight = 0;
float cBandwidthGraph::BarWidth = 0;
float cBandwidthGraph::YIncrement = 0;
#define COLOR_BLACK 0xFF000000
#define COLOR_WHITE 0xFFFFFFFF
#define COLOR_RED 0xFFFF0000
#define COLOR_GREEN 0xFF48FF48
//-----------------------------------------------------------------------------
void
cBandwidthGraph::Onetime_Init
(
void
)
{
WWDEBUG_SAY(("cBandwidthGraph::Onetime_Init\n"));
bool can_render = ConsoleBox.Is_Exclusive() ? false : true;
if (can_render) {
WWASSERT(WW3DAssetManager::Get_Instance() != NULL);
PFont = WW3DAssetManager::Get_Instance()->Get_Font3DInstance("FONT6x8.TGA");
WWASSERT(PFont != NULL);
PFont->Set_Mono_Spaced();
SET_REF_OWNER(PFont);
PTextRenderer = new Render2DTextClass(PFont);
PTextRenderer->Set_Coordinate_Range(Render2DClass::Get_Screen_Resolution());
BarWidth = Render2DClass::Get_Screen_Resolution().Width() / 10.0f;
BarHeight = PTextRenderer->Peek_Font()->Char_Height();
YIncrement = BarHeight * 1.25f;
}
// This needs to be done somewhere else - we need a good value whether we have the graph or not.
//PacketManager.Set_Stats_Sampling_Frequency_Delay(1000);
//PacketManager.Set_Stats_Sampling_Frequency_Delay(250);
}
//-----------------------------------------------------------------------------
void
cBandwidthGraph::Onetime_Shutdown
(
void
)
{
WWDEBUG_SAY(("cBandwidthGraph::Onetime_Close\n"));
if (PTextRenderer != NULL)
{
delete PTextRenderer;
PTextRenderer = NULL;
}
if (PFont != NULL)
{
PFont->Release_Ref();
PFont = NULL;
}
}
//-----------------------------------------------------------------------------
void
cBandwidthGraph::Bandwidth_Graph
(
StringClass & label,
int bps,
int target_bps,
float bandwidth_multiplier,
float average_priority,
bool is_loading
)
{
if (PTextRenderer == NULL) {
return;
}
WWASSERT(PTextRenderer != NULL);
float x1 = 0;
float x2 = bps / (float) BandwidthScaler * BarWidth;
float y1 = YPosition;
float y2 = y1 + BarHeight;
//
// Bandwidth used (graph)
//
PTextRenderer->Draw_Block(RectClass(x1, y1, x2, y2), COLOR_RED);
PTextRenderer->Set_Location(Vector2(2, YPosition));
PTextRenderer->Draw_Text(label);
//
// Bandwidth used (text)
//
StringClass text;
text.Format("%d", bps);
PTextRenderer->Set_Location(Vector2(200, YPosition));
PTextRenderer->Draw_Text(text);
//
// Bandwidth budgeted (text)
//
if (target_bps >= 0)
{
StringClass text;
text.Format("%d", target_bps);
PTextRenderer->Set_Location(Vector2(245, YPosition));
PTextRenderer->Draw_Text(text);
float target_x = target_bps / (float) BandwidthScaler * BarWidth;
PTextRenderer->Draw_Block(RectClass(target_x - 1, y1, target_x + 1, y2));
}
//
// Bandwidth multiplier and average object priority
//
if (bandwidth_multiplier >= 0.0f)
{
//
// Graph mark
//
//float tp = threshold_priority * Render2DClass::Get_Screen_Resolution().Width();
//PTextRenderer->Draw_Block(RectClass(tp - 1, y1, tp + 1, y2), COLOR_GREEN);
//
// Text
//
// Bandwidth multiplier
if (is_loading) {
text.Format("BM:%-8.6f Ld", bandwidth_multiplier);
} else {
text.Format("BM:%-8.6f", bandwidth_multiplier);
}
PTextRenderer->Set_Location(Vector2(400, YPosition));
PTextRenderer->Draw_Text(text);
// Average object priority on this client
text.Format("AP:%-8.6f", average_priority);
PTextRenderer->Set_Location(Vector2(500, YPosition));
PTextRenderer->Draw_Text(text);
}
YPosition += YIncrement;
}
//-----------------------------------------------------------------------------
void
cBandwidthGraph::Think
(
void
)
{
bool bail = true;
#ifdef WWDEBUG
if (cDevOptions::ShowBandwidth.Is_True())
{
bail = false;
}
#endif // WWDEBUG
if (bail)
{
return;
}
PacketManager.Update_Stats();
if (PTextRenderer == NULL) {
return;
}
WWASSERT(PTextRenderer != NULL);
PTextRenderer->Reset();
//
// Draw the scale at the top
//
YPosition = 50;
float x1 = 0;
float x2 = 0;
float y1 = YPosition;
float y2 = y1 + BarHeight;
int i = 0;
do {
x2 = x1 + BarWidth;
PTextRenderer->Draw_Block(RectClass(x1, y1, x2, y2), (i % 2) ? COLOR_WHITE : COLOR_BLACK);
x1 = x2;
i++;
} while (x2 < Render2DClass::Get_Screen_Resolution().Width());
//
// Label the scale
//
StringClass text;
text.Format("BW / %d", BandwidthScaler);
PTextRenderer->Set_Location(Vector2(2, YPosition - 10));
PTextRenderer->Draw_Text(text);
YPosition += YIncrement;
DWORD bps = 0;
DWORD target_bps = 0;
//
// Client bandwidth
//
if (cNetwork::I_Am_Client() && cNetwork::PClientConnection->Is_Established())
{
text.Format("c%d->s", cNetwork::Get_My_Id());
bps = PacketManager.Get_Compressed_Bandwidth_Out(&cNetwork::Get_Client_Rhost()->Get_Address());
target_bps = cNetwork::Get_Client_Rhost()->Get_Target_Bps();
Bandwidth_Graph(text, bps, target_bps, -1.0f, -1.0f, false); //cNetwork::Get_Client_Rhost()->Get_Threshold_Priority());
text.Format("c%d<-s", cNetwork::Get_My_Id());
bps = PacketManager.Get_Compressed_Bandwidth_In(&cNetwork::Get_Client_Rhost()->Get_Address());
Bandwidth_Graph(text, bps, -1, -1, -1.0f, false);
}
//
// Server bandwidth
//
if (cNetwork::PServerConnection != NULL)
{
text.Format("s->c*");
bps = PacketManager.Get_Total_Compressed_Bandwidth_Out();
target_bps = cNetwork::PServerConnection->Get_Bandwidth_Budget_Out();
Bandwidth_Graph(text, bps, target_bps, -1, -1.0f, false);
text.Format("s<-c*");
bps = PacketManager.Get_Total_Compressed_Bandwidth_In();
Bandwidth_Graph(text, bps, -1, -1, -1.0f, false);
for (int i = cNetwork::PServerConnection->Get_Min_RHost(); i <= cNetwork::PServerConnection->Get_Max_RHost(); i++)
{
cRemoteHost * p_rhost = cNetwork::Get_Server_Rhost(i);
if (p_rhost != NULL)
{
bool is_loading = p_rhost->Get_Flood();
text.Format("s->c%d", i);
bps = PacketManager.Get_Compressed_Bandwidth_Out(&p_rhost->Get_Address());
target_bps = p_rhost->Get_Target_Bps();
Bandwidth_Graph(text, bps, target_bps, p_rhost->Get_Bandwidth_Multiplier(), p_rhost->Get_Average_Priority(), is_loading);
text.Format("s<-c%d", i);
bps = PacketManager.Get_Compressed_Bandwidth_In(&p_rhost->Get_Address());
Bandwidth_Graph(text, bps, -1, -1, -1.0f, false);
}
}
}
}
//-----------------------------------------------------------------------------
void
cBandwidthGraph::Render
(
void
)
{
bool bail = true;
#ifdef WWDEBUG
if (cDevOptions::ShowBandwidth.Is_True())
{
bail = false;
}
#endif // WWDEBUG
if (bail)
{
return;
}
if (PTextRenderer == NULL) {
return;
}
WWASSERT(PTextRenderer != NULL);
PTextRenderer->Render();
}

View File

@@ -0,0 +1,73 @@
/*
** 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/bandwidthgraph.h $*
* *
* $Author:: Steve_t $*
* *
* $Modtime:: 10/26/01 12:45p $*
* *
* $Revision:: 5 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#ifndef __BANDWIDTHGRAPH_H__
#define __BANDWIDTHGRAPH_H__
#include "bittype.h"
#include "wwstring.h"
class Render2DTextClass;
class Font3DInstanceClass;
//-----------------------------------------------------------------------------
class cBandwidthGraph
{
public:
static void Onetime_Init(void);
static void Onetime_Shutdown(void);
static void Think(void);
static void Render(void);
static void Set_Scale(int scale) {BandwidthScaler = scale;}
private:
static void Bandwidth_Graph(StringClass & label, int bps,
int target_bps, float bandwidth_multiplier, float average_priority, bool is_loading);
static Render2DTextClass * PTextRenderer;
static Font3DInstanceClass * PFont;
static int BandwidthScaler;
static float YPosition;
static float BarHeight;
static float BarWidth;
static float YIncrement;
};
//-----------------------------------------------------------------------------
#endif // __BANDWIDTHGRAPH_H__

235
Code/Commando/bioevent.cpp Normal file
View File

@@ -0,0 +1,235 @@
/*
** 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/bioevent.cpp $*
* *
* $Author:: Steve_t $*
* *
* $Modtime:: 2/20/02 11:01p $*
* *
* $Revision:: 26 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include "bioevent.h"
#include <stdio.h>
#include <stdlib.h>
#include "networkobjectfactory.h"
#include "cnetwork.h"
#include "networkobjectmgr.h"
#include "evictionevent.h"
#include "playermanager.h"
#include "god.h"
#include "gametype.h"
#include "apppackettypes.h"
#include "gamedataupdateevent.h"
#include "consolemode.h"
#include "winevent.h"
#include "gamespyadmin.h"
DECLARE_NETWORKOBJECT_FACTORY(cBioEvent, NETCLASSID_BIOEVENT);
//-----------------------------------------------------------------------------
cBioEvent::cBioEvent(void) :
SenderId(0),
TeamChoice(-1),
ClanID(0)
{
Set_App_Packet_Type(APPPACKETTYPE_BIOEVENT);
}
//-----------------------------------------------------------------------------
void
cBioEvent::Init(int teamChoice, unsigned long clanID)
{
WWASSERT(cNetwork::I_Am_Client());
SenderId = cNetwork::Get_My_Id();
Nickname = cNetInterface::Get_Nickname();
TeamChoice = teamChoice;
ClanID = clanID;
strcpy(MapName, The_Game()->Get_Map_Name().Peek_Buffer());
Set_Network_ID(NetworkObjectMgrClass::Get_New_Client_ID());
if (cNetwork::I_Am_Server()) {
Act();
} else {
Set_Object_Dirty_Bit(0, BIT_CREATION, true);
}
}
//-----------------------------------------------------------------------------
void
cBioEvent::Act(void)
{
WWASSERT(cNetwork::I_Am_Server());
//
// This is where we validate a player. If we don't want him to play,
// for whichever reason, after learning all about him, evict him here.
// Note that the server has already seen the player name in
// cNetwork::Application_Acceptance_Handler.
// Now the server will see additional data.
//
bool is_accepted = true;
EvictionCodeEnum eviction_code = EVICTION_POOR_BANDWIDTH;
if (is_accepted) {
//
// Tell the new guy about all existing players
//
for (SLNode<cPlayer> * player_node = cPlayerManager::Get_Player_Object_List()->Head();
player_node;
player_node = player_node->Next()) {
cPlayer * p_player = player_node->Data();
WWASSERT(p_player != NULL);
cNetwork::Send_Object_Update(p_player, SenderId);
}
//GAMESPY
if (cGameSpyAdmin::Is_Gamespy_Game() &&
cGameSpyAdmin::Is_Nickname_Collision(Nickname)) {
WideStringClass new_nickname;
int count = 1;
do {
new_nickname.Format(L"%s(%d)", Nickname, count++);
} while (cGameSpyAdmin::Is_Nickname_Collision(new_nickname));
Nickname = new_nickname;
}
cPlayer * p_player = cGod::Create_Player(SenderId, Nickname, TeamChoice, ClanID);
WWASSERT(p_player != NULL);
if (!IS_SOLOPLAY) {
//
// Record his IP address for diagnostic purposes
//
WWASSERT(cNetwork::Get_Server_Rhost(SenderId) != NULL);
SOCKADDR_IN & address = cNetwork::Get_Server_Rhost(SenderId)->Get_Address();
p_player->Set_Ip_Address(address.sin_addr.s_addr);
//
// Tell the remote host object to expect a lot of temporary extra bandwidth.
//
if (cNetwork::PServerConnection != NULL) {
cNetwork::PServerConnection->Set_Rhost_Expect_Packet_Flood(p_player->Get_Id(), true);
}
//
// Update him about any dynamic game data parameters.
//
WWDEBUG_SAY(("BioEvent acting\n"));
cGameDataUpdateEvent * p_event = new cGameDataUpdateEvent();
p_event->Init(p_player->Get_Id());
StringClass str(128, true);
Nickname.Convert_To(str);
ConsoleBox.Print_Maybe("Player %s joined the game\n", str.Peek_Buffer());
//
// If we (the server) are already in intermission mode then deactivate the player until the next map starts. The player
// will have already loaded the next map. ST - 1/17/2002 7:43PM
//
if (The_Game()->IsIntermission.Is_True()) {
//
// If the new player has the old map loaded (which can happen if the intermission starts after the client has
// started loading the old map) then send him a wineven so he knows to load the next map.
//
if (stricmp(MapName, The_Game()->Get_Map_Name().Peek_Buffer()) != 0) {
cWinEvent * p_win = new cWinEvent;
p_win->Init(The_Game()->Get_Winner_ID(), SenderId, The_Game()->Is_Map_Cycle_Over());
cNetwork::Send_Object_Update(p_win, SenderId);
} else {
p_player->Set_Is_In_Game(false);
p_player->Set_Is_Waiting_For_Intermission(true);
}
}
}
} else {
cEvictionEvent * p_event = new cEvictionEvent;
p_event->Init(SenderId, eviction_code);
cNetwork::Flush();
cNetwork::Server_Kill_Connection(SenderId);
}
Set_Delete_Pending();
}
//-----------------------------------------------------------------------------
void
cBioEvent::Export_Creation(BitStreamClass & packet)
{
cNetEvent::Export_Creation(packet);
WWASSERT(cNetwork::I_Am_Only_Client());
WWASSERT(SenderId > 0);
packet.Add(SenderId);
packet.Add_Wide_Terminated_String(Nickname);
packet.Add(TeamChoice);
packet.Add(ClanID);
packet.Add_Terminated_String(MapName, false);
WWDEBUG_SAY(("cBioEvent sent\n"));
Set_Delete_Pending();
}
//-----------------------------------------------------------------------------
void
cBioEvent::Import_Creation(BitStreamClass & packet)
{
cNetEvent::Import_Creation(packet);
WWASSERT(cNetwork::I_Am_Server());
packet.Get(SenderId);
packet.Get_Wide_Terminated_String(Nickname.Get_Buffer(256), 256, true);
packet.Get(TeamChoice);
packet.Get(ClanID);
packet.Get_Terminated_String(MapName, sizeof(MapName), false);
WWASSERT(SenderId > 0);
WWDEBUG_SAY(("cBioEvent recd\n"));
Act();
}

74
Code/Commando/bioevent.h Normal file
View File

@@ -0,0 +1,74 @@
/*
** 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/bioevent.h $*
* *
* $Author:: Steve_t $*
* *
* $Modtime:: 1/18/02 1:23p $*
* *
* $Revision:: 11 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#ifndef __BIOEVENT_H__
#define __BIOEVENT_H__
#include "netevent.h"
#include "netclassids.h"
//-----------------------------------------------------------------------------
//
// A C->S mirrored event object for transmitting initial player bio data.
//
class cBioEvent : public cNetEvent
{
public:
cBioEvent(void);
void Init(int team_choice, unsigned long clanID);
virtual void Export_Creation(BitStreamClass &packet);
virtual void Import_Creation(BitStreamClass &packet);
virtual uint32 Get_Network_Class_ID(void) const {return NETCLASSID_BIOEVENT;}
private:
virtual void Act(void);
int SenderId;
WideStringClass Nickname;
char MapName[256];
int TeamChoice;
unsigned long ClanID;
};
//-----------------------------------------------------------------------------
#endif // __BIOEVENT_H__

50
Code/Commando/boolean.h Normal file
View File

@@ -0,0 +1,50 @@
/*
** 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/>.
*/
//
// Filename: boolean.h
// Author: Tom Spencer-Smith
// Date: Nov 1999
// Description:
//
//-----------------------------------------------------------------------------
#if defined(_MSV_VER)
#pragma once
#endif
#ifndef BOOLEAN_H
#define BOOLEAN_H
//-----------------------------------------------------------------------------
class cBoolean
{
public:
cBoolean(bool value = false) {Value = value;}
bool Toggle(void) {Value = !Value; return Value;}
bool Set(bool value) {Value = value; return Value;}
bool Get(void) const {return Value;}
bool Is_True(void) const {return Value == true;}
bool Is_False(void) const {return Value == false;}
private:
bool Value;
};
//-----------------------------------------------------------------------------
#endif // BOOLEAN_H

317
Code/Commando/buildnum.cpp Normal file
View File

@@ -0,0 +1,317 @@
/*
** 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/>.
*/
/***********************************************************************************************
*** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : Combat *
* *
* $Archive:: /Commando/Code/Commando/buildnum.cpp $*
* *
* Author:: Steve Tall *
* *
* $Modtime:: 10/29/01 10:06p $*
* *
* $Revision:: 2 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include "always.h"
#include "buildnum.h"
#include "wwdebug.h"
#include <stdio.h>
#include "win.h"
/*
**
** This is just a placeholder for the build number.
** A post build step will stamp the build number into here.
**
*/
char BuildInfoClass::BuildNumber [64] = {"Insert1Build2Number3Here4 xxxx "};
char BuildInfoClass::BuildDate [64] = {"Insert1Build2Date3Here4 xxxx "};
/*
** Unreachable code warning.
*/
#pragma warning(disable : 4702)
/***********************************************************************************************
* BuildInfoClass::Get_Build_Number -- Gets the 32 bit build number. *
* *
* *
* *
* INPUT: Nothing *
* *
* OUTPUT: Build number *
* *
* WARNINGS: None *
* *
* HISTORY: *
* 10/29/2001 4:54PM ST : Created *
*=============================================================================================*/
unsigned long BuildInfoClass::Get_Build_Number(void)
{
return (*(unsigned long*)(&BuildNumber[28]));
}
/***********************************************************************************************
* BuildInfoClass::Get_Build_Number_String -- Gets the build number as a human readable string.*
* *
* *
* *
* INPUT: Nothing *
* *
* OUTPUT: Ptr to build number string *
* *
* WARNINGS: None *
* *
* HISTORY: *
* 10/29/2001 4:55PM ST : Created *
*=============================================================================================*/
char *BuildInfoClass::Get_Build_Number_String(void)
{
static char _buffer[16];
sprintf (_buffer, "%d", *(unsigned long*)(&BuildNumber[28]));
return (_buffer);
}
/***********************************************************************************************
* BuildInfoClass::Get_Builder_Name -- Gets the name of the person who built this executable. *
* *
* *
* *
* INPUT: Nothing *
* *
* OUTPUT: Ptr to builder name string *
* *
* WARNINGS: None *
* *
* HISTORY: *
* 10/29/2001 5:08PM ST : Created *
*=============================================================================================*/
char *BuildInfoClass::Get_Builder_Name(void)
{
return(&BuildNumber[32]);
}
/***********************************************************************************************
* BuildInfoClass::Get_Build_Date_String -- Gets the date this executable was built on. *
* *
* *
* *
* INPUT: Nothing *
* *
* OUTPUT: Ptr to build date string *
* *
* WARNINGS: None *
* *
* HISTORY: *
* 10/29/2001 5:10PM ST : Created *
*=============================================================================================*/
char *BuildInfoClass::Get_Build_Date_String(void)
{
static char _buffer[64];
SYSTEMTIME systime;
if (FileTimeToSystemTime ((LPFILETIME)(&BuildDate[28]), &systime) ) {
sprintf(_buffer, "%02d/%02d/%04d - %02d:%02d:%02d", systime.wMonth, systime.wDay, systime.wYear, systime.wHour, systime.wMinute, systime.wSecond);
} else {
_buffer[0] = 0;
}
return(_buffer);
}
/***********************************************************************************************
* BuildInfoClass::Get_Builder_Initials -- Gets the initials of the builder *
* *
* *
* *
* INPUT: Nothing *
* *
* OUTPUT: Ptr to string containing initials *
* *
* WARNINGS: None *
* *
* HISTORY: *
* 10/29/2001 5:12PM ST : Created *
*=============================================================================================*/
char *BuildInfoClass::Get_Builder_Initials(void)
{
static char _buffer[4];
_buffer[0] = BuildNumber[32];
_buffer[1] = 0;
_buffer[2] = 0;
char *lastname = strchr(&BuildNumber[32], '_');
if (lastname) {
_buffer[1] = lastname[1];
}
return (_buffer);
}
/***********************************************************************************************
* BuildInfoClass::Get_Build_Version_String -- Get composite version as string *
* *
* *
* *
* INPUT: Nothing *
* *
* OUTPUT: Version string *
* *
* WARNINGS: None *
* *
* HISTORY: *
* 10/29/2001 7:30PM ST : Created *
*=============================================================================================*/
char *BuildInfoClass::Get_Build_Version_String(void)
{
static char _buffer[128];
sprintf(_buffer, "%s-%s", Get_Builder_Initials(), Get_Build_Number_String());
return(_buffer);
}
/***********************************************************************************************
* BuildInfoClass::Get_Build_Type -- Get the type of build this is *
* *
* *
* *
* INPUT: Nothing *
* *
* OUTPUT: Build type *
* *
* WARNINGS: None *
* *
* HISTORY: *
* 10/29/2001 7:40PM ST : Created *
*=============================================================================================*/
BuildInfoClass::BuildType BuildInfoClass::Get_Build_Type(void)
{
#ifndef _DEBUG
#ifdef WWDEBUG
return(BUILD_PROFILE);
#else //WWDEBUG
return(BUILD_RELEASE);
#endif //WWDEBUG
#else //_DEBUG
return(BUILD_DEBUG);
#endif //_DEBUG
}
/***********************************************************************************************
* BuildInfoClass::Get_Build_Type_String -- Get the build type as a string. *
* *
* *
* *
* INPUT: Nothing *
* *
* OUTPUT: Nothing *
* *
* WARNINGS: None *
* *
* HISTORY: *
* 10/29/2001 7:42PM ST : Created *
*=============================================================================================*/
char *BuildInfoClass::Get_Build_Type_String(void)
{
switch (Get_Build_Type()) {
case BUILD_DEBUG:
return("DEBUG");
case BUILD_RELEASE:
return("RELEASE");
case BUILD_PROFILE:
return("PROFILE");
default:
WWASSERT(false);
return("UNKNOWN");
}
}
/***********************************************************************************************
* BuildInfoClass::Composite_Build_Info -- Get lots of build info *
* *
* *
* *
* INPUT: Nothing *
* *
* OUTPUT: Ptr to info *
* *
* WARNINGS: None *
* *
* HISTORY: *
* 10/29/2001 7:49PM ST : Created *
*=============================================================================================*/
char *BuildInfoClass::Composite_Build_Info(void)
{
static char _buffer[256];
sprintf(_buffer, "%s Build %d by %s - Build time %s", Get_Build_Type_String(), Get_Build_Number(), Get_Builder_Name(), Get_Build_Date_String());
return(_buffer);
}
/***********************************************************************************************
* BuildInfoClass::Log_Build_Info -- Dump build info to the logfile. *
* *
* *
* *
* INPUT: Nothing *
* *
* OUTPUT: Nothing *
* *
* WARNINGS: None *
* *
* HISTORY: *
* 10/29/2001 7:49PM ST : Created *
*=============================================================================================*/
void BuildInfoClass::Log_Build_Info(void)
{
WWDEBUG_SAY((Composite_Build_Info()));
WWDEBUG_SAY(("\n"));
}

112
Code/Commando/buildnum.h Normal file
View File

@@ -0,0 +1,112 @@
/*
** 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/>.
*/
/***********************************************************************************************
*** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : Combat *
* *
* $Archive:: /Commando/Code/Commando/buildnum.h $*
* *
* Author:: Steve Tall *
* *
* $Modtime:: 10/29/01 9:58p $*
* *
* $Revision:: 2 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
/*
**
** This is just a placeholder for the build number.
** A post build step will stamp the build number into here.
**
*/
class BuildInfoClass
{
public:
/*
** Build types.
*/
typedef enum {
BUILD_RELEASE,
BUILD_DEBUG,
BUILD_PROFILE
} BuildType;
/*
** Gets the 32 bit build number.
*/
static unsigned long Get_Build_Number(void);
/*
** Gets the 32 bit build number as a human readable string.
*/
static char *Get_Build_Number_String(void);
/*
** Gets the name of the person who built this executable.
*/
static char *Get_Builder_Name(void);
/*
** Gets the date this executable was built on.
*/
static char *Get_Build_Date_String(void);
/*
** Gets the initials of the person who built this executable.
*/
static char *Get_Builder_Initials(void);
/*
** Get a composite build number string with the works.
*/
static char *Get_Build_Version_String(void);
/*
** Get build type.
*/
static BuildType Get_Build_Type(void);
static char *Get_Build_Type_String(void);
/*
** Dump build info to the log file
*/
static void Log_Build_Info(void);
/*
** Lots of build info together.
*/
static char *Composite_Build_Info(void);
private:
static char BuildNumber [64];
static char BuildDate [64];
};

471
Code/Commando/campaign.cpp Normal file
View File

@@ -0,0 +1,471 @@
/*
** 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/campaign.cpp $*
* *
* $Author:: Ian_l $*
* *
* $Modtime:: 1/19/02 12:30p $*
* *
* $Revision:: 33 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include "campaign.h"
#include "debug.h"
#include "gamemode.h"
#include "gamedata.h"
#include "singlepl.h"
#include "gdsingleplayer.h"
#include "cnetwork.h"
#include "playertype.h"
#include "gameinitmgr.h"
#include "scorescreen.h"
#include "assets.h"
#include "movie.h"
#include "consolefunction.h"
#include "renegadedialogmgr.h"
#include "registry.h"
#include "_globals.h"
#include "crandom.h"
#include "god.h"
#include "dlgloadspgame.h"
#include "ccamera.h"
/*
**
*/
int CampaignManager::State = 0;
int CampaignManager::BackdropIndex = 0;
#define CAMPAIGN_INI_FILENAME "campaign.ini"
#define SECTION_CAMPAIGN "Campaign"
#define NOT_IN_CAMPAIGN_STATE -10
#define REPLAY_LEVEL -11
#define REPLAY_SCORE -12
DynamicVectorClass<StringClass> CampaignFlowDescriptions;
struct BackdropDescriptionStruct {
int State;
DynamicVectorClass<StringClass> Lines;
bool operator == (BackdropDescriptionStruct const & rec) const { return false; }
bool operator != (BackdropDescriptionStruct const & rec) const { return true; }
};
DynamicVectorClass<BackdropDescriptionStruct> BackdropDescriptions;
/*
**
*/
void CampaignManager::Init( void )
{
State = NOT_IN_CAMPAIGN_STATE;
BackdropIndex = 0;
// Load CAMPAIGN.INI to get campain flow
INIClass * campaignINI = Get_INI( CAMPAIGN_INI_FILENAME );
if (campaignINI != NULL) {
WWASSERT( campaignINI && campaignINI->Section_Count() > 0 );
int count = campaignINI->Entry_Count( SECTION_CAMPAIGN );
for ( int entry = 0; entry < count; entry++ ) {
StringClass description(0,true);
campaignINI->Get_String(description, SECTION_CAMPAIGN, campaignINI->Get_Entry( SECTION_CAMPAIGN, entry) );
CampaignFlowDescriptions.Add( description );
}
// Load Backdrop Descriptions
// Load the first 100, because 90-95 are multiplay.. :)
for ( int state = 0; state < 100; state++ ) {
StringClass section_name;
section_name.Format( "Backdrop%d", state );
int count = campaignINI->Entry_Count( section_name );
if ( count != 0 ) {
int index = BackdropDescriptions.Count();
BackdropDescriptions.Uninitialized_Add();
BackdropDescriptions[index].State = state;
for ( int entry = 0; entry < count; entry++ ) {
StringClass description(0,true);
campaignINI->Get_String(description, section_name, campaignINI->Get_Entry( section_name, entry) );
BackdropDescriptions[index].Lines.Add( description );
}
}
}
Release_INI( campaignINI );
} else {
Debug_Say(("CampaignManager::Init - Unable to load %s\n", CAMPAIGN_INI_FILENAME));
}
}
/*
**
*/
void CampaignManager::Shutdown( void )
{
CampaignFlowDescriptions.Clear();
}
/*
**
*/
//-----------------------------------------------------------------------------
enum {
CHUNKID_VARIABLES = 906011356,
MICROCHUNK_STATE = 1,
MICROCHUNK_BACKDROP_INDEX,
};
//-----------------------------------------------------------------------------
bool CampaignManager::Save(ChunkSaveClass & csave)
{
csave.Begin_Chunk(CHUNKID_VARIABLES);
WRITE_MICRO_CHUNK(csave, MICROCHUNK_STATE, State);
WRITE_MICRO_CHUNK(csave, MICROCHUNK_BACKDROP_INDEX, BackdropIndex);
csave.End_Chunk();
return true;
}
//-----------------------------------------------------------------------------
bool CampaignManager::Load(ChunkLoadClass &cload)
{
while (cload.Open_Chunk()) {
switch(cload.Cur_Chunk_ID()) {
case CHUNKID_VARIABLES:
while (cload.Open_Micro_Chunk()) {
switch(cload.Cur_Micro_Chunk_ID()) {
READ_MICRO_CHUNK(cload, MICROCHUNK_STATE, State);
READ_MICRO_CHUNK(cload, MICROCHUNK_BACKDROP_INDEX, BackdropIndex);
default:
Debug_Say(( "Unrecognized Campaign Variable chunkID\n" ));
break;
}
cload.Close_Micro_Chunk();
}
break;
default:
Debug_Say(( "Unrecognized campaign chunkID\n" ));
break;
}
cload.Close_Chunk();
}
return true;
}
/*
**
*/
void CampaignManager::Start_Campaign( int difficulty )
{
Debug_Say(( "CampaignManager::Start_Campaign( %d )\n", difficulty ));
State = -1;
BackdropIndex = 0;
// Why was this commented out???
CombatManager::Set_Difficulty_Level( difficulty );
StringClass diff_string;
diff_string.Format( "difficulty %d", difficulty );
ConsoleFunctionManager::Parse_Input( diff_string );
cGod::Reset_Inventory();
Continue();
}
/*
**
*/
void CampaignManager::Continue( bool success )
{
BackdropIndex = 0;
if ( State == REPLAY_LEVEL ) {
State = REPLAY_SCORE;
// Activeate the Score screen before the combat deactivates, so we can get the stats
ScoreScreenGameModeClass * ss = (ScoreScreenGameModeClass *)GameModeManager::Find ("ScoreScreen");
if ( ss != NULL ) {
ss->Save_Stats();
}
GameModeManager::Find ("Movie")->Deactivate();
GameModeManager::Find ("Combat")->Suspend();
GameInitMgrClass::End_Game();
GameModeManager::Find ("Menu")->Deactivate();
if ( ss != NULL ) {
ss->Activate();
}
return;
}
if ( State == NOT_IN_CAMPAIGN_STATE || State == REPLAY_SCORE || ( State >= CampaignFlowDescriptions.Count() - 1 ) ) {
State = NOT_IN_CAMPAIGN_STATE;
GameModeManager::Find ("Movie")->Deactivate();
GameModeManager::Find ("ScoreScreen")->Deactivate(); // BMG???
GameModeManager::Find ("Combat")->Suspend();
GameInitMgrClass::End_Game();
GameInitMgrClass::Display_End_Game_Menu();
return;
}
State = State+1;
Debug_Say(( "CampaignManager::Continue %d\n", State ));
const char * state_description = CampaignFlowDescriptions[State];
#define StringMatch(a,b) (!::strncmp( a,b,strlen(b) ))
if ( StringMatch( state_description, "Message " ) ) {
state_description += ::strlen( "Message " );
GameModeManager::Find ("Movie")->Deactivate();
GameModeManager::Find ("Combat")->Suspend();
GameInitMgrClass::End_Game();
GameModeManager::Find ("Menu")->Deactivate();
GameModeManager::Find ("ScoreScreen")->Activate();
} else if ( StringMatch( state_description, "Score" ) ) {
state_description += ::strlen( "Score" );
// Activeate the Score screen before the combat deactivates, so we can get the stats
ScoreScreenGameModeClass * ss = (ScoreScreenGameModeClass *)GameModeManager::Find ("ScoreScreen");
if ( ss != NULL ) {
ss->Save_Stats();
}
GameModeManager::Find ("Movie")->Deactivate();
GameModeManager::Find ("Combat")->Suspend();
GameInitMgrClass::End_Game();
GameModeManager::Find ("Menu")->Deactivate();
if ( ss != NULL ) {
ss->Activate();
}
} else if ( StringMatch( state_description, "Level " ) ) {
GameModeManager::Find ("Combat")->Suspend();
GameModeManager::Find ("Movie")->Deactivate();
GameModeManager::Find ("ScoreScreen")->Deactivate ();
GameInitMgrClass::End_Game();
state_description += ::strlen( "Level " );
int mission = cGameData::Get_Mission_Number_From_Map_Name( state_description );
Select_Backdrop_Number( mission );
GameInitMgrClass::Start_Game ( state_description, PLAYERTYPE_RENEGADE, 0 );
// Hack to not autosave for Mission 0 (M13)
if ( ::strnicmp( state_description, "M13", 3 ) != 0 ) {
CombatManager::Request_Autosave();
}
} else if ( StringMatch( state_description, "Movie " ) ) {
if (COMBAT_CAMERA != NULL) {
COMBAT_CAMERA->Set_Host_Model (NULL);
}
GameModeManager::Find ("Combat")->Suspend();
GameInitMgrClass::End_Game();
GameModeManager::Find ("Menu")->Deactivate();
GameModeManager::Find ("ScoreScreen")->Deactivate ();
//
// Parse the parameters
//
int len = ::strlen( state_description );
StringClass foo( len + 1, true );
StringClass filename( len + 1, true );
StringClass description( len + 1, true );
::sscanf (state_description, "%s %s %s", foo.Peek_Buffer (), filename.Peek_Buffer (), description.Peek_Buffer ());
MovieGameModeClass * mode = (MovieGameModeClass *)GameModeManager::Find ("Movie");
if ( mode ) {
mode->Activate();
mode->Start_Movie( filename );
//
// Add this movie name to the registry (that way the user
// can watch it later)
//
RegistryClass registry( APPLICATION_SUB_KEY_NAME_MOVIES );
if ( registry.Is_Valid() ) {
registry.Set_String( filename, description );
}
}
} else {
Debug_Say(( "Failed to Parse Campaign Description %s\n", state_description ));
State = NOT_IN_CAMPAIGN_STATE;
RenegadeDialogMgrClass::Goto_Location (RenegadeDialogMgrClass::LOC_MAIN_MENU);
}
}
void CampaignManager::Reset()
{
State = NOT_IN_CAMPAIGN_STATE;
}
/*
**
*/
void CampaignManager::Replay_Level( const char * mission_name, int difficulty )
{
State = REPLAY_LEVEL;
cGod::Reset_Inventory();
CombatManager::Set_Difficulty_Level( difficulty );
GameInitMgrClass::Start_Game( mission_name, PLAYERTYPE_RENEGADE, 0 );
}
/*
**
*/
int CampaignManager::Get_Backdrop_Description_Count( void )
{
if (BackdropDescriptions.Count() > 0) {
return BackdropDescriptions[BackdropIndex].Lines.Count();
}
return 0;
}
const char * CampaignManager::Get_Backdrop_Description( int index )
{
return BackdropDescriptions[BackdropIndex].Lines[index];
}
void CampaignManager::Select_Backdrop_Number( int state_number )
{
// Find Backdrop Index
BackdropIndex = 0;
for ( int i = 0; i < BackdropDescriptions.Count(); i++ ) {
if ( BackdropDescriptions[i].State == state_number ) {
BackdropIndex = i;
}
}
if ( BackdropIndex == 0 ) {
Debug_Say(( "Failed to find load menu for state %d\n", state_number ));
}
}
void CampaignManager::Select_Backdrop_Number_By_MP_Type( int type )
{
//
// Setup Load Menu
//
/*
#define MULTIPLAY_LOAD_MENU_NUMBER_DEATHMATCH 91
#define MULTIPLAY_LOAD_MENU_NUMBER_TEAM_DEATHMATCH 92
#define MULTIPLAY_LOAD_MENU_NUMBER_CTF 93
#define MULTIPLAY_LOAD_MENU_NUMBER_CNC1 94
#define MULTIPLAY_LOAD_MENU_NUMBER_CNC2 95
int load_menu_number = 0;
if ( type == cGameData::GAME_TYPE_DEATHMATCH ) {
load_menu_number = MULTIPLAY_LOAD_MENU_NUMBER_DEATHMATCH;
}
if ( type == cGameData::GAME_TYPE_TEAM_DEATHMATCH ) {
load_menu_number = MULTIPLAY_LOAD_MENU_NUMBER_TEAM_DEATHMATCH;
}
if ( type == cGameData::GAME_TYPE_CNC ) {
load_menu_number = MULTIPLAY_LOAD_MENU_NUMBER_CNC1;
if ( FreeRandom.Get_Int() & 1 ) {
load_menu_number = MULTIPLAY_LOAD_MENU_NUMBER_CNC2;
}
}
Select_Backdrop_Number( load_menu_number );
*/
WWASSERT(type == cGameData::GAME_TYPE_CNC);
#define MULTIPLAY_LOAD_MENU_NUMBER_CNC1 94
#define MULTIPLAY_LOAD_MENU_NUMBER_CNC2 95
int load_menu_number = 0;
if (FreeRandom.Get_Int() & 1) {
load_menu_number = MULTIPLAY_LOAD_MENU_NUMBER_CNC1;
} else {
load_menu_number = MULTIPLAY_LOAD_MENU_NUMBER_CNC2;
}
// Select_Backdrop_Number(load_menu_number);
//forget the random screen, alwayds do 94 (BMG 11/24/01)
Select_Backdrop_Number( MULTIPLAY_LOAD_MENU_NUMBER_CNC1 );
}
/*
if ( type == cGameData::GAME_TYPE_CTF ) {
load_menu_number = MULTIPLAY_LOAD_MENU_NUMBER_CTF;
}
*/

79
Code/Commando/campaign.h Normal file
View File

@@ -0,0 +1,79 @@
/*
** 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/campaign.h $*
* *
* $Author:: Byon_g $*
* *
* $Modtime:: 12/01/01 12:02p $*
* *
* $Revision:: 8 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#ifndef CAMPAIGN_H
#define CAMPAIGN_H
#ifndef ALWAYS_H
#include "always.h"
#endif
class ChunkSaveClass;
class ChunkLoadClass;
/*
** CampaignManager is responsible for controlling the flow of missions and sub-states through
** the playing of a campaign. It also is the main entry point for single mission, and multi-play sessions.
*/
class CampaignManager {
public:
static void Init( void );
static void Shutdown( void );
static bool Save(ChunkSaveClass & csave);
static bool Load(ChunkLoadClass &cload);
static void Start_Campaign( int difficulty );
static void Continue( bool success = true );
static void Reset();
// Backdrop Descriptions
static int Get_Backdrop_Description_Count( void );
static const char * Get_Backdrop_Description( int index );
static void Select_Backdrop_Number( int state_number );
static void Select_Backdrop_Number_By_MP_Type( int type );
static void Replay_Level( const char * mission_name, int difficulty );
private:
static int State;
static int BackdropIndex;
};
#endif

194
Code/Commando/cdverify.cpp Normal file
View File

@@ -0,0 +1,194 @@
/*
** 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/>.
*/
/***********************************************************************************************
*** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : commando *
* *
* $Archive:: /Commando/Code/commando/cdverify.cpp $*
* *
* Author:: Patrick Smith *
* *
* $Modtime:: 1/03/02 9:57a $*
* *
* $Revision:: 7 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include "always.h"
#include "cdverify.h"
#include "wwstring.h"
#include "popupdialog.h"
#include "resource.h"
//////////////////////////////////////////////////////////////////////
// Local constants
//////////////////////////////////////////////////////////////////////
static const char *RENEGADE_MOVIES_VOLUME = "Renegade Data";
////////////////////////////////////////////////////////////////
//
// CDVerifyDialogClass
//
////////////////////////////////////////////////////////////////
class CDVerifyDialogClass : public PopupDialogClass
{
public:
////////////////////////////////////////////////////////////////
// Public constructors/destructors
////////////////////////////////////////////////////////////////
CDVerifyDialogClass (void) :
Object (NULL),
PopupDialogClass (IDD_CDVERIFY) {}
void On_Command (int ctrl_id, int mesage_id, DWORD param);
void Set_Object (CDVerifyClass *object) { Object = object; }
private:
////////////////////////////////////////////////////////////////
// Private member data
////////////////////////////////////////////////////////////////
CDVerifyClass * Object;
};
//////////////////////////////////////////////////////////////////////
//
// Get_CD_Path
//
//////////////////////////////////////////////////////////////////////
bool
CDVerifyClass::Get_CD_Path (StringClass &drive_path)
{
bool retval = false;
char buffer[1024] = { 0 };
::GetLogicalDriveStrings (sizeof (buffer), buffer);
//
// Loop over all the drives
//
const char *drive_root_name = buffer;
while (drive_root_name[0] != 0) {
//
// Only check CD drives
//
if (::GetDriveType (drive_root_name) == DRIVE_CDROM) {
//
// Get the name of this volume
//
char volume_name[256] = { 0 };
if (::GetVolumeInformation (drive_root_name, volume_name, sizeof (volume_name),
NULL, NULL, NULL, NULL, NULL))
{
int cmp_len = ::lstrlen (volume_name);
cmp_len = max (cmp_len, 11);
//
// Is this the movies CD?
//
if (::strnicmp (volume_name, RENEGADE_MOVIES_VOLUME, cmp_len) == 0) {
retval = true;
drive_path = drive_root_name;
break;
}
}
}
//
// Advance to the next drive
//
drive_root_name += ::lstrlen (drive_root_name) + 1;
}
return retval;
}
//////////////////////////////////////////////////////////////////////
//
// Get_CD_Path
//
//////////////////////////////////////////////////////////////////////
void
CDVerifyClass::Display_UI (Observer<CDVerifyEvent> *observer)
{
AddObserver (*observer);
//
// Display the dialog
//
CDVerifyDialogClass *dialog = new CDVerifyDialogClass;
dialog->Set_Object (this);
dialog->Start_Dialog ();
REF_PTR_RELEASE (dialog);
return ;
}
////////////////////////////////////////////////////////////////
//
// On_Command
//
////////////////////////////////////////////////////////////////
void
CDVerifyDialogClass::On_Command (int ctrl_id, int message_id, DWORD param)
{
//
// Check to see if the CD is in the drive now...
///
if (ctrl_id == IDOK) {
StringClass path;
if (Object->Get_CD_Path (path)) {
//
// Notify anybody who cares that the CD is in the drive
//
CDVerifyEvent event (CDVerifyEvent::VERIFIED, Object);
Object->NotifyObservers (event);
//
// Close the dialog
//
End_Dialog ();
}
} else if (ctrl_id == IDCANCEL) {
//
// Notify anybody who cares that the user has cancelled the operation
//
CDVerifyEvent event (CDVerifyEvent::NOT_VERIFIED, Object);
Object->NotifyObservers (event);
//
// Close the dialog
//
End_Dialog ();
}
PopupDialogClass::On_Command (ctrl_id, message_id, param);
return ;
}

129
Code/Commando/cdverify.h Normal file
View File

@@ -0,0 +1,129 @@
/*
** 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/>.
*/
/***********************************************************************************************
*** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : commando *
* *
* $Archive:: /Commando/Code/commando/cdverify.h $*
* *
* Author:: Patrick Smith *
* *
* $Modtime:: 9/19/01 9:22a $*
* *
* $Revision:: 3 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#if defined(_MSC_VER)
#pragma once
#endif
#ifndef __CDVERIFY_H
#define __CDVERIFY_H
#include "notify.h"
//////////////////////////////////////////////////////////////////////
// Forward declarations
//////////////////////////////////////////////////////////////////////
class StringClass;
class CDVerifyClass;
//////////////////////////////////////////////////////////////////////
//
// CDVerifyEvent
//
//////////////////////////////////////////////////////////////////////
class CDVerifyEvent : public TypedEventPtr<CDVerifyEvent, CDVerifyClass>
{
public:
///////////////////////////////////////////////////////////////////
// Public constants
///////////////////////////////////////////////////////////////////
typedef enum
{
NOT_VERIFIED = 0,
VERIFIED,
} EventID;
///////////////////////////////////////////////////////////////////
// Public constructors/destructors
///////////////////////////////////////////////////////////////////
CDVerifyEvent (EventID event, CDVerifyClass *object) :
TypedEventPtr<CDVerifyEvent, CDVerifyClass>(object),
MyEventID (event) {}
~CDVerifyEvent (void) {}
///////////////////////////////////////////////////////////////////
// Public methods
///////////////////////////////////////////////////////////////////
//
// Inherited
//
inline EventID Event (void) const { return MyEventID; }
private:
///////////////////////////////////////////////////////////////////
// Private member data
///////////////////////////////////////////////////////////////////
EventID MyEventID;
};
//////////////////////////////////////////////////////////////////////
//
// CDVerifyClass
//
//////////////////////////////////////////////////////////////////////
class CDVerifyClass : public Notifier<CDVerifyEvent>
{
public:
///////////////////////////////////////////////////////////////////
// Public constructors/destructors
///////////////////////////////////////////////////////////////////
CDVerifyClass (void) {}
~CDVerifyClass (void) {}
///////////////////////////////////////////////////////////////////
// Public methods
///////////////////////////////////////////////////////////////////
bool Get_CD_Path (StringClass &drive_path);
void Display_UI (Observer<CDVerifyEvent> *observer);
private:
///////////////////////////////////////////////////////////////////
// Private member data
///////////////////////////////////////////////////////////////////
};
#endif //__CDVERIFY_H

View File

@@ -0,0 +1,233 @@
/*
** 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/changeteamevent.cpp $*
* *
* $Author:: Patrick $*
* *
* $Modtime:: 1/17/02 3:30p $*
* *
* $Revision:: 22 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include "changeteamevent.h"
#include <stdio.h>
#include <stdlib.h>
#include "networkobjectfactory.h"
#include "cnetwork.h"
#include "networkobjectmgr.h"
#include "playertype.h"
#include "playermanager.h"
#include "gamemode.h"
#include "gamedata.h"
#include "gameobjmanager.h"
#include "spawn.h"
#include "apppackettypes.h"
#include "sctextobj.h"
#include "translatedb.h"
#include "string_ids.h"
#include "c4.h"
#include "beacongameobj.h"
#include "weaponview.h"
DECLARE_NETWORKOBJECT_FACTORY(cChangeTeamEvent, NETCLASSID_CHANGETEAMEVENT);
//-----------------------------------------------------------------------------
cChangeTeamEvent::cChangeTeamEvent(void)
{
SenderId = 0;
Set_App_Packet_Type(APPPACKETTYPE_CHANGETEAMEVENT);
}
//-----------------------------------------------------------------------------
void
cChangeTeamEvent::Init(void)
{
WWASSERT(cNetwork::I_Am_Client());
SenderId = cNetwork::Get_My_Id();
Set_Network_ID(NetworkObjectMgrClass::Get_New_Client_ID());
if (cNetwork::I_Am_Server()) {
Act();
} else {
Set_Object_Dirty_Bit(0, BIT_CREATION, true);
}
}
//-----------------------------------------------------------------------------
void
cChangeTeamEvent::Act(void)
{
WWASSERT(cNetwork::I_Am_Server());
cPlayer * p_player = cPlayerManager::Find_Player(SenderId);
if (p_player != NULL &&
The_Game() != NULL &&
//The_Game()->Is_Team_Game() &&
(The_Game()->IsTeamChangingAllowed.Is_True() || p_player->Invulnerable.Is_True()))
{
int team = p_player->Get_Player_Type();
WWASSERT(team == PLAYERTYPE_NOD || team == PLAYERTYPE_GDI);
int new_team = PLAYERTYPE_NOD;
if (team == PLAYERTYPE_NOD)
{
new_team = PLAYERTYPE_GDI;
}
else
{
new_team = PLAYERTYPE_NOD;
}
p_player->Set_Player_Type(new_team);
WWDEBUG_SAY(("Client %d changed team.\n", SenderId));
//
// Only reset the player's cash if they've changed teams after 60 seconds
// have elapsed.
//
DWORD playing_time = (TIMEGETTIME() - p_player->Get_Join_Time ());
if (playing_time > 30000) {
p_player->Set_Score(0);
p_player->Set_Money(0);
}
SoldierGameObj * p_soldier = GameObjManager::Find_Soldier_Of_Client_ID(SenderId);
if (p_soldier != NULL)
{
if ( COMBAT_STAR == p_soldier ) {
WeaponViewClass::Reset();
}
// Defuse all C4 belonging to this guy
SLNode<BaseGameObj> *objnode;
for ( objnode = GameObjManager::Get_Game_Obj_List()->Head(); objnode; objnode = objnode->Next()) {
PhysicalGameObj *obj = objnode->Data()->As_PhysicalGameObj();
if ( obj && obj->As_C4GameObj() ) {
if ( obj->As_C4GameObj()->Get_Owner() == p_soldier ) {
obj->As_C4GameObj()->Defuse();
}
}
if ( obj && obj->As_BeaconGameObj() ) {
if ( obj->As_BeaconGameObj()->Get_Owner() == p_soldier ) {
// disarm C4
OffenseObjectClass unused (0.0F, 0);
obj->As_BeaconGameObj()->Completely_Damaged( unused );
}
}
}
//
// We have to respawn him and possibly change his model...
// let's just destroy the soldier and leave the rest up to God.
//
p_soldier->Set_Delete_Pending();
}
//
// Tell everyone
//
WideStringClass text;
//text.Format(L"_%s_changed_teams!_", p_player->Get_Name());
text.Format(L"%s %s", p_player->Get_Name(), TRANSLATE(IDS_MP_CHANGED_TEAMS));
cScTextObj * p_message = new cScTextObj;
p_message->Init(text, TEXT_MESSAGE_PUBLIC, false, HOST_TEXT_SENDER, -1);
}
Set_Delete_Pending();
}
//-----------------------------------------------------------------------------
void
cChangeTeamEvent::Export_Creation(BitStreamClass & packet)
{
WWASSERT(cNetwork::I_Am_Only_Client());
cNetEvent::Export_Creation(packet);
WWASSERT(SenderId > 0);
packet.Add(SenderId);
Set_Delete_Pending();
}
//-----------------------------------------------------------------------------
void
cChangeTeamEvent::Import_Creation(BitStreamClass & packet)
{
WWASSERT(cNetwork::I_Am_Server());
cNetEvent::Import_Creation(packet);
packet.Get(SenderId);
WWASSERT(SenderId > 0);
Act();
}
//-----------------------------------------------------------------------------
bool
cChangeTeamEvent::Is_Change_Team_Possible(void)
{
return
cNetwork::I_Am_Client() &&
GameModeManager::Find("Combat") != NULL &&
GameModeManager::Find("Combat")->Is_Active() &&
The_Game() != NULL &&
//The_Game()->Is_Team_Game() &&
The_Game()->IsTeamChangingAllowed.Is_True();
}

View File

@@ -0,0 +1,70 @@
/*
** 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/changeteamevent.h $*
* *
* $Author:: Tom_s $*
* *
* $Modtime:: 9/21/01 2:42p $*
* *
* $Revision:: 2 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#ifndef __CHANGETEAMEVENT_H__
#define __CHANGETEAMEVENT_H__
#include "netevent.h"
#include "netclassids.h"
//-----------------------------------------------------------------------------
//
// A C->S mirrored object for player changing team
//
class cChangeTeamEvent : public cNetEvent
{
public:
cChangeTeamEvent(void);
void Init(void);
virtual void Export_Creation(BitStreamClass &packet);
virtual void Import_Creation(BitStreamClass &packet);
virtual uint32 Get_Network_Class_ID(void) const {return NETCLASSID_CHANGETEAMEVENT;}
static bool Is_Change_Team_Possible(void);
private:
virtual void Act(void);
int SenderId;
};
//-----------------------------------------------------------------------------
#endif // __CHANGETEAMEVENT_H__

3576
Code/Commando/chat.rc Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,56 @@
/*
** 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/>.
*/
//
// Filename: chatshre.cpp
// Project: Network.lib, for Commando
// Author: Tom Spencer-Smith
// Date: Dec 1998
// Description:
//
//-----------------------------------------------------------------------------
#include "chatshre.h"
#include "wwdebug.h"
//-----------------------------------------------------------------------------
#define ADD_CASE(exp) case exp: return #exp; break;
LPCSTR Translate_Location(ChatLocationEnum location)
{
switch (location) {
ADD_CASE(WOLLOC_EXIT);
ADD_CASE(WOLLOC_NOLIST);
ADD_CASE(WOLLOC_LOBBYLIST);
ADD_CASE(WOLLOC_LOBBY);
ADD_CASE(WOLLOC_GAMESLIST);
ADD_CASE(WOLLOC_GAMEDATA);
ADD_CASE(WOLLOC_INGAME);
ADD_CASE(LANLOC_EXIT);
ADD_CASE(LANLOC_LOBBY);
ADD_CASE(LANLOC_GAMESLIST);
ADD_CASE(LANLOC_GAMEDATA);
ADD_CASE(LANLOC_INGAME);
default:
WWASSERT(0);
return ""; // to avoid compiler warning
}
}

65
Code/Commando/chatshre.h Normal file
View File

@@ -0,0 +1,65 @@
/*
** 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/>.
*/
//
// Filename: chatshre.h
// Project: Network.lib, for Commando
// Author: Tom Spencer-Smith
// Date: Dec 1998
// Description:
//
//-----------------------------------------------------------------------------
#if defined(_MSV_VER)
#pragma once
#endif
#ifndef CHATSHRE_H
#define CHATSHRE_H
#include "bittype.h"
//-----------------------------------------------------------------------------
enum ChatLocationEnum {
//
// Wol interface
//
WOLLOC_EXIT,
WOLLOC_NOLIST,
WOLLOC_LOBBYLIST,
WOLLOC_LOBBY,
WOLLOC_GAMESLIST,
WOLLOC_GAMEDATA,
WOLLOC_INGAME,
//
// Lan interface
//
LANLOC_EXIT,
LANLOC_LOBBY,
LANLOC_GAMESLIST,
LANLOC_GAMEDATA,
LANLOC_INGAME,
};
LPCSTR Translate_Location(ChatLocationEnum location);
//-----------------------------------------------------------------------------
#endif // CHATSHRE_H

View File

@@ -0,0 +1,126 @@
/*
** 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/clientbboevent.cpp $*
* *
* $Author:: Tom_s $*
* *
* $Modtime:: 11/27/01 3:12p $*
* *
* $Revision:: 5 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include "clientbboevent.h"
#include <stdio.h>
#include <stdlib.h>
#include "networkobjectfactory.h"
#include "cnetwork.h"
#include "networkobjectmgr.h"
#include "gameobjmanager.h"
#include "apppackettypes.h"
DECLARE_NETWORKOBJECT_FACTORY(cClientBboEvent, NETCLASSID_CLIENTBBOEVENT);
//-----------------------------------------------------------------------------
cClientBboEvent::cClientBboEvent(void)
{
SenderId = 0;
Bbo = 0;
Set_App_Packet_Type(APPPACKETTYPE_CLIENTBBOEVENT);
}
//-----------------------------------------------------------------------------
void
cClientBboEvent::Init(int bbo)
{
WWASSERT(cNetwork::I_Am_Client());
//WWASSERT(bbo > 0);
SenderId = cNetwork::Get_My_Id();
Bbo = bbo;
Set_Network_ID(NetworkObjectMgrClass::Get_New_Client_ID());
if (cNetwork::I_Am_Server()) {
Act();
} else {
Set_Object_Dirty_Bit(0, BIT_CREATION, true);
}
}
//-----------------------------------------------------------------------------
void
cClientBboEvent::Act(void)
{
WWASSERT(cNetwork::I_Am_Server());
cRemoteHost * p_rhost = cNetwork::Get_Server_Rhost(SenderId);
if (p_rhost != NULL) {
p_rhost->Set_Maximum_Bps(Bbo);
WWDEBUG_SAY(("Client %d adjusted bbo to %d.\n", SenderId, Bbo));
}
Set_Delete_Pending();
}
//-----------------------------------------------------------------------------
void
cClientBboEvent::Export_Creation(BitStreamClass & packet)
{
WWASSERT(cNetwork::I_Am_Only_Client());
cNetEvent::Export_Creation(packet);
WWASSERT(SenderId > 0);
WWASSERT(Bbo > 0);
packet.Add(SenderId);
packet.Add(Bbo);
Set_Delete_Pending();
}
//-----------------------------------------------------------------------------
void
cClientBboEvent::Import_Creation(BitStreamClass & packet)
{
WWASSERT(cNetwork::I_Am_Server());
cNetEvent::Import_Creation(packet);
packet.Get(SenderId);
packet.Get(Bbo);
WWASSERT(SenderId > 0);
WWASSERT(Bbo > 0);
Act();
}

View File

@@ -0,0 +1,69 @@
/*
** 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/clientbboevent.h $*
* *
* $Author:: Tom_s $*
* *
* $Modtime:: 9/21/01 2:42p $*
* *
* $Revision:: 2 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#ifndef __CLIENTBBOEVENT_H__
#define __CLIENTBBOEVENT_H__
#include "netevent.h"
#include "netclassids.h"
//-----------------------------------------------------------------------------
//
// A C->S mirrored object for client bandwidth adjustment
//
class cClientBboEvent : public cNetEvent
{
public:
cClientBboEvent(void);
void Init(int bbo);
virtual void Export_Creation(BitStreamClass &packet);
virtual void Import_Creation(BitStreamClass &packet);
virtual uint32 Get_Network_Class_ID(void) const {return NETCLASSID_CLIENTBBOEVENT;}
private:
virtual void Act(void);
int SenderId;
int Bbo;
};
//-----------------------------------------------------------------------------
#endif // __CLIENTBBOEVENT_H__

150
Code/Commando/clientfps.cpp Normal file
View File

@@ -0,0 +1,150 @@
/*
** 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/clientfps.cpp $*
* *
* $Author:: Tom_s $*
* *
* $Modtime:: 9/20/01 11:28a $*
* *
* $Revision:: 2 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include "clientfps.h"
#include "networkobjectfactory.h"
#include "networkobjectmgr.h"
#include "cnetwork.h"
#include "playermanager.h"
#include "apppackettypes.h"
CClientFps * PClientFps = NULL;
DECLARE_NETWORKOBJECT_FACTORY(CClientFps, NETCLASSID_CLIENTFPS);
#pragma message("(TSS) high priority for me to fix this CClientFps bug...")
//
// TSS2001 problem: destruction of this object on the server. Quitting and rejoining
// a game will crash the server.
//
//-----------------------------------------------------------------------------
CClientFps::CClientFps(void)
{
ClientId = -1;
Fps = 0;
Set_App_Packet_Type(APPPACKETTYPE_CLIENTFPS);
}
//-----------------------------------------------------------------------------
CClientFps::~CClientFps(void)
{
}
//-----------------------------------------------------------------------------
void
CClientFps::Init(void)
{
WWASSERT(cNetwork::I_Am_Client());
ClientId = cNetwork::Get_My_Id();
Set_Network_ID(NetworkObjectMgrClass::Get_New_Client_ID());
Set_Object_Dirty_Bit(0, NetworkObjectClass::BIT_CREATION, true);
}
//-----------------------------------------------------------------------------
void
CClientFps::Set_Fps(int fps)
{
WWASSERT(cNetwork::I_Am_Client());
WWASSERT(fps >= 0);
Fps = (BYTE) fps;
Set_Object_Dirty_Bit(0, NetworkObjectClass::BIT_FREQUENT, true);
}
//-----------------------------------------------------------------------------
void
CClientFps::Act(void)
{
WWASSERT(cNetwork::I_Am_Server());
cPlayer * p_player = cPlayerManager::Find_Player(ClientId);
if (p_player != NULL)
{
p_player->Set_Fps(Fps);
}
}
//-----------------------------------------------------------------------------
void
CClientFps::Export_Creation(BitStreamClass & packet)
{
WWASSERT(cNetwork::I_Am_Client());
NetworkObjectClass::Export_Creation(packet);
packet.Add(ClientId);
}
//-----------------------------------------------------------------------------
void
CClientFps::Import_Creation(BitStreamClass & packet)
{
WWASSERT(cNetwork::I_Am_Server());
NetworkObjectClass::Import_Creation(packet);
packet.Get(ClientId);
}
//-----------------------------------------------------------------------------
void
CClientFps::Export_Frequent(BitStreamClass & packet)
{
WWASSERT(cNetwork::I_Am_Client());
packet.Add(Fps);
}
//-----------------------------------------------------------------------------
void
CClientFps::Import_Frequent(BitStreamClass & packet)
{
WWASSERT(cNetwork::I_Am_Server());
packet.Get(Fps);
Act();
}

80
Code/Commando/clientfps.h Normal file
View File

@@ -0,0 +1,80 @@
/*
** 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/clientfps.h $*
* *
* $Author:: Tom_s $*
* *
* $Modtime:: 9/18/01 5:12p $*
* *
* $Revision:: 1 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#ifndef __CLIENTFPS_H__
#define __CLIENTFPS_H__
#include "networkobject.h"
#include "netclassids.h"
//#include "control.h"
//-----------------------------------------------------------------------------
//
// A C-S mirrored object to inform server of client framerate
//
class CClientFps : public NetworkObjectClass
{
public:
CClientFps();
~CClientFps();
void Init(void);
virtual uint32 Get_Network_Class_ID(void) const {return NETCLASSID_CLIENTFPS;}
virtual void Delete(void) {delete this;}
void Set_Fps(int fps);
void Act(void);
virtual void Export_Creation(BitStreamClass &packet);
virtual void Import_Creation(BitStreamClass &packet);
virtual void Export_Frequent(BitStreamClass &packet);
virtual void Import_Frequent(BitStreamClass &packet);
private:
int ClientId;
BYTE Fps;
};
//-----------------------------------------------------------------------------
extern CClientFps * PClientFps;
//-----------------------------------------------------------------------------
#endif // __CLIENTFPS_H__

View File

@@ -0,0 +1,133 @@
/*
** 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/clientgoodbyeevent.cpp $*
* *
* $Author:: Tom_s $*
* *
* $Modtime:: 10/10/01 4:53p $*
* *
* $Revision:: 6 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include "clientgoodbyeevent.h"
#include "networkobjectfactory.h"
#include "cnetwork.h"
#include "networkobjectmgr.h"
#include "apppackettypes.h"
//
// TSS2001 Problem - we have lost the unreliable multiblast effect for this message
//
DECLARE_NETWORKOBJECT_FACTORY(cClientGoodbyeEvent, NETCLASSID_CLIENTGOODBYEEVENT);
//-----------------------------------------------------------------------------
cClientGoodbyeEvent::cClientGoodbyeEvent(void)
{
WWDEBUG_SAY(("cClientGoodbyeEvent::cClientGoodbyeEvent\n"));
SenderId = -1;
Set_App_Packet_Type(APPPACKETTYPE_CLIENTGOODBYEEVENT);
}
//-----------------------------------------------------------------------------
void
cClientGoodbyeEvent::Init(void)
{
WWDEBUG_SAY(("cClientGoodbyeEvent::Init\n"));
WWASSERT(cNetwork::I_Am_Client());
SenderId = cNetwork::Get_My_Id();
Set_Network_ID(NetworkObjectMgrClass::Get_New_Client_ID());
if (cNetwork::I_Am_Server()) {
Act();
} else {
Set_Object_Dirty_Bit(0, BIT_CREATION, true);
}
}
//-----------------------------------------------------------------------------
void
cClientGoodbyeEvent::Act(void)
{
WWDEBUG_SAY(("cClientGoodbyeEvent::Act\n"));
WWASSERT(cNetwork::I_Am_Server());
WWASSERT(SenderId > 0);
Set_Delete_Pending();
//
// TSS092101 - crashy.
// This cleanup probably deletes *this* object...
//
/**/
cNetwork::Server_Kill_Connection(SenderId);
cNetwork::Cleanup_After_Client(SenderId);
/**/
}
//-----------------------------------------------------------------------------
void
cClientGoodbyeEvent::Export_Creation(BitStreamClass & packet)
{
WWDEBUG_SAY(("cClientGoodbyeEvent::Export_Creation\n"));
WWASSERT(cNetwork::I_Am_Only_Client());
cNetEvent::Export_Creation(packet);
WWASSERT(SenderId > 0);
packet.Add(SenderId);
Set_Delete_Pending();
}
//-----------------------------------------------------------------------------
void
cClientGoodbyeEvent::Import_Creation(BitStreamClass & packet)
{
WWDEBUG_SAY(("cClientGoodbyeEvent::Import_Creation\n"));
WWASSERT(cNetwork::I_Am_Server());
cNetEvent::Import_Creation(packet);
packet.Get(SenderId);
WWASSERT(SenderId > 0);
Act();
}

View File

@@ -0,0 +1,67 @@
/*
** 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/clientgoodbyeevent.h $*
* *
* $Author:: Tom_s $*
* *
* $Modtime:: 9/21/01 2:42p $*
* *
* $Revision:: 2 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#ifndef __CLIENTGOODBYEEVENT_H__
#define __CLIENTGOODBYEEVENT_H__
#include "netevent.h"
#include "netclassids.h"
//-----------------------------------------------------------------------------
//
// A C->S mirrored object to represent client destruction
//
class cClientGoodbyeEvent : public cNetEvent
{
public:
cClientGoodbyeEvent(void);
void Init(void);
virtual void Export_Creation(BitStreamClass &packet);
virtual void Import_Creation(BitStreamClass &packet);
virtual uint32 Get_Network_Class_ID(void) const {return NETCLASSID_CLIENTGOODBYEEVENT;}
private:
virtual void Act(void);
int SenderId;
};
//-----------------------------------------------------------------------------
#endif // __CLIENTGOODBYEEVENT_H__

View File

@@ -0,0 +1,293 @@
/*
** 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/clienthintmanager.cpp $*
* *
* $Author:: Steve_t $*
* *
* $Modtime:: 12/09/01 6:40p $*
* *
* $Revision:: 6 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include "clienthintmanager.h"
#include "cshint.h"
#include "cnetwork.h"
#include "combat.h"
#include "gameobjmanager.h"
#include "pscene.h"
#include "apppackettypes.h"
#include "vistable.h"
#include "useroptions.h"
#include "priority.h"
#include "apppacketstats.h"
//
// Class statics
//
//-----------------------------------------------------------------------------
void
cClientHintManager::Think
(
void
)
{
if (cNetwork::I_Am_Server() ||
COMBAT_SCENE == NULL ||
cUserOptions::ClientHintFactor.Get() < 1)
{
//
// Bail:
// Only dedicated clients send hints.
// Also, ClientHintFactor is disabled by using any value < 1.
//
return;
}
WWASSERT(cNetwork::I_Am_Only_Client());
SoldierGameObj * p_my_soldier = GameObjManager::Find_Soldier_Of_Client_ID(cNetwork::Get_My_Id());
if (p_my_soldier == NULL)
{
//
// Bail...
//
return;
}
//
// Do not allow hints to go out at too high a frequency.
//
static DWORD last_hint_time_ms = 0;
DWORD time_now_ms = TIMEGETTIME();
const DWORD MIN_HINT_DELAY_MS = 1000;
if (time_now_ms - last_hint_time_ms < MIN_HINT_DELAY_MS)
{
//
// Bail...
//
return;
}
//
// Examine all the vis-visible soldiers and vehicles. If we find one that hasn't been
// updated for a suspiciously long time, send a hint to the server, He'll follow
// up with an update.
//
Vector3 my_position;
p_my_soldier->Get_Position(&my_position);
my_position.Z += 1.5;
VisTableClass * pvs = COMBAT_SCENE->Get_Vis_Table(my_position);
int num_objects = 0;
//ULONG total_delay_ms = 0;
//ULONG maximum_delay_ms = 0;
//int longest_delayed_index = -1;
int count = NetworkObjectMgrClass::Get_Object_Count();
NetworkObjectClass **object_list = (NetworkObjectClass **) _alloca((count * sizeof(NetworkObjectClass*)) + 128);
WWASSERT(object_list != NULL);
SmartGameObj * player_ptr = GameObjManager::Find_Soldier_Of_Client_ID(cNetwork::Get_My_Id());
WWASSERT(player_ptr != NULL);
//
// Traverse the vehicles and soldiers and gather data about update rates.
//
for (int index = 0; index < count; index ++)
{
NetworkObjectClass * p_object = NetworkObjectMgrClass::Get_Object(index);
WWASSERT(p_object != NULL);
BYTE type = p_object->Get_App_Packet_Type();
if (type == APPPACKETTYPE_SOLDIER || type == APPPACKETTYPE_VEHICLE)
{
if (p_object->Get_Clientside_Update_Frequency()) {
int vis_id = p_object->Get_Vis_ID();
//
// If there is no vis data, proceed.
// If vis data does exist then only proceed with this object if it is vis-visible.
//
if (pvs == NULL || vis_id == -1 || pvs->Get_Bit(vis_id))
{
// Just add the object to the list on this pass.
object_list[num_objects++] = p_object;
// Work out the priority of this object from the clients perspective.
if (player_ptr) {
Vector3 position;
player_ptr->Get_Position(&position);
float priority = cPriority::Compute_Object_Priority(cNetwork::Get_My_Id(), position, p_object, true);
p_object->Set_Cached_Priority(priority);
}
#if (0)
ULONG delay_ms = time_now_ms - p_object->Get_Last_Clientside_Update_Time();
total_delay_ms += delay_ms;
num_objects++;
if (delay_ms > maximum_delay_ms)
{
maximum_delay_ms = delay_ms;
longest_delayed_index = index;
}
#endif //(0)
}
}
}
}
if (num_objects < 2) {
return;
}
//
// Sort the object list. Lowest priority first.
//
qsort(object_list, num_objects, sizeof(unsigned long), (int (__cdecl *)(const void *,const void *)) &Priority_Compare);
//
// Look for an object that has a higher priority than it's neighbor but is getting updated much less frequently
//
// Ignore the worst priority object. This might have to change....?
//
int most_broken_object_index = -1;
int worst_percentage = 0;
unsigned long time = TIMEGETTIME();
for (int i=1 ; i<num_objects ; i++) {
int higher_priority_rate = object_list[i]->Get_Clientside_Update_Frequency();
//
// Don't hint for objects with a recent updates. This should prevent us from hinting about objects we just hinted about.
//
if (time - object_list[i]->Get_Last_Clientside_Update_Time() > 1500) {
int lower_priority_rate = object_list[i-1]->Get_Clientside_Update_Frequency();
if (lower_priority_rate && higher_priority_rate) {
// Lower priority rate should be higher in terms of milliseconds.
if (lower_priority_rate < higher_priority_rate) {
// The higher priority object is being updated by the server less frequently. That doesn't seem right.
int percentage = (higher_priority_rate * 100) / lower_priority_rate;
if (percentage > worst_percentage) {
worst_percentage = percentage;
most_broken_object_index = i;
}
}
}
}
}
//
// Calculate the average delay for this set of soldiers and vehicles
//
//float average_delay_ms = 0;
//if (num_objects > 0)
//{
// average_delay_ms = total_delay_ms / (float) num_objects;
//}
//
// If the most OOD object is much more OOD than the average object, then request an update.
//
//if ((longest_delayed_index != -1) &&
// (maximum_delay_ms > cUserOptions::ClientHintFactor.Get() * average_delay_ms))
//{
float hint_factor = cUserOptions::ClientHintFactor.Get();
if (most_broken_object_index != -1 && worst_percentage > 100 + (10.0f * hint_factor)) {
//NetworkObjectClass * p_object = NetworkObjectMgrClass::Get_Object(longest_delayed_index);
NetworkObjectClass * p_object = object_list[most_broken_object_index];
WWASSERT(p_object != NULL);
cCsHint * p_hint = new cCsHint;
p_hint->Init(p_object->Get_Network_ID());
last_hint_time_ms = time_now_ms;
//WWDEBUG_SAY(("cClientHintManager::Think, requesting hint for object id %d, avg = %5.2f, max = %d\n",
// p_object->Get_Network_ID(), average_delay_ms, maximum_delay_ms));
WWDEBUG_SAY(("cClientHintManager::Think, requesting hint for object id %d (%s), priority = %5.2f, ave update rate = %dms\n",
p_object->Get_Network_ID(),
cAppPacketStats::Interpret_Type(p_object->Get_App_Packet_Type()),
p_object->Get_Cached_Priority(),
p_object->Get_Clientside_Update_Frequency()));
WWDEBUG_SAY((" Compared to object id %d with priority %5.2f, avg update rate %dms\n",
object_list[most_broken_object_index-1]->Get_Network_ID(),
object_list[most_broken_object_index-1]->Get_Cached_Priority(),
object_list[most_broken_object_index-1]->Get_Clientside_Update_Frequency()));
WWDEBUG_SAY((" Client hint factor = %5.2f\n", hint_factor));
}
}
//
// Qsort compare function for array of object pointers.
//
int __cdecl cClientHintManager::Priority_Compare(const void **object1, const void **object2)
{
WWASSERT(object1 != NULL);
WWASSERT(object2 != NULL);
NetworkObjectClass *n1 = (NetworkObjectClass*) *object1;
NetworkObjectClass *n2 = (NetworkObjectClass*) *object2;
float p1 = n1->Get_Cached_Priority();
float p2 = n2->Get_Cached_Priority();
if (p1 == p2) {
return(0);
}
if (p1 < p2) {
return(-1);
}
return(1);
}

View File

@@ -0,0 +1,58 @@
/*
** 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/clienthintmanager.h $*
* *
* $Author:: Steve_t $*
* *
* $Modtime:: 10/19/01 3:01p $*
* *
* $Revision:: 2 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#ifndef __CLIENTHINTMANAGER_H__
#define __CLIENTHINTMANAGER_H__
#include "vector.h"
class NetworkObjectClass;
//-----------------------------------------------------------------------------
class cClientHintManager
{
public:
static void Think(void);
private:
static int __cdecl Priority_Compare(const void **object1, const void **object2);
};
//-----------------------------------------------------------------------------
#endif // __CLIENTHINTMANAGER_H__

View File

@@ -0,0 +1,176 @@
/*
** 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/clientpingmanager.cpp $*
* *
* $Author:: Steve_t $*
* *
* $Modtime:: 12/09/01 6:40p $*
* *
* $Revision:: 2 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include "clientpingmanager.h"
#include <windows.h>
#include "systimer.h"
#include "gamemode.h"
#include "cspingrequestevent.h"
#include "cnetwork.h"
//
// Class statics
//
int cClientPingManager::PingNumber = 0;
DWORD cClientPingManager::TimeSentMs = 0;
DWORD cClientPingManager::LastRoundTripPingMs = 0;
DWORD cClientPingManager::AvgRoundTripPingMs = 0;
bool cClientPingManager::IsAwaitingResponse = false;
DWORD cClientPingManager::RoundTripPingSamplesMs[];
//-----------------------------------------------------------------------------
void
cClientPingManager::Init
(
void
)
{
PingNumber = 0;
TimeSentMs = 0;
LastRoundTripPingMs = 0;
AvgRoundTripPingMs = 0;
IsAwaitingResponse = false;
for (int i = 0; i < MAX_SAMPLES; i++)
{
RoundTripPingSamplesMs[i] = 0;
}
}
//-----------------------------------------------------------------------------
void
cClientPingManager::Think
(
void
)
{
if (GameModeManager::Find("Combat")->Is_Active() && cNetwork::I_Am_Only_Client())
{
if (!IsAwaitingResponse)
{
DWORD time_now_ms = TIMEGETTIME();
if (time_now_ms - TimeSentMs >= MIN_PING_DELAY_MS)
{
PingNumber++;
TimeSentMs = time_now_ms;
IsAwaitingResponse = true;
cCsPingRequestEvent * p_event = new cCsPingRequestEvent;
p_event->Init(PingNumber);
}
}
//
// Propagate latency data to combat
//
CombatManager::Set_Last_Round_Trip_Ping_Ms(LastRoundTripPingMs);
CombatManager::Set_Avg_Round_Trip_Ping_Ms(AvgRoundTripPingMs);
}
}
//-----------------------------------------------------------------------------
DWORD
cClientPingManager::Get_Last_Round_Trip_Ping_Ms
(
void
)
{
return LastRoundTripPingMs;
}
//-----------------------------------------------------------------------------
DWORD
cClientPingManager::Get_Avg_Round_Trip_Ping_Ms
(
void
)
{
return AvgRoundTripPingMs;
}
//-----------------------------------------------------------------------------
void
cClientPingManager::Compute_Average_Round_Trip_Ping_Ms
(
void
)
{
//
// This is the average of MAX_SAMPLES non-zero pings.
//
AvgRoundTripPingMs = 0;
DWORD num_pings = 0;
DWORD total_ping = 0;
for (int i = 0; i < MAX_SAMPLES; i++)
{
if (RoundTripPingSamplesMs[i] != 0)
{
num_pings++;
total_ping += RoundTripPingSamplesMs[i];
}
}
if (num_pings > 0)
{
AvgRoundTripPingMs = (DWORD)(total_ping / (float) num_pings);
}
}
//-----------------------------------------------------------------------------
void
cClientPingManager::Response_Received
(
int ping_number
)
{
if (ping_number == PingNumber)
{
LastRoundTripPingMs = TIMEGETTIME() - TimeSentMs;
RoundTripPingSamplesMs[PingNumber % MAX_SAMPLES] = LastRoundTripPingMs;
Compute_Average_Round_Trip_Ping_Ms();
IsAwaitingResponse = false;
}
else
{
WWDEBUG_SAY(("WARNING: cClientPingManager::Response_Received ping number mismatch (%d, %d)\n",
ping_number, PingNumber));
}
}

View File

@@ -0,0 +1,71 @@
/*
** 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/clientpingmanager.h $*
* *
* $Author:: Tom_s $*
* *
* $Modtime:: 10/15/01 4:34p $*
* *
* $Revision:: 2 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#ifndef __CLIENTPINGMANAGER_H__
#define __CLIENTPINGMANAGER_H__
#include "bittype.h"
//-----------------------------------------------------------------------------
class cClientPingManager
{
public:
static void Init(void);
static void Think(void);
static DWORD Get_Last_Round_Trip_Ping_Ms(void);
static DWORD Get_Avg_Round_Trip_Ping_Ms(void);
static void Response_Received(int ping_number);
private:
static void Compute_Average_Round_Trip_Ping_Ms(void);
enum {MAX_SAMPLES = 3};
enum {MIN_PING_DELAY_MS = 1000};
static int PingNumber;
static DWORD TimeSentMs;
static DWORD LastRoundTripPingMs;
static DWORD AvgRoundTripPingMs;
static bool IsAwaitingResponse;
static DWORD RoundTripPingSamplesMs[MAX_SAMPLES];
};
//-----------------------------------------------------------------------------
#endif // __CLIENTPINGMANAGER_H__

1667
Code/Commando/cnetwork.cpp Normal file

File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More