This repository has been archived on 2025-02-27. You can view files and clone it, but cannot push or open issues or pull requests.
CnC_Renegade/Code/Commando/pkthandlers.cpp

404 lines
No EOL
12 KiB
C++

/*
** Command & Conquer Renegade(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/***********************************************************************************************
*** Confidential - Westwood Studios ***
***********************************************************************************************
* *
* Project Name : Commando *
* *
* $Archive:: /Commando/Code/Commando/pkthandlers.cpp $*
* *
* $Author:: Steve_t $*
* *
* $Modtime:: 1/18/02 11:33a $*
* *
* $Revision:: 53 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include "cnetwork.h"
#include "debug.h"
#include "networkobjectmgr.h"
#include "networkobjectfactory.h"
#include "networkobjectfactorymgr.h"
#include "playermanager.h"
#include "apppacketstats.h"
#include "specialbuilds.h"
extern char * Addr_As_String(sockaddr_in *addr);
extern bool g_is_loading;
//-----------------------------------------------------------------------------
NetworkObjectClass *
Create_Network_Object (cPacket &packet, int class_id, int network_obj_id)
{
WWASSERT(network_obj_id > 0);
//
// Lookup the factory for this type of network object
//
NetworkObjectFactoryClass *factory = NetworkObjectFactoryMgrClass::Find_Factory (class_id);
WWASSERT (factory != NULL);
//
// Create the new object
//
NetworkObjectClass *new_object = factory->Create (packet);
WWASSERT (new_object != NULL);
new_object->Set_Network_ID(network_obj_id);//TSS2001b
return new_object;
}
//-----------------------------------------------------------------------------
void cNetwork::Server_Packet_Handler(cPacket & packet, int rhost_id)
{
#ifndef BETACLIENT
WWASSERT(I_Am_Server());
WWASSERT(
rhost_id >= PServerConnection->Get_Min_RHost() &&
rhost_id <= PServerConnection->Get_Max_RHost());
WWASSERT(Receiver != NULL);
/*TSS082801
// TSS - hack
if (g_is_loading) {
Debug_Say(("Server flushing packet during loading\n"));
packet.Flush();
return;
}
*/
//
// TSS112401 XXX
//
if (PServerConnection->Get_Remote_Host(rhost_id) == NULL) {
//
// We were getting this crash:
// pkthandlers.cpp (95) - received BIT_CREATION for existing object of type
// APPPACKETTYPE_CSDAMAGEEVENT following messages "Insufficient bandwidth to send all guaranteed packets".
//
// The only scenario I can envisage is that the server destroys a client, but
// some damage packets are on the wire. Then a new client joins, gets the same client_id,
// and sends some damage packets with the same id's.
//
WWDEBUG_SAY(("cNetwork::Server_Packet_Handler: flushing packet from invalid rhost_id %d\n",
rhost_id));
packet.Flush();
return;
}
int network_obj_id = packet.Get (network_obj_id);
BYTE dirty_bits = packet.Get (dirty_bits);
bool is_delete_pending = packet.Get (is_delete_pending);
//
// Lookup the object this data belongs to
//
NetworkObjectClass *object = NetworkObjectMgrClass::Find_Object (network_obj_id);
//
// Do we need to create this object?
//
if ((dirty_bits & NetworkObjectClass::BIT_CREATION) == NetworkObjectClass::BIT_CREATION) {
int net_classid = packet.Get (net_classid);
//WWASSERT (object == NULL);
if (object != NULL)
{
#ifdef WWDEBUG
//sockaddr_in *actual_from_addr_ptr = (LPSOCKADDR_IN) &packet.Get_From_Address_Wrapper()->FromAddress;
//sockaddr_in rhost_addr = PServerConnection->Get_Remote_Host(rhost_id)->Get_Address();
#endif //WWDEBUG
//#pragma message("(TSS) APPPACKETTYPE_CSDAMAGEEVENT workaround for unknown crash bug.\n")
//WWDEBUG_SAY(("\n"));
//WWDEBUG_SAY(("cNetwork::Server_Packet_Handler: received BIT_CREATION (id %d, is_delete_pending = %d, net_classid = %d, from rhost %d - %s) for existing object:\n",
// network_obj_id, is_delete_pending, net_classid, rhost_id, Addr_As_String(&rhost_addr)));
//WWDEBUG_SAY((" id = %d\n", object->Get_Network_ID()));
//WWDEBUG_SAY((" AppPacketType = %s\n", cAppPacketStats::Interpret_Type(object->Get_App_Packet_Type())));
//WWDEBUG_SAY((" IsDeletePending = %d\n", object->Is_Delete_Pending()));
//WWDEBUG_SAY((" CreatedByPacketID = %d\n", object->Get_Created_By_Packet_ID()));
//WWDEBUG_SAY(("Packet actually from address %s\n", Addr_As_String(actual_from_addr_ptr)));
//WWDEBUG_SAY(("\n"));
//DIE;
//
// So far we've only seen the problem manifest for APPPACKETTYPE_CSDAMAGEEVENT.
// It should be safe to kill the existing conflicting object of this type.
//
if (object->Get_App_Packet_Type() == APPPACKETTYPE_CSDAMAGEEVENT) {
object->Set_Delete_Pending();
}
//
// Flush this packet and bail.
//
packet.Flush();
return;
}
//
// Create the network object
//
object = Create_Network_Object (packet, net_classid, network_obj_id);
#ifdef WWDEBUG
object->Set_Created_By_Packet_ID(packet.Get_Id());
#endif //WWDEBUG
object->Import_Creation (packet);
/*
//XXX
WWDEBUG_SAY(("Created object # %-3d of type %-20s and id %d\n",
NetworkObjectMgrClass::Get_Object_Count(),
cAppPacketStats::Interpret_Type(object->Get_App_Packet_Type()),
network_obj_id));
*/
}
//
// TSS092301
//
if (PServerConnection->Get_Remote_Host(rhost_id) == NULL) {
//
// This was probably a quit packet. Bail !
//
packet.Flush();
return;
}
if (object != NULL) {
//
// Do we need to modify this object?
//
if ((dirty_bits & NetworkObjectClass::BIT_RARE) == NetworkObjectClass::BIT_RARE) {
object->Import_Rare (packet);
}
//
// Do we need to modify this object?
//
if ((dirty_bits & NetworkObjectClass::BIT_OCCASIONAL) == NetworkObjectClass::BIT_OCCASIONAL) {
object->Import_Occasional (packet);
}
//
// Do we need to update this object?
//
if ((dirty_bits & NetworkObjectClass::BIT_FREQUENT) == NetworkObjectClass::BIT_FREQUENT) {
object->Import_Frequent (packet);
//object->Increment_Import_State_Count ();
}
object->Increment_Import_State_Count();
//
// Do we need to delete this object?
//
if (is_delete_pending) {
//
// Delete the object
//
if (object != NULL) {
object->Set_Delete_Pending ();
}
}
} else {
packet.Flush();
//Debug_Network_Basic(("Server received update for non-existent object %d.\n",
// network_obj_id));
}
//
// Did we read all the data contained in the packet?
//
//WWASSERT(packet.Is_Flushed());
if (!packet.Is_Flushed())
{
WWDEBUG_SAY(("cNetwork::Client_Packet_Handler: packet not flushed for object of type %s\n",
cAppPacketStats::Interpret_Type(object->Get_App_Packet_Type())));
DIE;
}
#endif // not BETACLIENT
}
//-----------------------------------------------------------------------------
void cNetwork::Client_Packet_Handler(cPacket & packet)
{
#ifndef FREEDEDICATEDSERVER
WWASSERT(I_Am_Client());
WWASSERT(Receiver != NULL);
// TSS - hack
if (g_is_loading) {
Debug_Say(("Client flushing packet during loading\n"));
packet.Flush();
return;
}
//
// This is presently needed for team object creation which isn't filtered out on send
//
if (cNetwork::I_Am_Server()) {
packet.Flush ();
return;
}
int network_obj_id = packet.Get (network_obj_id);
BYTE dirty_bits = packet.Get (dirty_bits);
bool is_delete_pending = packet.Get (is_delete_pending);
//BYTE app_packet_type = packet.Get (app_packet_type);
//
// Lookup the object this data belongs to
//
NetworkObjectClass *object = NetworkObjectMgrClass::Find_Object (network_obj_id);
//
// Do we need to create this object?
//
if ((dirty_bits & NetworkObjectClass::BIT_CREATION) == NetworkObjectClass::BIT_CREATION) {
//WWASSERT (object == NULL);
if (object != NULL)
{
WWDEBUG_SAY(("cNetwork::Client_Packet_Handler: received BIT_CREATION for existing object of type %s\n",
cAppPacketStats::Interpret_Type(object->Get_App_Packet_Type())));
DIE;
}
//
// Create the network object
//
int net_classid = packet.Get (net_classid);
if (object == NULL) {
object = Create_Network_Object (packet, net_classid, network_obj_id);
}
object->Import_Creation (packet);
//
// HACK - HACK
//
if (net_classid == NETCLASSID_GAMEOBJ) {
BaseGameObj *game_obj = (BaseGameObj *)object;
SmartGameObj *smart_game_obj = game_obj->As_SmartGameObj ();
if (smart_game_obj != NULL) {
int control_owner = smart_game_obj->Get_Control_Owner ();
smart_game_obj->Set_Player_Data (cPlayerManager::Find_Player (control_owner));
}
}
/*
//XXX
WWDEBUG_SAY(("Created object # %-3d of type %-20s and id %d\n",
NetworkObjectMgrClass::Get_Object_Count(),
cAppPacketStats::Interpret_Type(object->Get_App_Packet_Type()),
network_obj_id));
*/
}
if (object != NULL) {
//
// Do we need to delete this object?
//
if (is_delete_pending && object != NULL) {
object->Set_Delete_Pending ();
}
//
// Do we need to modify this object?
//
if ((dirty_bits & NetworkObjectClass::BIT_RARE) == NetworkObjectClass::BIT_RARE) {
object->Import_Rare (packet);
}
//
// Do we need to modify this object?
//
if ((dirty_bits & NetworkObjectClass::BIT_OCCASIONAL) == NetworkObjectClass::BIT_OCCASIONAL) {
object->Import_Occasional (packet);
}
//
// Do we need to update this object?
//
if ((dirty_bits & NetworkObjectClass::BIT_FREQUENT) == NetworkObjectClass::BIT_FREQUENT) {
object->Import_Frequent (packet);
//object->Increment_Import_State_Count ();
}
object->Increment_Import_State_Count();
object->Set_Last_Clientside_Update_Time(TIMEGETTIME());
/*moving up
//
// Do we need to delete this object?
//
if (is_delete_pending) {
//
// Delete the object
//
if (object != NULL) {
object->Set_Delete_Pending ();
}
}
*/
} else {
packet.Flush();
//Debug_Network_Basic(("Client %d received update for non-existent object %d.\n",
// Get_My_Id(), network_obj_id));
}
//
// Did we read all the data contained in the packet?
//
//WWASSERT(packet.Is_Flushed());
if (!packet.Is_Flushed())
{
WWDEBUG_SAY(("cNetwork::Client_Packet_Handler: packet not flushed for object of type %s\n",
cAppPacketStats::Interpret_Type(object->Get_App_Packet_Type())));
//DIE;
}
#endif // !FREEDEDICATEDSERVER
}
//BYTE app_packet_type = packet.Get (app_packet_type);