Files
firestorm/Gameleap/code/mw4/Code/MW4/NetClientServerController.cpp
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

1529 lines
48 KiB
C++

//===========================================================================//
// File: NetClientServerController.hpp
// Contents : All movement messages and rewind capabilites
//---------------------------------------------------------------------------//
// Date Who Modification //
// -------- --- ---------------------------------------------------------- //
// 01/18/1999 JSE Inital coding
//---------------------------------------------------------------------------//
// Copyright (C) 1998, Microsoft Corp. //
// All Rights reserved worldwide //
// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL //
//===========================================================================//
#include "MW4Headers.hpp"
#include "NetClientServerController.hpp"
#include "MWEntityManager.hpp"
#include "MWApplication.hpp"
#include "Mech.hpp"
#include "Torso.hpp"
#include "VehicleInterface.hpp"
#include "MWPlayer.hpp"
#include "Weapon.hpp"
#include "MissileWeapon.hpp"
#include "SubsystemClassData.hpp"
#include <Adept\CollisionGrid.hpp>
#include <Adept\Site.hpp>
#include <Adept\Map.hpp>
#include <Adept\NetStatCollector.hpp>
// for OutputDebugString^^
#include <windows.h>
#undef min
#undef max
// for OutputDebugString^^
#define DIRECTINPUT_VERSION 0x700
#include <dinput.h>
#include <dsetup.h>
#include <dsound.h>
#include <d3d.h>
#include <dplay.h>
#include <dplobby.h>
#pragma warning( disable: 4201 ) // nameless struct/union (again - something reenables this!)
#include <amstream.h>
#include <control.h>
#include <process.h>
#include <mmreg.h>
#include <msacm.h>
#ifndef __IDDrawExclModeVideo_FWD_DEFINED__
#error DirectX Media 6.0 SDK is required
#endif
#include "gameos\Net_header.hpp"
#include "gameos\mreplay.h"
#include "mreplay2.h"
extern bool g_bCOOP;
DWORD g_clientControlPackets;
DWORD g_clientPacketsWaitingConfirmation;
DWORD g_clientForgotenPackets;
DWORD g_clientSkippedPackets;
DWORD g_clientTimedOutPackets;
DWORD g_clientLatePackets;
DWORD g_clientFullConfirms;
DWORD g_clientSmallConfirms;
DWORD g_serverControlsApplied;
DWORD g_serverFullRetransmits;
DWORD g_serverSmallRetransmits;
DWORD g_serverPacketsOutOfRange;
DWORD g_serverFullConfirms;
DWORD g_serverSmallConfirms;
DWORD g_serverTimeOuts;
SecurityQueryInfo::SecurityQueryInfo()
{
lastSecurityKey = 0;
memset(&lastSecurityAnswer,0,sizeof(lastSecurityAnswer));
securityKey = 0;
memset(&securityAnswer,0,sizeof(securityAnswer));
securityTimer = 0;
otherSidesKey = 0;
needInit = true;
}
void SecurityQueryInfo::Reset(void)
{
lastSecurityKey = 0;
memset(&lastSecurityAnswer,0,sizeof(lastSecurityAnswer));
securityKey = 0;
memset(&securityAnswer,0,sizeof(securityAnswer));
securityTimer = 0;
otherSidesKey = 0;
needInit = true;
}
Point3D ClampPoint(Point3D origin, Point3D target, Point3D min_box, Point3D max_box)
{
Verify(origin.x > min_box.x);
Verify(origin.z > min_box.z);
Verify(origin.x < max_box.x);
Verify(origin.z < max_box.z);
Verify(origin != target);
if (origin == target)
return target;
Scalar original_y = target.y;
origin.y = 0.0f;
target.y = 0.0f;
min_box.y = 0.0f;
max_box.y = 0.0f;
Vector3D vec;
vec.Subtract(target,origin);
UnitVector3D u_vec;
u_vec = vec;
Line3D line(origin, u_vec, vec.GetLength());
Scalar max_distance = line.m_length;
Scalar distance;
if (target.x > max_box.x)
{
distance = Abs((max_box.x - origin.x) / line.m_direction.x);
if (distance < max_distance)
{
max_distance = distance;
}
}
else if (target.x < min_box.x)
{
distance = Abs((min_box.x - origin.x) / line.m_direction.x);
if (distance < max_distance)
{
max_distance = distance;
}
}
if (target.z > max_box.z)
{
distance = Abs((max_box.z - origin.z) / line.m_direction.z);
if (distance < max_distance)
{
max_distance = distance;
}
}
else if (target.z < min_box.z)
{
distance = Abs((min_box.x - origin.z) / line.m_direction.z);
if (distance < max_distance)
{
max_distance = distance;
}
}
line.m_length = max_distance * 0.9f;
Point3D end_point;
line.FindEnd(&end_point);
Verify(end_point.x <= max_box.x);
Verify(end_point.x >= min_box.x);
Verify(end_point.z <= max_box.z);
Verify(end_point.z >= min_box.z);
end_point.y = original_y;
return end_point;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
ServerController::ServerController()
{
m_EntityManager = Cast_Object(MWEntityManager*, EntityManager::GetInstance());
for (int i = 0; i < Maximum_Players; ++i)
{
lastControlPacketID[i] = 0;
lastPingDelta[i] = 0.0f;
lastControlPacket[i] = 0.0f;
lastControlPacketLocal[i] = (float)gos_GetElapsedTime(1);
lastTimeFailure[i] = (float)gos_GetElapsedTime(1);
lastReportedPosition[i] = Point3D::HellPoint;
positionErrors[i] = 0;
waitingForRespawn[i] = true;
clockDifference[i] = 0.0f;
lowestLatency[i] = 1000000.0f;
latencyDelay[i] = 0;
securityQuery[i].Reset();
}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
ServerController::~ServerController()
{
}
void ServerController::Reset()
{
for (int i = 0; i < Maximum_Players; ++i)
{
lastControlPacketID[i] = 0;
lastPingDelta[i] = 0.0f;
lastControlPacket[i] = 0.0f;
lastControlPacketLocal[i] = (float)gos_GetElapsedTime(1);
lastTimeFailure[i] = (float)gos_GetElapsedTime(1);
lastReportedPosition[i] = Point3D::HellPoint;
positionErrors[i] = 0;
waitingForRespawn[i] = true;
clockDifference[i] = 0.0f;
lowestLatency[i] = 1000000.0f;
latencyDelay[i] = 0;
securityQuery[i].Reset();
}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void ServerController::ResetClient(int connection_id)
{
lastControlPacketID[connection_id] = 0;
lastPingDelta[connection_id] = 0.0f;
lastControlPacket[connection_id] = 0.0f;
lastControlPacketLocal[connection_id] = (float)gos_GetElapsedTime(1);
lastTimeFailure[connection_id] = (float)gos_GetElapsedTime(1);
lastReportedPosition[connection_id] = Point3D::HellPoint;
positionErrors[connection_id] = 0;
waitingForRespawn[connection_id] = true;
clockDifference[connection_id] = 0.0f;
lowestLatency[connection_id] = 1000000.0f;
latencyDelay[connection_id] = 0;
securityQuery[connection_id].Reset();
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void ServerController::ReceivePlayerControl(int connection, Stuff::MemoryStream *message)
{
MWEntityManager *manager = Cast_Object (MWEntityManager*, MWEntityManager::GetInstance());
ThrottleTest(connection);
Mech *vehicle = (Mech *) manager->playerVehicle[connection];
int bandwidth = 0;
if (vehicle != NULL)
{
Scalar old_speed = vehicle->currentSpeedMPS;
Scalar packet_time = 0;
double latency = 0;
double better_latency = 0;
DictionaryManager *dictionary_manager = manager->GetDictionaryManager(connection);
if(dictionary_manager != NULL)
{
int version = 0;
message->ReadBits(&version,8);
BYTE packet_number;
message->ReadBits(&packet_number,8);
if (MWEntityManager::IsNumberBehind(packet_number, lastControlPacketID[connection], 40, 255))
{
//SPEWALWAYS(("jerryeds", "LATE CONTROL PACKET THROWN OUT"));
return;
}
// calculate ping...
//t1-t2
Scalar t2_minus_t1;
message->ReadBits(&t2_minus_t1, 32);
Scalar t3;
Scalar t4 = (float)(gos_GetElapsedTime(1) * 1000.0);
message->ReadBits(&t3, 32);
lastPingDelta[connection] = t4 - t3;
//SPEWALWAYS(("jerryeds", "S-REC - %d : t2-t1 : %f, t4-t3 %f : t3 : %f t4 : %f", packet_number, t2_minus_t1, t4 - t3, t3, t4));
MWApplication::GetInstance()->servedConnectionData[connection].effectivePing = t2_minus_t1 + (t4 - t3);
MWApplication::GetInstance()->servedConnectionData[connection].averagePing.Add(MWApplication::GetInstance()->servedConnectionData[connection].effectivePing);
latency = MWApplication::GetInstance()->servedConnectionData[connection].effectivePing * 0.5f;
bool do_clock_sync = true;
if (latency < 0.0f)
do_clock_sync = false;
Min_Clamp(latency, 0.01f);
latency *= 0.001f;
packet_time = t3 * 0.001f;
double current_time = gos_GetElapsedTime(1);
if (do_clock_sync && latencyDelay[connection] > 5 )
{
if (latency < lowestLatency[connection])
{
lowestLatency[connection] = latency;
clockDifference[connection] = current_time - (packet_time + latency);
//SPEWALWAYS(("jerryeds", "new clock diff %f", clockDifference[connection]));
}
}
else if (do_clock_sync)
{
clockDifference[connection] = current_time - (packet_time + latency);
//SPEWALWAYS(("jerryeds", "DELAY - new clock diff %f", clockDifference[connection]));
++latencyDelay[connection];
}
//latency now equals current_time - packet_time+clock_difference
better_latency = current_time - (packet_time + clockDifference[connection]);
//SPEWALWAYS(("jerryeds", "better latency %f : orig: %f diff: %f\n", better_latency, latency, better_latency - latency));
//latency = better_latency;
Min_Clamp(latency, 0.00001f);
Min_Clamp(better_latency, 0.00001f);
// clockDifference[connection] - (current_time - (packet_time + latency))
//
//SPEWALWAYS(("jerryeds", "local:%f client:%f clock_adj:%f", current_time, packet_time, clockDifference[connection] ));
//MWApplication::GetInstance()->servedConnectionData[connection].effectivePing = (float)(latency * 2.0 * 1000.0);
//doesn't get executed due to the above clamp and never has. I can remove this, but am not for compile consistancy.
if (do_clock_sync && latency < 0.0f)
{
clockDifference[connection] += latency;
//SPEWALWAYS(("jerryeds", "clock adj : %f", clockDifference[connection]));
}
lastControlPacketID[connection] = packet_number;
// used to be GetVersion, but that will cause packets to not be read for no reason.
Dictionary *dictionary = dictionary_manager->GetCurrentDictionary();
if (dictionary != NULL)
{
bandwidth = dictionary->dictionaryBandwidth;
// if this is ahead and not more than 30 messages ahead...
int rate_type = manager->bitManager->GetUpdateRate(UpdateManager::MechPositionUpdateID, dictionary->dictionaryBandwidth).m_ActiveRate;
Scalar rate = DictionaryPage::CalculateSeconds(rate_type);
SecurityQuery::Decode(vehicle, message, 0.0, (float)latency, connection, dictionary->debugDictionaryLevel, dictionary->dictionaryBandwidth);
MechPositionUpdate::Decode(vehicle, message, 0.0, (float)latency, connection, dictionary->debugDictionaryLevel, dictionary->dictionaryBandwidth, rate);
SecurityResponse::Decode(vehicle, message, 0.0, (float)latency, connection, dictionary->debugDictionaryLevel, dictionary->dictionaryBandwidth);
ExternalJumpJetUpdate::Decode(vehicle, message, 0.0, (float)latency, connection, dictionary->debugDictionaryLevel, dictionary->dictionaryBandwidth, rate);
//MechMovemntUpdate::Decode(vehicle, message, 0.0, latency, connection, dictionary->debugDictionaryLevel, dictionary->dictionaryBandwidth, rate);
//MechAnimationUpdate::Decode(vehicle, message, 0.0, latency, connection, dictionary->debugDictionaryLevel, dictionary->dictionaryBandwidth, rate);
int command_count=0;
message->ReadBits(&command_count, 8);
while (command_count)
{
int command=0;
message->ReadBits(&command, 5);
vehicle->ProcessCommand(command);
command_count--;
}
}
}
YawPitchRoll ypr;
vehicle->GetDeadReckonedNetworkPosition(MWApplication::GetInstance()->servedConnectionData[connection].vehiclePosition, ypr);
MWApplication::GetInstance()->servedConnectionData[connection].vehicleRotation.yaw = ypr.yaw;
Point3D current_position;
current_position = vehicle->GetLocalToWorld();
Point3D distance_traveled;
//SPEWALWAYS(("jerryeds", "MOVE COMMAND : %d", connection));
//SPEWALWAYS(("jerryeds", "CUR POS %f %f %f", current_position.x, current_position.y, current_position.z));
//SPEWALWAYS(("jerryeds", "NET POS %f %f %f", MWApplication::GetInstance()->servedConnectionData[connection].vehiclePosition.x, MWApplication::GetInstance()->servedConnectionData[connection].vehiclePosition.y, MWApplication::GetInstance()->servedConnectionData[connection].vehiclePosition.z));
if (!waitingForRespawn[connection])
{
//SPEWALWAYS((0,"CLIENT : %d", connection));
positionErrors[connection] = 0;
Point3D real_last_position = lastReportedPosition[connection];
lastReportedPosition[connection] = MWApplication::GetInstance()->servedConnectionData[connection].vehiclePosition;
//SPEWALWAYS(("jerryeds", "REAL LAST %f %f %f", real_last_position.x, real_last_position.y, real_last_position.z));
//SPEWALWAYS(("jerryeds", "LAST REPORTED %f %f %f", lastReportedPosition[connection].x, lastReportedPosition[connection].y, lastReportedPosition[connection].z));
distance_traveled.Subtract(lastReportedPosition[connection], real_last_position);
// if the mech was breaking the rules....
Scalar local_time = (Scalar)gos_GetElapsedTime(1) - (Scalar)better_latency;
Scalar local_dif = local_time-lastControlPacketLocal[connection];
Scalar remote_dif = packet_time-lastControlPacket[connection];
//SPEW(("jerryeds","TIME DIFFERENCE %f", local_dif-remote_dif));
Scalar time_dif = remote_dif - local_dif;
// jcem - Verify(fabs(time_dif) > 0.0f);
//SPEWALWAYS((0,"local_time : %f remote_time : %f", gos_GetElapsedTime(), packet_time));
//SPEWALWAYS((0,"TIME SINCE FAILURE : %f", gos_GetElapsedTime() - lastTimeFailure[connection]));
bool loose_time = true;
if (gos_GetElapsedTime(1) - lastTimeFailure[connection] < 3.0f)
{
loose_time = false;
}
//double time_since_failure = (float)gos_GetElapsedTime(1) - lastTimeFailure[connection];
if (time_dif > 0.04f)
{
lastTimeFailure[connection] = (float)gos_GetElapsedTime(1);
//SPEWALWAYS((0, "ALLOWED TIME RULE BREAKER"));
}
//SPEWALWAYS((0,"SERVER : %f - CLIENT : %f - DIF %f - latency %f\n", local_dif, remote_dif, time_dif, latency));
//SPEWALWAYS((0, "TIME DIFF %f : %f : %f", local_dif, remote_dif, fabs(time_dif)));
if (Close_Enough(real_last_position, Point3D::HellPoint, 100.0f))
{
// the real position is in hell on the server but the client got to move
// go ahead and let this one by
}
else if (loose_time && time_dif > 0.25f)
{
//Connection *conn = Network::GetInstance()->GetConnection(connection);
//DWORD que = reinterpret_cast<DWORD>(gos_NetInformation(gos_GetOutboundWindowSizeDpid, conn->GetNetworkAddress()));
lowestLatency[connection] = 0.5f;
clockDifference[connection] = gos_GetElapsedTime(1) - packet_time + 0.5f;
//SPEWALWAYS((0, "LOOSE TIME - RULE BREAK"));
//SPEWALWAYS((0,"CLIENT : %d : %s", connection, (char *)Network::GetInstance()->GetConnection(connection)->GetConnectionName()));
//SPEWALWAYS((0,"connection speed : %d", bandwidth));
//SPEWALWAYS((0,"QUE : %d", que));
//SPEWALWAYS((0, "clock_adj:%f", clockDifference[connection] ));
//SPEWALWAYS((0,"local_time : %f remote_time : %f : diff : %f", gos_GetElapsedTime(1), packet_time, gos_GetElapsedTime(1) - packet_time));
//SPEWALWAYS((0,"TIME SINCE FAILURE : %f", time_since_failure));
//SPEWALWAYS((0,"SERVER : %f - CLIENT : %f - DIF %f - latency %f", local_dif, remote_dif, time_dif, latency));
//SPEWALWAYS((0, "TIME DIFF %f : %f : %f", local_dif, remote_dif, fabs(time_dif)));
//SPEWALWAYS((0,"-----------------------------\n", connection));
//PAUSE(("RULE BREAKER"));
vehicle->ClearNetworkPosition();
vehicle->speedDemand = 0.0f;
vehicle->yawDemand = 0.0f;
vehicle->currentSpeedMPS = old_speed;
SendFullConfirmation(connection);
lastReportedPosition[connection] = vehicle->GetLocalToWorld();
}
else if (!loose_time && time_dif > 0.04f)
{
//Connection *conn = Network::GetInstance()->GetConnection(connection);
//DWORD que = reinterpret_cast<DWORD>(gos_NetInformation(gos_GetOutboundWindowSizeDpid, conn->GetNetworkAddress()));
lowestLatency[connection] = 0.5f;
clockDifference[connection] = gos_GetElapsedTime(1) - packet_time + 0.5f;
//SPEWALWAYS((0,"NO LOOSE TIME - RULE BREAKER"));
//SPEWALWAYS((0,"CLIENT : %d : %s", connection, (char *)Network::GetInstance()->GetConnection(connection)->GetConnectionName()));
//SPEWALWAYS((0,"connection speed : %d", bandwidth));
//SPEWALWAYS((0,"QUE : %d", que));
//SPEWALWAYS((0, "clock_adj:%f", clockDifference[connection] ));
//SPEWALWAYS((0,"local_time : %f remote_time : %f : diff : %f", gos_GetElapsedTime(1), packet_time, gos_GetElapsedTime(1) - packet_time));
//SPEWALWAYS((0,"TIME SINCE FAILURE : %f", time_since_failure));
//SPEWALWAYS((0,"SERVER : %f - CLIENT : %f - DIF %f - latency %f", local_dif, remote_dif, time_dif, latency));
//SPEWALWAYS((0, "TIME DIFF %f : %f : %f", local_dif, remote_dif, fabs(time_dif)));
//SPEWALWAYS((0,"-----------------------------\n", connection));
//PAUSE(("RULE BREAKER"));
vehicle->ClearNetworkPosition();
vehicle->speedDemand = 0.0f;
vehicle->yawDemand = 0.0f;
vehicle->currentSpeedMPS = old_speed;
SendFullConfirmation(connection);
lastReportedPosition[connection] = vehicle->GetLocalToWorld();
}
else if (vehicle->executionState->GetState() == Mech::ExecutionStateEngine::FlyingMotionState)
{
Scalar time = packet_time-lastControlPacket[connection];
Scalar max_speed_squared = vehicle->GetMaxSpeed()*2.0f*time;
max_speed_squared *= max_speed_squared;
distance_traveled.y = 0.0f;
if (!Small_Enough(time))
{
if (distance_traveled.GetLengthSquared() > max_speed_squared)
{
//rule breaker...
//PAUSE(("RULE BREAKER"));
//SPEWALWAYS(("jerryeds", "RULE BREAKER %f : %f : %f > %f ", MWApplication::GetInstance()->servedConnectionData[connection].effectivePing, time, distance_traveled.GetLength(), sqrt(max_speed_squared)));
vehicle->ClearNetworkPosition();
vehicle->speedDemand = 0.0f;
vehicle->yawDemand = 0.0f;
vehicle->currentSpeedMPS = old_speed;
SendFullConfirmation(connection);
lastReportedPosition[connection] = current_position;
}
}
}
else
{
Scalar time = packet_time-lastControlPacket[connection];
Scalar max_speed_squared = vehicle->GetMaxSpeed()*1.5f*time;
max_speed_squared *= max_speed_squared;
distance_traveled.y = 0.0f;
if (!Small_Enough(time))
{
if (distance_traveled.GetLengthSquared() > max_speed_squared)
{
//rule breaker...
//PAUSE(("RULE BREAKER"));
//SPEWALWAYS(("jerryeds", "RULE BREAKER %f : %f : %f > %f ", MWApplication::GetInstance()->servedConnectionData[connection].effectivePing, time, distance_traveled.GetLength(), sqrt(max_speed_squared)));
vehicle->ClearNetworkPosition();
vehicle->speedDemand = 0.0f;
vehicle->yawDemand = 0.0f;
vehicle->currentSpeedMPS = old_speed;
SendFullConfirmation(connection);
lastReportedPosition[connection] = current_position;
}
}
}
lastControlPacketLocal[connection] = local_time;
lastControlPacket[connection] = packet_time;
//SPEWALWAYS((0,"-----------------------------\n", connection));
}
else
{
// if this is the actual respawn...
//SPEWALWAYS(("jerryeds", "WAITING FOR RESPAWN <%f:%f:%f> -> <%f:%f:%f>",
// MWApplication::GetInstance()->servedConnectionData[connection].vehiclePosition.x,
// MWApplication::GetInstance()->servedConnectionData[connection].vehiclePosition.y,
// MWApplication::GetInstance()->servedConnectionData[connection].vehiclePosition.z,
// lastReportedPosition[connection].x, lastReportedPosition[connection].y, lastReportedPosition[connection].z));
if (lastReportedPosition[connection] == Point3D::HellPoint && MWApplication::GetInstance()->servedConnectionData[connection].vehiclePosition != Point3D::HellPoint)
{
//STOP (("NEVER SHOULD THIS HAPPEN"));
waitingForRespawn[connection] = false;
Point3D trans;
YawPitchRoll rot;
vehicle->GetDeadReckonedNetworkPosition(trans, rot);
vehicle->ClearNetworkPosition();
LinearMatrix4D drop_position;
drop_position.BuildTranslation(trans);
drop_position.BuildRotation(rot);
vehicle->SetNewLocalToParent(drop_position);
vehicle->SyncMatrices(true);
Map::GetInstance()->UpdateZone(vehicle);
}
else
{
Point3D distance;
distance.Subtract(lastReportedPosition[connection],MWApplication::GetInstance()->servedConnectionData[connection].vehiclePosition);
distance.y = 0.0f;
if (Small_Enough(distance.GetLengthSquared(),100.0f))
{
waitingForRespawn[connection] = false;
Point3D trans;
YawPitchRoll rot;
vehicle->GetDeadReckonedNetworkPosition(trans, rot);
vehicle->ClearNetworkPosition();
LinearMatrix4D drop_position;
drop_position.BuildTranslation(trans);
drop_position.BuildRotation(rot);
vehicle->SetNewLocalToParent(drop_position);
vehicle->SyncMatrices(true);
Map::GetInstance()->UpdateZone(vehicle);
}
else
{
vehicle->speedDemand = 0.0f;
vehicle->yawDemand = 0.0f;
vehicle->currentSpeedMPS = old_speed;
vehicle->ClearNetworkPosition();
++positionErrors[connection];
if (positionErrors[connection] > 10)
{
//SPEWALWAYS(("jerryeds", "NO RESPAWN %f %f %f", current_position.x, current_position.y, current_position.z));
Point3D trans;
YawPitchRoll rot;
LinearMatrix4D drop_position = LinearMatrix4D::Identity;
drop_position.BuildTranslation(lastReportedPosition[connection]);
vehicle->SetNewLocalToParent(drop_position);
vehicle->SyncMatrices(true);
Map::GetInstance()->UpdateZone(vehicle);
SendFullConfirmation(connection);
vehicle->ClearNetworkPosition();
//lastReportedPosition[connection] = current_position;
waitingForRespawn[connection] = false;
}
}
}
}
}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void ServerController::SendFullConfirmation(int connection)
{
MWEntityManager *manager = Cast_Object (MWEntityManager*, MWEntityManager::GetInstance());
DictionaryManager *dictionary_manager = manager->GetDictionaryManager(connection);
if(dictionary_manager != NULL)
{
Dictionary *dictionary = dictionary_manager->GetCurrentDictionary();
//int rate_type = manager->bitManager->GetUpdateRate(UpdateManager::MechPositionUpdateID, dictionary->dictionaryBandwidth).m_ActiveRate;
//Scalar rate = DictionaryPage::CalculateSeconds(rate_type);
DynamicMemoryStream movement_packet(MWEntityManager::Packet_Buffer, DefaultPacketBufferSize);
Player *player = MWApplication::GetInstance()->servedConnectionData[connection].clientPlayer;
movement_packet.WriteBits(&dictionary->versionNumber,8);
MechPositionUpdate::Encode(player->vehicle, &movement_packet, player->vehicle->GetReplicatorID().connectionID, dictionary->debugDictionaryLevel, dictionary->dictionaryBandwidth);
ExternalJumpJetUpdate::Encode(player->vehicle, &movement_packet, player->vehicle->GetReplicatorID().connectionID, dictionary->debugDictionaryLevel, dictionary->dictionaryBandwidth);
MechInternalDamageUpdate::Encode(player->vehicle, &movement_packet, player->vehicle->GetReplicatorID().connectionID, dictionary->debugDictionaryLevel, dictionary->dictionaryBandwidth);
movement_packet.WriteByteAlign();
movement_packet.Rewind();
Network::GetInstance()->SendNetMessage(connection, MWEntityManager::FirstPersonFullConfirmationMessageID, &movement_packet, false);
}
/*
if (!((g_nMR == 1) && (connection != 1)))
return;
dictionary_manager = manager->GetDictionaryManager(1);
if(dictionary_manager != NULL)
{
Dictionary *dictionary = dictionary_manager->GetCurrentDictionary();
//int rate_type = manager->bitManager->GetUpdateRate(UpdateManager::MechPositionUpdateID, dictionary->dictionaryBandwidth).m_ActiveRate;
//Scalar rate = DictionaryPage::CalculateSeconds(rate_type);
DynamicMemoryStream movement_packet(MWEntityManager::Packet_Buffer, DefaultPacketBufferSize);
movement_packet.WriteBits(&dictionary->versionNumber,8);
Player *player = MWApplication::GetInstance()->servedConnectionData[connection].clientPlayer;
Vehicle* vehicle = Cast_Object(Vehicle*, player->vehicle);
ReplicatorID id = vehicle->GetReplicatorID();
movement_packet.WriteBits(&id.connectionID, 8);
movement_packet.WriteBits(&id.localID, 16);
MechPositionUpdate::Encode(vehicle, &movement_packet, id.connectionID, dictionary->debugDictionaryLevel, dictionary->dictionaryBandwidth);
ExternalJumpJetUpdate::Encode(vehicle, &movement_packet, id.connectionID, dictionary->debugDictionaryLevel, dictionary->dictionaryBandwidth);
movement_packet.WriteByteAlign();
movement_packet.Rewind();
g_MRF.SendMessage(1, &movement_packet, MRP_FULLCONFIRM);
}*/
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void ServerController::ReceivePlayerObserverControl(int connection, Stuff::MemoryStream *message)
{
ThrottleTest(connection);
YawPitchRange viewing_rotation = YawPitchRange::Identity;
Point3D viewing_position = Point3D::Identity;
Scalar min_z, max_z, min_x, max_x;
Map::GetInstance()->GetMapExtents(&min_z, &max_z, &min_x, &max_x);
message->ReadBitsToScaledFloat(viewing_position.x, min_x, max_x, 24);
message->ReadBitsToScaledFloat(viewing_position.y, -2005.0f, 1005.0f, 24);
message->ReadBitsToScaledFloat(viewing_position.z, min_z, max_z, 24);
message->ReadBitsToScaledFloat(viewing_rotation.yaw.angle, -Stuff::Pi, Stuff::Pi, 24);
Scalar t2_minus_t1;
message->ReadBits(&t2_minus_t1, 32);
Scalar t3;
Scalar t4 = (float)(gos_GetElapsedTime(1) * 1000.0);
message->ReadBits(&t3, 32);
lastPingDelta[connection] = t4 - t3;
//SPEWALWAYS(("jerryeds", "S-REC - %d : t2-t1 : %f, t4-t3 %f : t3 : %f t4 : %f", packet_number, t2_minus_t1, t4 - t3, t3, t4));
MWApplication::GetInstance()->servedConnectionData[connection].effectivePing = t2_minus_t1 + (t4 - t3);
MWApplication::GetInstance()->servedConnectionData[connection].averagePing.Add(MWApplication::GetInstance()->servedConnectionData[connection].effectivePing);
SecurityQuery::Decode(NULL, message, 0.0f, 0.0f, connection, 0, 0);
SecurityResponse::Decode(NULL, message, 0.0f, 0.0f, connection, 0, 0);
MWApplication::GetInstance()->servedConnectionData[connection].vehiclePosition = viewing_position;
MWApplication::GetInstance()->servedConnectionData[connection].vehicleRotation = viewing_rotation;
Network::GetInstance()->netStatCollector[Network::IncomingMechMovementBitSizeStat].AddToStatistic(connection,72);
//SPEWALWAYS(("jerryeds","REC CAM - %f %f %f : %f", viewing_position.x, viewing_position.y, viewing_position.z, viewing_rotation.yaw.angle));
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void ServerController::ReceiveWeaponCommand(int connection, int message_type, Stuff::MemoryStream *message)
{
Verify(message_type >= MWEntityManager::StartFirstPersonWeaponMessageID && message_type <= MWEntityManager::EndFirstPersonWeaponMessageID);
Verify(Network::GetInstance()->AmIServer());
#if defined(_DEBUG) && 0 // jcem - for MR test
{
char Buffer[128];
sprintf(Buffer, "Server::ReceiveWeaponCommand\n");
OutputDebugString(Buffer);
}
#endif // _DEBUG && ...
WeaponUpdate *data = new WeaponUpdate;
WeaponCommand::SpecialDecode(connection, message_type, *data, message);
// send the weapon data to the other clients.
if (data->obsolete)
return;
if (data->originator.GetCurrent() == NULL)
return;
#if 0
//SPEW(("jerryeds", "SERVER RECIEVED WEAPON COMMAND FROM : %d", data.originator->GetReplicatorID().connectionID));
int message_offset = message_type - MWEntityManager::StartFirstPersonWeaponMessageID;
DynamicMemoryStream weapon_packet(MWEntityManager::Packet_Buffer, DefaultPacketBufferSize);
WeaponCommand::SpecialEncode((BYTE)connection, MWEntityManager::StartThirdPersonWeaponMessageID+message_offset, *data, &weapon_packet);
weapon_packet.WriteByteAlign();
weapon_packet.Rewind();
for (int i = 0; i < Maximum_Players; ++i)
{
if(MWApplication::GetInstance()->servedConnectionData[i].clientReady && i != connection && i != Connection::Server->GetID())
{
Network::GetInstance()->netStatCollector[Network::OutgoingWeaponMessageBitSizeStat].AddToStatistic(i,message->GetBufferBytesUsed()*8);
Network::GetInstance()->SendNetMessage(i, MWEntityManager::StartThirdPersonWeaponMessageID+message_offset, &weapon_packet, false);
}
}
#endif
m_EntityManager->PlayerWeaponUpdate(data);
// create the collision packet and fire the weapon
//m_EntityManager->CreateWeaponEffect(data);
m_EntityManager->QueWeapon(data);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
bool ServerController::SendWeaponCommands()
{
Stuff::ChainIteratorOf<WeaponUpdate*> iterator(&m_EntityManager->weaponUpdates);
WeaponUpdate *update;
DynamicMemoryStream weapon_bundle_packet(DefaultPacketBufferSize);
while ((update = iterator.GetCurrent()) != NULL)
{
if (update->originator.GetCurrent())
{
DynamicMemoryStream weapon_packet(MWEntityManager::Packet_Buffer, DefaultPacketBufferSize);
int message_type = 0;
bool fire_weapon = false;
if (update->originator.GetCurrent()->IsPlayerVehicle())
message_type = MWEntityManager::StartThirdPersonWeaponMessageID;
else
message_type = MWEntityManager::StartAIWeaponMessageID;
if (update->target.GetCurrent() == NULL)
{
// SPEWALWAYS(("jackyc", "Server Sends - Third Person Weapon To No Target"));
message_type += MWEntityManager::ToNoTargetOffset;
Point3D min(Point3D::Identity);
Point3D max(Point3D::Identity);
Map::GetInstance()->GetMapExtents(&min.z, &max.z, &min.x, &max.x);
Point3D origin;
origin = update->originator.GetCurrent()->GetLocalToWorld();
update->targetOffset = ClampPoint(origin, update->targetOffset, min, max);
Clamp(update->targetOffset.y, -1000.0f, 1000.0f);
fire_weapon = true;
}
else if (update->target.GetCurrent() == Map::GetInstance())
{
message_type += MWEntityManager::ToGroundOffset;
fire_weapon = true;
}
else if (update->target.GetCurrent()->GetReplicatorID().connectionID == Connection::Hermit->GetID())
{
// SPEWALWAYS(("jackyc", "Server Sends - Third Person Weapon To Ground"));
message_type += MWEntityManager::ToGroundOffset;
Point3D new_point;
new_point.Multiply(update->targetOffset, update->target.GetCurrent()->GetLocalToWorld());
update->targetOffset = new_point;
update->target.Remove();
update->target.Add( Map::GetInstance() );
fire_weapon = true;
}
else if (update->target.GetCurrent()->GetReplicatorID().connectionID != Connection::Server->GetID())
{
// SPEWALWAYS(("jackyc", "Server Sends - Third Person Weapon To Mech"));
message_type += MWEntityManager::ToMechOffset;
fire_weapon = true;
}
else if (update->target.GetCurrent()->GetReplicatorID().connectionID == Connection::Server->GetID())
{
// SPEWALWAYS(("jackyc", "Server Sends - Third Person Weapon To Server"));
// we hit a server object
message_type += MWEntityManager::ToServerOffset;
fire_weapon = true;
}
if (fire_weapon)
{
WeaponCommand::SpecialEncode((BYTE)Connection::Server->GetID(), message_type, *update, &weapon_packet);
//weapon_packet.WriteByteAlign();
//weapon_packet.Rewind();
weapon_packet.WriteByteAlign();
weapon_packet.Rewind();
int size = weapon_packet.GetBufferBytesUsed();
weapon_bundle_packet.WriteBytes(&size, 1);
weapon_bundle_packet.WriteBytes(&message_type, 1);
weapon_bundle_packet.WriteBytes(weapon_packet.GetPointer(), size);
// SPEW(("jackyc", "SIZE - %d", size));
// SPEW(("jackyc", "TYPE - %d", message_type));
}
iterator.Remove();
delete update;
if (weapon_bundle_packet.GetBufferBytesUsed() + 45 >= Network::DefaultPacketSize)
break;
}
else
{
iterator.Remove();
delete update;
}
}
if (weapon_bundle_packet.GetBufferBytesUsed() > 0)
{
for (int i = 0; i < Maximum_Players; ++i)
{
if(MWApplication::GetInstance()->servedConnectionData[i].clientReady)
{
if (i == Connection::Server->GetID()) {
if ((g_nMR != 1) || (g_MRF.m_nCount < 0))
continue;
}
Network::GetInstance()->SendNetMessage(i, MWEntityManager::WeaponBundleMessageID, &weapon_bundle_packet, false);
Network::GetInstance()->netStatCollector[Network::OutgoingWeaponMessageBitSizeStat].AddToStatistic(i,weapon_bundle_packet.GetBufferBytesUsed()*8);
}
}
}
if (iterator.GetCurrent())
return true;
return false;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void ServerController::SendAIWeaponCommands()
{
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void ServerController::RespawnClient(int connection_id, Point3D translation)
{
waitingForRespawn[connection_id] = true;
lastReportedPosition[connection_id] = translation;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void ServerController::ThrottleTest(int connection_id)
{
MWApplication *app = MWApplication::GetInstance();
Network *net = Network::GetInstance();
if (app->servedConnectionData[connection_id].bandwidthThrottle)
return;
Scalar cur_time = (Scalar)gos_GetElapsedTime();
if (app->servedConnectionData[connection_id].timeSinceLastThrottleTest == -1.0f)
{
app->servedConnectionData[connection_id].timeSinceLastThrottleTest = cur_time;
net->packetsSent[connection_id] = 0;
net->packetsDropped[connection_id] = 0;
}
else if (cur_time - app->servedConnectionData[connection_id].timeSinceLastThrottleTest > 30.0f)
{
Scalar percent = 0.0f;
app->servedConnectionData[connection_id].timeSinceLastThrottleTest = cur_time;
if (net->packetsSent[connection_id])
{
percent = (Scalar)net->packetsDropped[connection_id] / (Scalar)net->packetsSent[connection_id];
}
if (percent > 0.1)
{
//PAUSE(("THROTTLE TEST"));
app->servedConnectionData[connection_id].bandwidthThrottle = 1;
MWEntityManager::GetInstance()->UpdateDictionaries(connection_id);
}
}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
ClientController::ClientController()
{
m_EntityManager = Cast_Object(MWEntityManager*, EntityManager::GetInstance());
controlUpdateTimer = 0.0f;
lastControlPacketID = 0;
lastPingDelta = 0.0f;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
ClientController::~ClientController()
{
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void ClientController::Reset()
{
controlUpdateTimer = 0.0f;
securityQuery.Reset();
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void ClientController::SendControlPacketToServer(Scalar time_slice)
{
controlUpdateTimer += time_slice;
MWPlayer *player = Cast_Object(MWPlayer *, MWPlayer::GetInstance());
VehicleInterface *veh_interface = Cast_Object(VehicleInterface *, player->playerInterface);
if (!veh_interface->observerMode)
{
if (MWEntityManager::GetInstance() == NULL)
return;
MWEntityManager *manager = Cast_Object (MWEntityManager*, MWEntityManager::GetInstance());
if (manager->GetDictionaryManager(Connection::Local->GetID()) == NULL)
return;
Dictionary *dictionary = manager->GetDictionaryManager(Connection::Local->GetID())->GetCurrentDictionary();
if (dictionary == NULL)
return;
int rate_type = manager->bitManager->GetUpdateRate(UpdateManager::MechPositionUpdateID, dictionary->dictionaryBandwidth).m_ActiveRate;
Scalar rate = DictionaryPage::CalculateSeconds(rate_type);
if (controlUpdateTimer < rate)
{
return;
}
controlUpdateTimer = 0.0f;
DynamicMemoryStream movement_packet(MWEntityManager::Packet_Buffer, DefaultPacketBufferSize);
movement_packet.WriteBits(&dictionary->versionNumber,8);
++lastControlPacketID;
if (lastControlPacketID == 255)
lastControlPacketID = 0;
movement_packet.WriteBits(&lastControlPacketID,8);
movement_packet.WriteBits(&lastPingDelta, 32);
Scalar current_time = (float)(gos_GetElapsedTime(1) * 1000.0);
movement_packet.WriteBits(&current_time, 32);
//SPEWALWAYS(("jerryeds", "C-SEND - %d : t2-t1 : %f, t3 : %f", lastControlPacketID, lastPingDelta, current_time));
SecurityQuery::Encode(player->vehicle, &movement_packet, player->vehicle->GetReplicatorID().connectionID, dictionary->debugDictionaryLevel, dictionary->dictionaryBandwidth);
MechPositionUpdate::Encode(player->vehicle, &movement_packet, player->vehicle->GetReplicatorID().connectionID, dictionary->debugDictionaryLevel, dictionary->dictionaryBandwidth);
SecurityResponse::Encode(player->vehicle, &movement_packet, player->vehicle->GetReplicatorID().connectionID, dictionary->debugDictionaryLevel, dictionary->dictionaryBandwidth);
ExternalJumpJetUpdate::Encode(player->vehicle, &movement_packet, player->vehicle->GetReplicatorID().connectionID, dictionary->debugDictionaryLevel, dictionary->dictionaryBandwidth);
//MechMovemntUpdate::Encode(player->vehicle, &movement_packet, player->vehicle->GetReplicatorID().connectionID, dictionary->debugDictionaryLevel, dictionary->dictionaryBandwidth);
//MechAnimationUpdate::Encode(player->vehicle, &movement_packet, player->vehicle->GetReplicatorID().connectionID, dictionary->debugDictionaryLevel, dictionary->dictionaryBandwidth);
movement_packet.WriteBits(&m_EntityManager->commandCount, 8);
Verify(m_EntityManager->commandCount < 256);
ChainIteratorOf<VehicleCommand*> command_iterator(&m_EntityManager->quedCommands);
VehicleCommand *command;
while ((command = command_iterator.GetCurrent()) != NULL)
{
movement_packet.WriteBits(&command->m_Command, 5);
m_EntityManager->commandCount--;
command_iterator.Remove();
delete command;
}
Verify(m_EntityManager->commandCount == 0);
movement_packet.WriteByteAlign();
movement_packet.Rewind();
Network::GetInstance()->SendNetMessage(Connection::Server->GetID(), MWEntityManager::FirstPersonControlMessageID, &movement_packet, false);
}
else
{
if (controlUpdateTimer < 1.0f)
{
return;
}
controlUpdateTimer = 0.0f;
Point3D viewing_position;
YawPitchRoll viewing_rotation;
//if(veh_interface->observingEntity.GetCurrent() != NULL)
//{
// viewing_position = veh_interface->observingEntity.GetCurrent()->GetLocalToWorld();
// viewing_rotation = veh_interface->observingEntity.GetCurrent()->GetLocalToWorld();
//}
//else
//{
// viewing_position = veh_interface->vehicle->GetLocalToWorld();
// viewing_rotation = veh_interface->vehicle->GetLocalToWorld();
//}
viewing_position = Player::GetInstance()->GetEyePoint();
viewing_rotation = Player::GetInstance()->GetEyePoint();
DynamicMemoryStream movement_packet(MWEntityManager::Packet_Buffer, DefaultPacketBufferSize);
Scalar min_z, max_z, min_x, max_x;
Map::GetInstance()->GetMapExtents(&min_z, &max_z, &min_x, &max_x);
movement_packet.WriteScaledFloatToBits(viewing_position.x, min_x, max_x, 24);
movement_packet.WriteScaledFloatToBits(viewing_position.y, -2005.0f, 1005.0f, 24);
movement_packet.WriteScaledFloatToBits(viewing_position.z, min_z, max_z, 24);
movement_packet.WriteScaledFloatToBits(viewing_rotation.yaw.angle, -Stuff::Pi, Stuff::Pi, 24);
movement_packet.WriteBits(&lastPingDelta, 32);
Scalar current_time = (float)(gos_GetElapsedTime(1) * 1000.0);
movement_packet.WriteBits(&current_time, 32);
SecurityQuery::Encode(player->vehicle, &movement_packet, player->vehicle->GetReplicatorID().connectionID, 0, 0);
SecurityResponse::Encode(player->vehicle, &movement_packet, player->vehicle->GetReplicatorID().connectionID, 0, 0);
movement_packet.Rewind();
//SPEWALWAYS(("jerryeds","SEND CAM - %f %f %f : %f", viewing_position.x, viewing_position.y, viewing_position.z, viewing_rotation.yaw.angle));
Network::GetInstance()->SendNetMessage(Connection::Server->GetID(), MWEntityManager::FirstPersonObserverControlMessageID, &movement_packet, false);
Network::GetInstance()->netStatCollector[Network::OutgoingMechMovementBitSizeStat].AddToStatistic(Connection::Server->GetID(),72);
}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void ClientController::SendWeaponCommands(void)
{
Stuff::ChainIteratorOf<WeaponUpdate*> iterator(&m_EntityManager->weaponUpdates);
WeaponUpdate *update;
while ((update = iterator.GetCurrent()) != NULL)
{
int message_type = 0;
bool fire_weapon = false;
if (update->target.GetCurrent() == NULL)
{
// SPEWALWAYS(("jackyc", "Client Sends - First Person Weapon To No Target"));
message_type = MWEntityManager::FirstPersonWeaponNoTargetCommandMessageID;
Point3D min(Point3D::Identity);
Point3D max(Point3D::Identity);
Map::GetInstance()->GetMapExtents(&min.z, &max.z, &min.x, &max.x);
Point3D origin;
origin = update->originator.GetCurrent()->GetLocalToWorld();
update->targetOffset = ClampPoint(origin, update->targetOffset, min, max);
Clamp(update->targetOffset.y, -1000.0f, 1000.0f);
fire_weapon = true;
}
else if (update->target.GetCurrent() == Map::GetInstance())
{
// SPEWALWAYS(("jackyc", "Client Sends - First Person Weapon To Ground"));
message_type = MWEntityManager::FirstPersonWeaponToGroundCommandMessageID;
fire_weapon = true;
}
else if (update->target.GetCurrent()->GetReplicatorID().connectionID == Connection::Hermit->GetID())
{
// SPEWALWAYS(("jackyc", "Client Sends - First Person Weapon To Ground"));
message_type = MWEntityManager::FirstPersonWeaponToGroundCommandMessageID;
Point3D new_point;
new_point.Multiply(update->targetOffset, update->target.GetCurrent()->GetLocalToWorld());
update->targetOffset = new_point;
update->target.Add( Map::GetInstance() );
fire_weapon = true;
}
else if (update->target.GetCurrent()->GetReplicatorID().connectionID != Connection::Server->GetID())
{
// SPEWALWAYS(("jackyc", "Client Sends - First Person Weapon To Mech"));
message_type = MWEntityManager::FirstPersonWeaponToMechCommandMessageID;
fire_weapon = true;
}
else if (update->target.GetCurrent()->GetReplicatorID().connectionID == Connection::Server->GetID())
{
// SPEWALWAYS(("jackyc", "Client Sends - First Person Weapon To Server Object"));
// we hit a server object
message_type = MWEntityManager::FirstPersonWeaponToServerObjectCommandMessageID;
fire_weapon = true;
}
if (fire_weapon)
{
DynamicMemoryStream weapon_packet(MWEntityManager::Packet_Buffer, DefaultPacketBufferSize);
WeaponCommand::SpecialEncode((BYTE)Connection::Server->GetID(), message_type, *update, &weapon_packet);
weapon_packet.WriteByteAlign();
weapon_packet.Rewind();
Network::GetInstance()->netStatCollector[Network::OutgoingWeaponMessageBitSizeStat].AddToStatistic(Connection::Server->GetID(),weapon_packet.GetBufferBytesUsed()*8);
Network::GetInstance()->SendNetMessage(Connection::Server->GetID(), message_type, &weapon_packet, false);
}
iterator.Remove();
delete update;
}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void ClientController::ReceiveWeaponCommand(int connection, int message_type, Stuff::MemoryStream *message)
{
Verify(message_type >= MWEntityManager::StartThirdPersonWeaponMessageID && message_type <= MWEntityManager::EndAIWeaponMessageID);
Verify(!Network::GetInstance()->AmIServer());
#if defined(_DEBUG) && 0 // jcem - for MR test
{
char Buffer[128];
sprintf(Buffer, "Client::ReceiveWeaponCommand\n");
OutputDebugString(Buffer);
}
#endif // _DEBUG && ...
WeaponUpdate *data = new WeaponUpdate;
WeaponCommand::SpecialDecode(connection, message_type, *data, message);
//SPEW(("jerryeds", "CLEINT RECEIVED WEAPON COMMAND FROM : %d ", data.originator->GetReplicatorID().connectionID));
// create the collision packet and fire the weapon
//m_EntityManager->CreateWeaponEffect(data);
m_EntityManager->QueWeapon(data);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void ClientController::ReceiveWeaponBundle(int connection, int message_type, Stuff::MemoryStream *message)
{
Verify(message_type == MWEntityManager::WeaponBundleMessageID);
if (g_nMR != 2)
Verify(!Network::GetInstance()->AmIServer());
while (message->GetBytesRemaining())
{
int size = 0;
int real_type = 0;
message->ReadBytes(&size,1);
message->ReadBytes(&real_type,1);
// SPEW(("jackyc", "SIZE - %d", size));
// SPEW(("jackyc", "TYPE - %d", real_type));
MemoryStream sub_message(message->GetPointer(), size);
message->AdvancePointer(size);
WeaponUpdate *data = new WeaponUpdate;
WeaponCommand::SpecialDecode(connection, real_type, *data, &sub_message);
//SPEW(("jerryeds", "CLEINT RECEIVED WEAPON COMMAND FROM : %d ", data.originator->GetReplicatorID().connectionID));
// create the collision packet and fire the weapon
//m_EntityManager->CreateWeaponEffect(data);
m_EntityManager->QueWeapon(data);
}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void ClientController::RespawnClient(int connection_id)
{
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void ClientController::ReceiveFullConfirmation(Stuff::MemoryStream *message)
{
MWEntityManager *manager = Cast_Object (MWEntityManager*, MWEntityManager::GetInstance());
DictionaryManager *dictionary_manager = manager->GetDictionaryManager(Connection::Local->GetID());
if(dictionary_manager != NULL)
{
int version = 0;
message->ReadBits(&version,8);
Dictionary *dictionary = dictionary_manager->GetDictionary(version);
if (dictionary != NULL)
{
Player *player = MWApplication::GetInstance()->servedConnectionData[Connection::Local->GetID()].clientPlayer;
int rate_type = manager->bitManager->GetUpdateRate(UpdateManager::MechPositionUpdateID, dictionary->dictionaryBandwidth).m_ActiveRate;
Scalar rate = DictionaryPage::CalculateSeconds(rate_type);
MechPositionUpdate::Decode(player->vehicle, message, 0.0, 0.0f, Connection::Local->GetID(), dictionary->debugDictionaryLevel, dictionary->dictionaryBandwidth, rate);
ExternalJumpJetUpdate::Decode(player->vehicle, message, 0.0, 0.0f, Connection::Local->GetID(), dictionary->debugDictionaryLevel, dictionary->dictionaryBandwidth, rate);
MechInternalDamageUpdate::Decode(player->vehicle, message, 0.0, 0.0f, Connection::Local->GetID(), dictionary->debugDictionaryLevel, dictionary->dictionaryBandwidth, rate);
#if 0
YawPitchRoll ypr;
Point3D position;
Vehicle *vehicle = Cast_Object(Vehicle *, player->vehicle);
vehicle->GetDeadReckonedNetworkPosition(position, ypr);
#endif
//SPEW(("jerryeds","MOVEMENT CONF : %f %f %f", position.x, position.y, position.z));
}
}
}