| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654 |
- /*
- ** 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;
- }
|