//===========================================================================// // 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 #include #include #include #include #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;objectivenameTableArray [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;objectivenameTableArray [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;objectivenameTableArray [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;objectivenameTableArray [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;objectivenameTableArray [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;objectivenameTableArray [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;objectivenameTableArray [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;objectivenameTableArray [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;objectivenameTableArray [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 } }