Files
firestorm/Gameleap/code/mw4/Code/MW4/NetGenericMessages.cpp
T
Cyd 2b8ca921cb Initial full mirror of c:\VWE (source + assets + toolchain + outputs) via Git LFS
Complete disaster-recovery snapshot: engine/game source, game data assets,
VC6 toolchain + DX SDKs, build outputs, deployed game, and _UNUSED archive.
Large binaries in Git LFS; text preserved byte-for-byte (core.autocrlf=false,
no eol attributes). See RECOVERY.md for the one-clone rebuild procedure.
2026-06-24 21:28:16 -05:00

1239 lines
32 KiB
C++

//===========================================================================//
// File: NetGenericMessages.cpp
//---------------------------------------------------------------------------//
// Date Who Modification //
// -------- --- ---------------------------------------------------------- //
// 01/06/1999 JSE Inital coding
//---------------------------------------------------------------------------//
// Copyright (C) 1998, Microsoft Corp. //
// All Rights reserved worldwide //
// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL //
//===========================================================================//
#include "MW4Headers.hpp"
#include "NetGenericMessages.hpp"
#include "MWEntityManager.hpp"
#include "Objective.hpp"
#include "Flag.hpp"
#include "MWApplication.hpp"
#include "MWPlayer.hpp"
#include "MWMission.hpp"
#include "NavPoint.hpp"
#include <Adept\NameTable.hpp>
#include <Adept\Map.hpp>
#include <GameOS\Network.hpp>
#include <Adept\DamageObject.hpp>
#include <Adept\GlobalPointerManager.hpp>
#include "MW4\Bucket.hpp"
#include "MW4\MWDamageObject.hpp"
#include "MW4\VehicleInterface.hpp"
#include "MW4\Vehicle.hpp"
#include "MW4\Mech.hpp"
#include "MW4\WeaponMover.hpp"
#include "MW4\HeatManager.hpp"
#include "MW4\JumpJet.hpp"
#include "MW4\Weapon.hpp"
#include "MW4\NetMovement.hpp"
#include "MW4\NetWeapon.hpp"
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void MissionObjectiveUpdate::Decode(Entity *entity, MemoryStream *memory_stream, Time till, Scalar packet_latency, int connection, int debug_level, int bandwidth)
{
Check_Object(entity);
Check_Object(memory_stream);
NameTable *table = NameTable::GetInstance();
Check_Object (table);
int size = table->nameTableArray[NameTable::ObjectiveArray].GetLength ();
for (int objective=0;objective<size;objective++)
{
NameTableEntry *data;
data = &table->nameTableArray [NameTable::ObjectiveArray][objective];
Objective *obj;
Entity *ent;
ent = data->dataPointer->GetCurrent ();
if (ent)
{
obj = Cast_Object (Objective *,ent);
Check_Object (obj);
bool visibile;
memory_stream->ReadBit(visibile);
if (visibile)
{
obj->Reveal();
int status = 0; // jcem: critical error - should clear before ReadBits(...)...
memory_stream->ReadBits(&status, 2);
//SPEW(("jerryeds", "%d : 1-%d", objective, status));
switch(status)
{
case Objective::Objective_Failed:
obj->Fail();
break;
case Objective::Objective_Succeeded:
obj->Succeed();
break;
case Objective::Objective_Neutral:
//should never switch to neutral
//and should always start in neutral
break;
}
}
else
{
obj->Hide();
//SPEW(("jerryeds", "%d : 0", objective));
}
}
}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void MissionObjectiveUpdate::Skip(MemoryStream *memory_stream, int size, Time till, int connection, int debug_level, int bandwidth)
{
Check_Object(memory_stream);
NameTable *table = NameTable::GetInstance();
Check_Object (table);
int table_size = table->nameTableArray[NameTable::ObjectiveArray].GetLength ();
for (int objective=0;objective<table_size;objective++)
{
NameTableEntry *data;
data = &table->nameTableArray [NameTable::ObjectiveArray][objective];
Entity *ent;
ent = data->dataPointer->GetCurrent ();
if (ent)
{
bool visibile;
memory_stream->ReadBit(visibile);
if (visibile)
{
int status = 0; // jcem: critical error - should clear before ReadBits(...)...
memory_stream->ReadBits(&status, 2);
}
}
}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int MissionObjectiveUpdate::MaxSize(Entity *entity, int debug_level, int bandwidth)
{
NameTable *table = NameTable::GetInstance();
Check_Object (table);
int table_size = table->nameTableArray[NameTable::ObjectiveArray].GetLength ();
return table_size*3;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void MissionObjectiveUpdate::Encode(Entity *entity, DynamicMemoryStream *memory_stream, int connection, int debug_level, int bandwidth)
{
Check_Object(entity);
Check_Object(memory_stream);
NameTable *table = NameTable::GetInstance();
Check_Object (table);
int size = table->nameTableArray[NameTable::ObjectiveArray].GetLength ();
for (int objective=0;objective<size;objective++)
{
NameTableEntry *data;
data = &table->nameTableArray [NameTable::ObjectiveArray][objective];
Objective *obj;
Entity *ent;
ent = data->dataPointer->GetCurrent ();
if (ent)
{
obj = Cast_Object (Objective *,ent);
Check_Object (obj);
if (obj->Visible())
{
memory_stream->WriteBit(true);
int status = obj->Status();
memory_stream->WriteBits(&status, 2);
//SPEW(("jerryeds", "%d : 1-%d", objective, status));
}
else
{
//SPEW(("jerryeds", "%d : 0", objective));
memory_stream->WriteBit(false);
}
}
}
//SPEW(("jerryeds",""));
}
//====================================================================================================================================================
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void NavPointUpdate::Decode(Entity *entity, MemoryStream *memory_stream, Time till, Scalar packet_latency, int connection, int debug_level, int bandwidth)
{
Check_Object(entity);
Check_Object(memory_stream);
NameTable *table = NameTable::GetInstance();
Check_Object (table);
int size = table->nameTableArray[NameTable::NavArray].GetLength ();
for (int objective=0;objective<size;objective++)
{
NameTableEntry *data;
data = &table->nameTableArray [NameTable::NavArray][objective];
NavPoint *obj;
Entity *ent;
ent = data->dataPointer->GetCurrent ();
if (ent)
{
obj = Cast_Object (NavPoint *,ent);
Check_Object (obj);
bool visibile;
memory_stream->ReadBit(visibile);
if (visibile)
{
unsigned char radarid = 0; // jcem: critical error - should clear before ReadBits(...)...
obj->Reveal();
memory_stream->ReadBits (&radarid,3);
if (radarid == 7)
obj->m_RadarID = -1;
else
obj->m_RadarID = radarid;
}
}
}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void NavPointUpdate::Skip(MemoryStream *memory_stream, int size, Time till, int connection, int debug_level, int bandwidth)
{
Check_Object(memory_stream);
NameTable *table = NameTable::GetInstance();
Check_Object (table);
int table_size = table->nameTableArray[NameTable::NavArray].GetLength ();
for (int objective=0;objective<table_size;objective++)
{
NameTableEntry *data;
data = &table->nameTableArray [NameTable::NavArray][objective];
Entity *ent;
ent = data->dataPointer->GetCurrent ();
if (ent)
{
bool visibile;
memory_stream->ReadBit(visibile);
if (visibile)
{
BYTE temp = 0; // jcem: critical error - should clear before ReadBits(...)...
memory_stream->ReadBits (&temp,3);
}
}
}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int NavPointUpdate::MaxSize(Entity *entity, int debug_level, int bandwidth)
{
NameTable *table = NameTable::GetInstance();
Check_Object (table);
int table_size = table->nameTableArray[NameTable::NavArray].GetLength ();
return (table_size*4); // 1 for visible, 3 for radarid
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void NavPointUpdate::Encode(Entity *entity, DynamicMemoryStream *memory_stream, int connection, int debug_level, int bandwidth)
{
Check_Object(entity);
Check_Object(memory_stream);
NameTable *table = NameTable::GetInstance();
Check_Object (table);
int size = table->nameTableArray[NameTable::NavArray].GetLength ();
for (int objective=0;objective<size;objective++)
{
NameTableEntry *data;
data = &table->nameTableArray [NameTable::NavArray][objective];
NavPoint *obj;
Entity *ent;
ent = data->dataPointer->GetCurrent ();
if (ent)
{
obj = Cast_Object (NavPoint *,ent);
Check_Object (obj);
if (obj->IsVisible())
{
memory_stream->WriteBit(true);
unsigned char radarid;
if (obj->m_RadarID == -1)
radarid = 7;
else
radarid = (unsigned char) obj->m_RadarID;
memory_stream->WriteBits (&radarid,3);
//SPEW(("jerryeds", "%d : 1-%d", objective, status));
}
else
{
//SPEW(("jerryeds", "%d : 0", objective));
memory_stream->WriteBit(false);
}
}
}
//SPEW(("jerryeds",""));
}
//====================================================================================================================================================
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void FlagUpdate::Decode(Entity *entity, MemoryStream *memory_stream, Time till, Scalar packet_latency, int connection, int debug_level, int bandwidth)
{
NameTable *table = NameTable::GetInstance();
Check_Object (table);
MWMission* mwmission = Cast_Object(MWMission*,MWMission::GetInstance());
bool flags_as_nav_points(mwmission->GetFlagsAsNavPoints());
memory_stream->ReadBit(flags_as_nav_points);
mwmission->SetFlagsAsNavPoints(flags_as_nav_points);
int temp(0);
memory_stream->ReadBits(&temp,2);
MWMission::FLAG_ENABLE_STATE flags_enabled = (MWMission::FLAG_ENABLE_STATE)temp;
mwmission->SetFlagsEnabled(flags_enabled);
int size = table->nameTableArray[NameTable::FlagArray].GetLength ();
for (int objective=0;objective<size;objective++)
{
NameTableEntry *data;
data = &table->nameTableArray [NameTable::FlagArray][objective];
Flag *flag;
Entity *ent;
ent = data->dataPointer->GetCurrent ();
if (ent)
{
flag = Cast_Object (Flag *,ent);
Check_Object (flag);
bool visible;
memory_stream->ReadBit(visible);
if (visible)
{
flag->RevealFlag();
int last_event = 0;
memory_stream->ReadBits(&last_event,2);
flag->SetLastFlagEvent((Flag::FlagEvent)last_event);
int mode = 0;
memory_stream->ReadBits(&mode,2);
if (mode == GroundMode)
{
if (flag->Attached())
{
flag->Attach(NULL);
}
Point3D position;
position = flag->GetLocalToWorld();
Scalar min_z, max_z, min_x, max_x;
Map::GetInstance()->GetMapExtents(&min_z, &max_z, &min_x, &max_x);
memory_stream->ReadBitsToScaledFloat(position.x, min_x, max_x, BitDepthManager::BitDepth(UpdateType,XPositionUpdateEntryID));
memory_stream->ReadBitsToScaledFloat(position.z, min_z, max_z, BitDepthManager::BitDepth(UpdateType,ZPositionUpdateEntryID));
UnitQuaternion rot;
rot = flag->GetLocalToWorld();
LinearMatrix4D new_mat;
new_mat.BuildTranslation(position);
new_mat.BuildRotation(rot);
flag->SetNewLocalToParent(new_mat);
flag->SyncMatrices(true);
}
else if (mode == ServerObjectMode)
{
WORD object_id;
memory_stream->ReadBits(&object_id, 16);
ReplicatorID obj_id(Connection::Server->GetID(), object_id);
// if we are not connected to the right object
if (flag->Attached() && flag->Attached()->GetReplicatorID().localID != object_id)
{
flag->Attach(NULL);
}
// if we are not connected
if (flag->Attached() == NULL)
{
// find the object...
Connection *conn = Network::GetInstance()->GetConnection(Connection::Server->GetID());
if (conn != NULL)
{
Entity *entity = Cast_Object(Entity*, conn->FindReplicator(obj_id));
if (entity)
flag->Attach(entity);
}
}
}
else
{
WORD object_id = 0; // jcem: critical error - should clear before ReadBits(...)...
memory_stream->ReadBits(&object_id, 8);
if (flag->Attached() && flag->Attached()->GetReplicatorID().connectionID != object_id)
{
flag->Attach(NULL);
}
if (flag->Attached() == NULL)
{
Entity *entity = NULL;
if (MWApplication::GetInstance()->servedConnectionData[object_id].clientPlayer)
entity = MWApplication::GetInstance()->servedConnectionData[object_id].clientPlayer->vehicle;
if (entity)
flag->Attach(entity);
}
}
}
}
}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void FlagUpdate::Skip(MemoryStream *memory_stream, int , Time till, int connection, int debug_level, int bandwidth)
{
Check_Object(memory_stream);
NameTable *table = NameTable::GetInstance();
Check_Object (table);
bool flags_as_nav_points;
memory_stream->ReadBit(flags_as_nav_points);
int flags_enabled(0);
memory_stream->ReadBits(&flags_enabled,2);
int size = table->nameTableArray[NameTable::FlagArray].GetLength ();
for (int objective=0;objective<size;objective++)
{
NameTableEntry *data;
data = &table->nameTableArray [NameTable::FlagArray][objective];
Flag *flag;
Entity *ent;
ent = data->dataPointer->GetCurrent ();
if (ent)
{
flag = Cast_Object (Flag *,ent);
Check_Object (flag);
bool visible;
memory_stream->ReadBit(visible);
if (visible)
{
int last_event = 0;
memory_stream->ReadBits(&last_event,2);
int mode = 0;
memory_stream->ReadBits(&mode,2);
if (mode == GroundMode)
{
Scalar min_z, max_z, min_x, max_x;
Map::GetInstance()->GetMapExtents(&min_z, &max_z, &min_x, &max_x);
int throw_away;
memory_stream->ReadBits(&throw_away, BitDepthManager::BitDepth(UpdateType,XPositionUpdateEntryID));
memory_stream->ReadBits(&throw_away, BitDepthManager::BitDepth(UpdateType,ZPositionUpdateEntryID));
}
else if (mode == ServerObjectMode)
{
int object_id;
memory_stream->ReadBits(&object_id, 16);
}
else
{
int object_id;
memory_stream->ReadBits(&object_id, 8);
}
}
}
}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int FlagUpdate::MaxSize(Entity *entity, int debug_level, int bandwidth)
{
NameTable *table = NameTable::GetInstance();
Check_Object (table);
int table_size = table->nameTableArray[NameTable::NavArray].GetLength ();
int size_per_entry = BitDepthManager::BitDepth(UpdateType,XPositionUpdateEntryID) + 5;
return ((table_size * size_per_entry) + 3);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void FlagUpdate::Encode(Entity *entity, DynamicMemoryStream *memory_stream, int connection, int debug_level, int bandwidth)
{
Check_Object(entity);
Check_Object(memory_stream);
NameTable *table = NameTable::GetInstance();
Check_Object (table);
MWMission* mwmission = Cast_Object(MWMission*,MWMission::GetInstance());
memory_stream->WriteBit(mwmission->GetFlagsAsNavPoints());
MWMission::FLAG_ENABLE_STATE flags_enabled(mwmission->GetFlagsEnabled());
memory_stream->WriteBits(&flags_enabled,2);
int size = table->nameTableArray[NameTable::FlagArray].GetLength ();
for (int objective=0;objective<size;objective++)
{
NameTableEntry *data;
data = &table->nameTableArray [NameTable::FlagArray][objective];
Flag *flag;
Entity *ent;
ent = data->dataPointer->GetCurrent ();
if (ent)
{
flag = Cast_Object (Flag *,ent);
Check_Object (flag);
bool visible = flag->IsVisible();
memory_stream->WriteBit(visible);
if (visible)
{
int last_event = (int)flag->GetLastFlagEvent();
memory_stream->WriteBits(&last_event,2);
Entity *attached_to = flag->Attached();
int mode = GroundMode;
if (!attached_to)
{
mode = GroundMode;
memory_stream->WriteBits(&mode,2);
Point3D position;
position = flag->GetLocalToWorld();
Scalar min_z, max_z, min_x, max_x;
Map::GetInstance()->GetMapExtents(&min_z, &max_z, &min_x, &max_x);
memory_stream->WriteScaledFloatToBits(position.x, min_x, max_x, BitDepthManager::BitDepth(UpdateType,XPositionUpdateEntryID));
memory_stream->WriteScaledFloatToBits(position.z, min_z, max_z, BitDepthManager::BitDepth(UpdateType,ZPositionUpdateEntryID));
}
else if (attached_to->GetReplicatorID().connectionID == Connection::Server->GetID())
{
mode = ServerObjectMode;
memory_stream->WriteBits(&mode,2);
int object_id = attached_to->GetReplicatorID().localID;
memory_stream->WriteBits(&object_id, 16);
}
else
{
mode = PlayerMode;
memory_stream->WriteBits(&mode,2);
int object_id = attached_to->GetReplicatorID().connectionID;
memory_stream->WriteBits(&object_id, 8);
}
}
}
}
}
//====================================================================================================================================================
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void TimeUpdate::Decode(Entity *entity, MemoryStream *memory_stream, Time till, Scalar packet_latency, int connection, int debug_level, int bandwidth)
{
Check_Object(entity);
Check_Object(memory_stream);
Scalar mission_time;
memory_stream->ReadBits(&mission_time, 32);
mission_time += packet_latency;
MWMission *mission = Cast_Object(MWMission*, MWMission::GetInstance());
mission->SetNetworkTime(mission_time);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void TimeUpdate::Skip(MemoryStream *memory_stream, int size, Time till, int connection, int debug_level, int bandwidth)
{
Check_Object(memory_stream);
Scalar mission_time;
memory_stream->ReadBits(&mission_time, 32);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int TimeUpdate::MaxSize(Entity *entity, int debug_level, int bandwidth)
{
return 32;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void TimeUpdate::Encode(Entity *entity, DynamicMemoryStream *memory_stream, int connection, int debug_level, int bandwidth)
{
Check_Object(entity);
Check_Object(memory_stream);
//SPEW(("jerryeds",""));
MWMission *mission = Cast_Object(MWMission*, MWMission::GetInstance());
Scalar mission_time;
mission_time = mission->GetMissionTime();
memory_stream->WriteBits(&mission_time, 32);
}
//====================================================================================================================================================
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void PingUpdate::Decode(Entity *entity, MemoryStream *memory_stream, Time till, Scalar packet_latency, int connection, int debug_level, int bandwidth)
{
Check_Object(entity);
Check_Object(memory_stream);
Scalar ping_time;
memory_stream->ReadBitsToScaledFloat(ping_time, 0.0f, 10000.0f, 8);
MWApplication::GetInstance()->servedConnectionData[entity->GetReplicatorID().connectionID].effectivePing = ping_time;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void PingUpdate::Skip(MemoryStream *memory_stream, int size, Time till, int connection, int debug_level, int bandwidth)
{
Check_Object(memory_stream);
Scalar ping_time;
memory_stream->ReadBits(&ping_time, 8);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int PingUpdate::MaxSize(Entity *entity, int debug_level, int bandwidth)
{
return 8;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void PingUpdate::Encode(Entity *entity, DynamicMemoryStream *memory_stream, int connection, int debug_level, int bandwidth)
{
Check_Object(entity);
Check_Object(memory_stream);
Scalar ping_time;
ping_time = MWApplication::GetInstance()->servedConnectionData[entity->GetReplicatorID().connectionID].averagePing.CalculateAverage();
Clamp(ping_time, 0, 10000.0f);
memory_stream->WriteScaledFloatToBits(ping_time, 0.0f, 10000.0f, 8);
}
//====================================================================================================================================================
//
void __cdecl MechWarrior4::NetGenericMessagesSecurityCheckStart(void)
{
_asm
{
nop
}
}
//define USE_HACK_CRC 1
#ifdef USE_HACK_CRC
#include "crckey.hpp"
void *security_array[] =
{
(void*)&sequirity_0[0],
(void*)&sequirity_1[0],
(void*)&sequirity_2[0],
(void*)&sequirity_3[0],
(void*)&sequirity_4[0],
(void*)&sequirity_5[0],
(void*)&sequirity_6[0],
(void*)&sequirity_7[0],
(void*)&sequirity_8[0],
(void*)&sequirity_9[0],
(void*)&sequirity_10[0],
(void*)&sequirity_11[0],
(void*)&sequirity_12[0],
(void*)&sequirity_13[0],
(void*)&sequirity_14[0]
};
DWORD security_length[] =
{
(DWORD)ELEMENTS(sequirity_0)<<2,
(DWORD)ELEMENTS(sequirity_1)<<2,
(DWORD)ELEMENTS(sequirity_2)<<2,
(DWORD)ELEMENTS(sequirity_3)<<2,
(DWORD)ELEMENTS(sequirity_4)<<2,
(DWORD)ELEMENTS(sequirity_5)<<2,
(DWORD)ELEMENTS(sequirity_6)<<2,
(DWORD)ELEMENTS(sequirity_7)<<2,
(DWORD)ELEMENTS(sequirity_8)<<2,
(DWORD)ELEMENTS(sequirity_9)<<2,
(DWORD)ELEMENTS(sequirity_10)<<2,
(DWORD)ELEMENTS(sequirity_11)<<2,
(DWORD)ELEMENTS(sequirity_12)<<2,
(DWORD)ELEMENTS(sequirity_13)<<2,
(DWORD)ELEMENTS(sequirity_14)<<2
};
#else
void *security_array[] =
{
(void*)&MD5SecurityCheckStart,
(void*)&AdeptDamageSecurityCheckStart,
(void*)&AdeptGlobalPointerSecurityCheckStart,
(void*)&BucketSecurityCheckStart,
(void*)&MW4DamageSecurityCheckStart,
(void*)&VehicleInterfaceSecurityCheckStart,
(void*)&VehicleSecurityCheckStart,
(void*)&MechSecurityCheckStart,
(void*)&WeaponMoverSecurityCheckStart,
(void*)&HeatSecurityCheckStart,
(void*)&JumpJetSecurityCheckStart,
(void*)&WeaponSecurityCheckStart,
(void*)&NetMovementSecurityCheckStart,
(void*)&NetWeaponSecurityCheckStart,
(void*)&NetGenericMessagesSecurityCheckStart
};
DWORD security_length[] =
{
(DWORD)&MD5SecurityCheckStop - (DWORD)&MD5SecurityCheckStart,
(DWORD)&AdeptDamageSecurityCheckStop - (DWORD)&AdeptDamageSecurityCheckStart,
(DWORD)&AdeptGlobalPointerSecurityCheckStop - (DWORD)&AdeptGlobalPointerSecurityCheckStart,
(DWORD)&BucketSecurityCheckStop - (DWORD)&BucketSecurityCheckStart,
(DWORD)&MW4DamageSecurityCheckStop - (DWORD)&MW4DamageSecurityCheckStart,
(DWORD)&VehicleInterfaceSecurityCheckStop - (DWORD)&VehicleInterfaceSecurityCheckStart,
(DWORD)&VehicleSecurityCheckStop - (DWORD)&VehicleSecurityCheckStart,
(DWORD)&MechSecurityCheckStop - (DWORD)&MechSecurityCheckStart,
(DWORD)&WeaponMoverSecurityCheckStop - (DWORD)&WeaponMoverSecurityCheckStart,
(DWORD)&HeatSecurityCheckStop - (DWORD)&HeatSecurityCheckStart,
(DWORD)&JumpJetSecurityCheckStop - (DWORD)&JumpJetSecurityCheckStart,
(DWORD)&WeaponSecurityCheckStop - (DWORD)&WeaponSecurityCheckStart,
(DWORD)&NetMovementSecurityCheckStop - (DWORD)&NetMovementSecurityCheckStart,
(DWORD)&NetWeaponSecurityCheckStop - (DWORD)&NetWeaponSecurityCheckStart,
(DWORD)&NetGenericMessagesSecurityCheckStop - (DWORD)&NetGenericMessagesSecurityCheckStart
};
#endif
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void SecurityQuery::Decode(Entity *entity, MemoryStream *memory_stream, Time till, Scalar packet_latency, int connection, int debug_level, int bandwidth)
{
//Check_Object(entity);
Check_Object(memory_stream);
int key = 0;
memory_stream->ReadBits(&key, 16);
SecurityQueryInfo *seq_info;
MWEntityManager *manger = (MWEntityManager*)MWEntityManager::GetInstance();
if (MWApplication::GetInstance()->serverFlag)
{
seq_info = &manger->serverController->securityQuery[connection];
}
else
{
seq_info = &manger->clientController->securityQuery;
}
seq_info->otherSidesKey = key;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void SecurityQuery::Skip(MemoryStream *memory_stream, int size, Time till, int connection, int debug_level, int bandwidth)
{
Check_Object(memory_stream);
int key = 0;
memory_stream->ReadBits(&key, 16);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int SecurityQuery::MaxSize(Entity *entity, int debug_level, int bandwidth)
{
return 16;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void SecurityQuery::Encode(Entity *entity, DynamicMemoryStream *memory_stream, int connection, int debug_level, int bandwidth)
{
SecurityQueryInfo *seq_info;
MWEntityManager *manger = (MWEntityManager*)MWEntityManager::GetInstance();
if (MWApplication::GetInstance()->serverFlag)
{
seq_info = &manger->serverController->securityQuery[connection];
}
else
{
seq_info = &manger->clientController->securityQuery;
}
memory_stream->WriteBits(&seq_info->securityKey, 16);
}
void KickPlayer(int connection)
{
//SPEW(("jerryeds", "KICK PLAYER"));
if (MWApplication::GetInstance()->serverFlag)
{
MWApplication::GetInstance()->servedConnectionData[connection].clientQuedForKick = true;
}
else
{
MWApplication::GetInstance()->networkExitCode = MWApplication::BadServerExitCode;
MWApplication::GetInstance()->QueStopGame(true);
}
}
//====================================================================================================================================================
//
void SecurityResponse::Decode(Entity *entity, MemoryStream *memory_stream, Time till, Scalar packet_latency, int connection, int debug_level, int bandwidth)
{
//Check_Object(entity);
Check_Object(memory_stream);
int key = 0;
WORD client_answer = 0;
memory_stream->ReadBits(&key, 16);
memory_stream->ReadBits(&client_answer, 16);
bool server_flag = MWApplication::GetInstance()->serverFlag;
SecurityQueryInfo *seq_info;
MWEntityManager *manger = (MWEntityManager*)MWEntityManager::GetInstance();
if (server_flag)
{
seq_info = &manger->serverController->securityQuery[connection];
}
else
{
seq_info = &manger->clientController->securityQuery;
}
GUID null_hash;
memset(&null_hash, 0, sizeof(null_hash));
if (seq_info->needInit)
{
seq_info->needInit = false;
// we need an init!
MD5_CTX resource_context;
GUID new_code_hash;
unsigned char * buff=(unsigned char *) &new_code_hash;
MD5Init(&resource_context);
int new_key = 0;
for (int i = 0; i < ELEMENTS(security_array); ++i)
{
MD5Update(&resource_context, (unsigned char *) security_array[i], security_length[i]);
MD5Update(&resource_context, (unsigned char *) &key, 4);
}
MD5Final(buff, &resource_context);
seq_info->securityKey = new_key;
seq_info->securityAnswer = new_code_hash;
seq_info->securityTimer = (Scalar)gos_GetElapsedTime();
seq_info->lastSecurityKey = new_key;
seq_info->lastSecurityAnswer = new_code_hash;
}
if (key == seq_info->securityKey)
{
//if (memcmp(&code_hash, &seq_info->securityAnswer, sizeof(code_hash)) != 0)
WORD server_answer=0;
WORD *break_down = (WORD*)&seq_info->securityAnswer;
for (int i = 0; i < 8; ++i)
{
server_answer ^= break_down[i];
}
if (client_answer != server_answer)
{
// KICK PLAYER
//STOP(("KICK PLAYER"));
KickPlayer(connection);
}
else
{
// roll a new key
seq_info->lastSecurityKey = seq_info->securityKey;
seq_info->lastSecurityAnswer = seq_info->securityAnswer;
MD5_CTX resource_context;
GUID new_code_hash;
unsigned char * buff=(unsigned char *) &new_code_hash;
MD5Init(&resource_context);
int temp = Random::GetInt();
int new_key = temp >> 16;
new_key ^= (temp&0xffff);
for (int i = 0; i < ELEMENTS(security_array); ++i)
{
MD5Update(&resource_context, (unsigned char *) security_array[i], security_length[i]);
MD5Update(&resource_context, (unsigned char *) &new_key, 4);
}
MD5Final(buff, &resource_context);
seq_info->securityKey = new_key;
seq_info->securityAnswer = new_code_hash;
seq_info->securityTimer = (Scalar)gos_GetElapsedTime();
}
}
else if (key == seq_info->lastSecurityKey)
{
WORD server_answer=0;
WORD *break_down = (WORD*)&seq_info->lastSecurityAnswer;
for (int i = 0; i < 8; ++i)
{
server_answer ^= break_down[i];
}
if (client_answer != server_answer)
{
// KICK PLAYER
KickPlayer(connection);
}
else
{
// check the timer...
Scalar current_time = (Scalar)gos_GetElapsedTime();
if (current_time-seq_info->securityTimer > 75.0f + packet_latency)
{
KickPlayer(connection);
}
}
}
else
{
KickPlayer(connection);
}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void SecurityResponse::Skip(MemoryStream *memory_stream, int size, Time till, int connection, int debug_level, int bandwidth)
{
Check_Object(memory_stream);
int key = 0;
memory_stream->ReadBits(&key, 16);
memory_stream->ReadBits(&key, 16);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int SecurityResponse::MaxSize(Entity *entity, int debug_level, int bandwidth)
{
return 32;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void SecurityResponse::Encode(Entity *entity, DynamicMemoryStream *memory_stream, int connection, int debug_level, int bandwidth)
{
//Check_Object(entity);
Check_Object(memory_stream);
Verify(ELEMENTS(security_array) == ELEMENTS(security_length));
MD5_CTX resource_context;
GUID code_hash;
unsigned char * buff=(unsigned char *) &code_hash;
SecurityQueryInfo *seq_info;
MWEntityManager *manger = (MWEntityManager*)MWEntityManager::GetInstance();
if (MWApplication::GetInstance()->serverFlag)
{
seq_info = &manger->serverController->securityQuery[connection];
}
else
{
seq_info = &manger->clientController->securityQuery;
}
MD5Init(&resource_context);
int key = seq_info->otherSidesKey;
for (int i = 0; i < ELEMENTS(security_array); ++i)
{
MD5Update(&resource_context, (unsigned char *) security_array[i], security_length[i]);
MD5Update(&resource_context, (unsigned char *) &key, 4);
}
MD5Final(buff, &resource_context);
WORD *break_down = (WORD*)&code_hash;
memory_stream->WriteBits(&key, 16);
WORD result = 0;
for (i = 0; i < 8; ++i)
{
result ^= break_down[i];
}
memory_stream->WriteBits(&result, 16);
//SPEW(("jerryeds", "SEC_RESP ENCODE : %d :%d, %u-%u-%u-%u", Connection::Local->GetID(), key, break_down[0], break_down[1],break_down[2],break_down[3]));
}
__int64 MechWarrior4::CalculateCodeHash(int key)
{
MD5_CTX resource_context;
GUID code_hash;
unsigned char * buff=(unsigned char *) &code_hash;
MD5Init(&resource_context);
for (int i = 0; i < ELEMENTS(security_array); ++i)
{
MD5Update(&resource_context, (unsigned char *) security_array[i], security_length[i]);
MD5Update(&resource_context, (unsigned char *) &key, 4);
}
MD5Final(buff, &resource_context);
__int64 *break_down = (__int64*)&code_hash;
__int64 final = break_down[0] ^ break_down[1];
return final;
}
void __cdecl MechWarrior4::NetGenericMessagesSecurityCheckStop()
{
_asm
{
nop
}
}