| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388 |
- /*
- ** 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: lanchat.cpp
- // Project: Network.lib, for Commando
- // Author: Tom Spencer-Smith
- // Date: Dec 1998
- // Description: lan chat interface
- //
- // TODO:
- // - allow non-unique player names on the LAN
- // - no provision for graceless exit of person (must remove if don't hear from them)
- // - num players in a channel not shown
- //
- //-----------------------------------------------------------------------------
- #include "lanchat.h"
- #pragma warning(disable : 4201)
- #include "systimer.h"
- #include "wwdebug.h"
- #include "_globals.h"
- #include "netutil.h"
- #include "langmode.h"
- #include "cnetwork.h"
- #include "gamemode.h"
- #include "registry.h"
- #include "gamechanlist.h"
- #include "playermanager.h"
- #include "gametype.h"
- #include "translatedb.h"
- #include "string_ids.h"
- #include "fromaddress.h"
- #include "DlgMPConnect.h"
- #include "slavemaster.h"
- #include "dlgmpchangelannickname.h"
- #include "gamespyadmin.h"
- #include "demosupport.h"
- //
- // Class statics
- //
- const USHORT cLanChat::LAN_BROADCAST_INTERVAL_MS = 1000;
- #pragma message ("(TSS) BUMP LAN BCAST PORT FOR D1P")
- //const USHORT cLanChat::LAN_PORT = 0xEA00;
- const USHORT cLanChat::LAN_PORT = 3373;
- //-----------------------------------------------------------------------------
- cLanChat::cLanChat(void) :
- Socket(INVALID_SOCKET),
- LastPositionBroadcastTimeMs(0),
- PositionBroadcastNumber(0),
- CurrentLocation(LANLOC_LOBBY)
- {
- WWDEBUG_SAY(("cLanChat::cLanChat\n"));
- ZeroMemory(&Socket, sizeof(Socket));
- ZeroMemory(&LocalAddress, sizeof(LocalAddress));
- Load_Lan_Registry_Keys();
- Save_Lan_Registry_Keys();
- Init_Lan_Protocol_And_Socket();
- //cGameChannelList::Remove_All();
- }
- //-----------------------------------------------------------------------------
- cLanChat::~cLanChat(void)
- {
- WWDEBUG_SAY(("cLanChat::~cLanChat\n"));
- Save_Lan_Registry_Keys();
- if (Socket != INVALID_SOCKET) {
- cNetUtil::Close_Socket(Socket);
- }
- }
- //-----------------------------------------------------------------------------
- void cLanChat::Load_Lan_Registry_Keys(void)
- {
- WWDEBUG_SAY(("cLanChat::Load_Lan_Registry_Keys\n"));
- RegistryClass * registry = new RegistryClass(APPLICATION_SUB_KEY_NAME_NETOPTIONS);
- WWASSERT(registry);
- WWASSERT(registry->Is_Valid());
- char name[200];
- registry->Get_String("MyLanName", name, sizeof(name), "");
- WideStringClass widename;
- widename.Convert_From(name);
- if (!cGameSpyAdmin::Is_Gamespy_Game()) {
- if (widename.Is_Empty())
- {
- cNetInterface::Set_Random_Nickname();
- }
- else
- {
- cNetInterface::Set_Nickname(widename);
- }
- }
- int sidePref = registry->Get_Int("SidePref", -1);
- cNetInterface::Set_Side_Preference(sidePref);
- delete registry;
- }
- //-----------------------------------------------------------------------------
- void cLanChat::Save_Lan_Registry_Keys(void)
- {
- WWDEBUG_SAY(("cLanChat::Save_Lan_Registry_Keys...\n"));
- RegistryClass * registry = new RegistryClass(APPLICATION_SUB_KEY_NAME_NETOPTIONS);
- WWASSERT(registry);
- WWASSERT(registry->Is_Valid());
- if (!cGameSpyAdmin::Is_Gamespy_Game()) {
- StringClass string;
- cNetInterface::Get_Nickname().Convert_To(string);
- registry->Set_String("MyLanName", string);
- }
- registry->Set_Int("SidePref", cNetInterface::Get_Side_Preference());
- delete registry;
- }
- //-----------------------------------------------------------------------------
- void cLanChat::Init_Lan_Protocol_And_Socket(void)
- {
- WWASSERT(!IS_SOLOPLAY);
- if (cGameSpyAdmin::Is_Gamespy_Game()) {
- return;
- }
- bool is_internet = false;
- if (!cNetUtil::Protocol_Init(is_internet)) {
- DIE;
- }
- //
- // Init socket
- //
- if (Socket != INVALID_SOCKET) {
- cNetUtil::Close_Socket(Socket);
- }
- bool succeeded = cNetUtil::Create_Bound_Socket(Socket, LAN_PORT, LocalAddress);
- WWASSERT(succeeded);
- }
- //-----------------------------------------------------------------------------
- void cLanChat::Accept_Actions(void)
- {
- DlgMPConnect::DoDialog(cNetInterface::Get_Side_Preference(), 0);
- }
- //-----------------------------------------------------------------------------
- void cLanChat::Refusal_Actions(void)
- {
- //
- // Must do this if join rejected
- //
- }
- //-----------------------------------------------------------------------------
- void cLanChat::Send_Position_Broadcast(void)
- {
- //GAMESPY
- if (cGameSpyAdmin::Is_Gamespy_Game()) {
- return;
- }
- //Debug_Say(("Send_Position_Broadcast\n"));
- if (TIMEGETTIME() - LastPositionBroadcastTimeMs > LAN_BROADCAST_INTERVAL_MS) {
- //
- // Everybody broadcasts their position periodically, as well as
- // immediately after changing location.
- //
- //
- // Broadcast number is used to decide who has to change their name if
- // there is a name collision. The first guy in wins out.
- //
- LastPositionBroadcastTimeMs = TIMEGETTIME();
- PositionBroadcastNumber++;
- cPacket packet;
- packet.Add((BYTE) LAN_MESSAGE_POSITION);
- packet.Add_Wide_Terminated_String(cNetInterface::Get_Nickname());
- packet.Add(PositionBroadcastNumber);
- bool is_hosting = cNetwork::I_Am_Server() &&
- GameModeManager::Find("Combat")->Is_Active();
- packet.Add(is_hosting);
- if (is_hosting) {
- WWASSERT(PTheGameData != NULL);
- packet.Add((int) The_Game()->Get_Game_Type());
- The_Game()->Export_Tier_1_Data(packet);
- }
- cNetUtil::Broadcast(Socket, LAN_PORT, packet);
- }
- }
- //-----------------------------------------------------------------------------
- void cLanChat::Process_Position_Broadcast(cPacket & packet)
- {
- //Debug_Say(("Process_Position_Broadcast\n"));
- WideStringClass sender;
- packet.Get_Wide_Terminated_String(sender.Get_Buffer(256), 256);
- int broadcast_number = packet.Get(broadcast_number);
- bool is_hosting = packet.Get(is_hosting);
- //if (sender == cNetInterface::Get_Nickname() &&
- if (!sender.Compare_No_Case(cNetInterface::Get_Nickname()) &&
- broadcast_number > PositionBroadcastNumber) {
- packet.Flush();
- WWDEBUG_SAY(("*** LAN NICKNAME COLLISION (%s) ***\n", sender));
- DlgMpChangeLanNickname::DoDialog();
- return;
- }
- if (is_hosting) {
- int game_type = packet.Get(game_type);
- cGameData * p_game_data = cGameData::Create_Game_Of_Type(
- (cGameData::GameTypeEnum) game_type);
- WWASSERT(p_game_data != NULL);
- p_game_data->Import_Tier_1_Data(packet);
- /*
- //
- // TSS2001f
- // Manually correct hosting ip address according to recv address
- //
- WWASSERT(packet.Get_From_Address_Wrapper() != NULL);
- p_game_data->Set_Ip_Address(packet.Get_From_Address_Wrapper()->FromAddress.sin_addr.s_addr);
- WWDEBUG_SAY(("Manually setting ip to %s\n",
- cNetUtil::Address_To_String(p_game_data->Get_Ip_Address())));
- */
- //
- // Don't add this game to the channel list if the player doesn't
- // have the map locally
- //
- if (p_game_data->Does_Map_Exist ()) {
- cGameChannelList::Add_Channel(p_game_data);
- } else {
- delete p_game_data;
- p_game_data = NULL;
- }
- } else {
- cGameChannelList::Remove_Channel(sender);
- //Debug_Say(("Removing channel for %s\n", sender));
- }
- }
- //-----------------------------------------------------------------------------
- void cLanChat::Lan_Packet_Handler(cPacket & packet)
- {
- //GAMESPY
- if (cGameSpyAdmin::Is_Gamespy_Game()) {
- packet.Flush();
- return;
- }
- if (CurrentLocation == LANLOC_EXIT) {
- //
- // Ignore our own broadcasts
- //
- packet.Flush();
- } else {
- BYTE packet_type = packet.Get(packet_type);
- switch (packet_type) {
- case LAN_MESSAGE_POSITION:
- Process_Position_Broadcast(packet);
- break;
- default:
- WWDEBUG_SAY(("cLanChat::Lan_Packet_Handler: received bogus packet_type (%d)\n", packet_type));
- //DIE;
- packet.Flush();
- break;
- }
- }
- }
- //-----------------------------------------------------------------------------
- static void External_Lan_Packet_Handler(cPacket & packet)
- {
- //WWASSERT(LanGameModeClass::PLanChat != NULL);
- PLC->Lan_Packet_Handler(packet);
- }
- //-----------------------------------------------------------------------------
- void cLanChat::Go_To_Location(ChatLocationEnum location)
- {
- CurrentLocation = location;
- }
- //-----------------------------------------------------------------------------
- void cLanChat::Think(void)
- {
- if (cGameSpyAdmin::Is_Gamespy_Game()) {
- return;
- }
- if (CurrentLocation != LANLOC_EXIT) {
- Send_Position_Broadcast();
- cNetUtil::Lan_Servicing(Socket, External_Lan_Packet_Handler);
- DEMO_SECURITY_CHECK;
- }
- }
- /*
- if (MPLanGameListMenuClass::Get_Instance() != NULL) {
- MPLanGameListMenuClass::Get_Instance()->Set_Is_Name_Colliding();
- }
- */
- //MPLanGameListMenuClass::Set_Is_Name_Colliding();
- //#include "dlgmplangamelist.h"
- //cHelpText::Set(TRANSLATION(IDS_MP_NICKNAME_IN_USE));
- //WWDEBUG_SAY(("*** LAN NICKNAME COLLISION (%s) ***\n", sender));
- /*
- if (!cNetInterface::Is_Valid_Name(name)) {
- cNetInterface::Set_Random_Nickname();
- ::strcpy(name, cNetInterface::Get_Nickname());
- }
- */
|