| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609 |
- /*
- ** 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();
- }
- }
|