You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
196 lines
4.9 KiB
196 lines
4.9 KiB
//========= Copyright © 1996-2006, Valve Corporation, All rights reserved. ============// |
|
// |
|
// Purpose: Manages the server moving things back in time to match up to where clients thought they were |
|
// when the client commited an action |
|
// |
|
// $NoKeywords: $ |
|
//=============================================================================// |
|
|
|
#ifndef _PLAYER_LAG_COMPENSATION_H_ |
|
#define _PLAYER_LAG_COMPENSATION_H_ |
|
|
|
#ifdef _WIN32 |
|
#pragma once |
|
#endif |
|
|
|
#include "igamesystem.h" |
|
#include "ilagcompensationmanager.h" |
|
#include "utllinkedlist.h" |
|
|
|
#define MAX_LAYER_RECORDS (CBaseAnimatingOverlay::MAX_OVERLAYS) |
|
|
|
struct LayerRecord |
|
{ |
|
int m_sequence; |
|
float m_cycle; |
|
float m_weight; |
|
int m_order; |
|
|
|
LayerRecord() |
|
{ |
|
Clear(); |
|
} |
|
|
|
LayerRecord( const LayerRecord& src ) |
|
{ |
|
m_sequence = src.m_sequence; |
|
m_cycle = src.m_cycle; |
|
m_weight = src.m_weight; |
|
m_order = src.m_order; |
|
} |
|
|
|
void Clear() |
|
{ |
|
m_sequence = 0; |
|
m_cycle = 0; |
|
m_weight = 0; |
|
m_order = 0; |
|
} |
|
}; |
|
|
|
struct LagRecord |
|
{ |
|
public: |
|
LagRecord() |
|
{ |
|
Clear(); |
|
} |
|
|
|
LagRecord( const LagRecord& src ) |
|
{ |
|
m_fFlags = src.m_fFlags; |
|
m_vecOrigin = src.m_vecOrigin; |
|
m_vecAngles = src.m_vecAngles; |
|
m_vecMins = src.m_vecMins; |
|
m_vecMaxs = src.m_vecMaxs; |
|
m_flSimulationTime = src.m_flSimulationTime; |
|
for( int layerIndex = 0; layerIndex < MAX_LAYER_RECORDS; ++layerIndex ) |
|
{ |
|
m_layerRecords[layerIndex] = src.m_layerRecords[layerIndex]; |
|
} |
|
m_masterSequence = src.m_masterSequence; |
|
m_masterCycle = src.m_masterCycle; |
|
} |
|
|
|
void Clear() |
|
{ |
|
m_fFlags = 0; |
|
m_vecOrigin.Init(); |
|
m_vecAngles.Init(); |
|
m_vecMins.Init(); |
|
m_vecMaxs.Init(); |
|
m_flSimulationTime = -1; |
|
m_masterSequence = 0; |
|
m_masterCycle = 0; |
|
for( int layerIndex = 0; layerIndex < MAX_LAYER_RECORDS; ++layerIndex ) |
|
{ |
|
m_layerRecords[layerIndex].Clear(); |
|
} |
|
} |
|
|
|
// Did player die this frame |
|
int m_fFlags; |
|
|
|
// Player position, orientation and bbox |
|
Vector m_vecOrigin; |
|
QAngle m_vecAngles; |
|
Vector m_vecMins; |
|
Vector m_vecMaxs; |
|
|
|
float m_flSimulationTime; |
|
|
|
// Player animation details, so we can get the legs in the right spot. |
|
LayerRecord m_layerRecords[MAX_LAYER_RECORDS]; |
|
int m_masterSequence; |
|
float m_masterCycle; |
|
}; |
|
|
|
typedef CUtlFixedLinkedList< LagRecord > LagRecordList; |
|
|
|
//----------------------------------------------------------------------------- |
|
class CLagCompensationManager : public CAutoGameSystemPerFrame, public ILagCompensationManager |
|
{ |
|
public: |
|
CLagCompensationManager( char const *name ) : |
|
CAutoGameSystemPerFrame( name ), |
|
m_CompensatedEntities( 0, 0, DefLessFunc( EHANDLE ) ), |
|
m_AdditionalEntities( 0, 0, DefLessFunc( EHANDLE ) ) |
|
{ |
|
m_bNeedToRestore = false; |
|
m_weaponRange = 0.0f; |
|
m_isCurrentlyDoingCompensation = false; |
|
} |
|
|
|
// IServerSystem stuff |
|
virtual void Shutdown() |
|
{ |
|
ClearHistory(); |
|
} |
|
|
|
virtual void LevelShutdownPostEntity() |
|
{ |
|
ClearHistory(); |
|
} |
|
|
|
// called after entities think |
|
virtual void FrameUpdatePostEntityThink(); |
|
|
|
// ILagCompensationManager stuff |
|
|
|
// Called during player movement to set up/restore after lag compensation |
|
void StartLagCompensation( CBasePlayer *player, LagCompensationType lagCompensationType, const Vector& weaponPos = vec3_origin, const QAngle &weaponAngles = vec3_angle, float weaponRange = 0.0f ); |
|
void FinishLagCompensation( CBasePlayer *player ); |
|
|
|
// Mappers can flag certain additional entities to lag compensate, this handles them |
|
virtual void AddAdditionalEntity( CBaseEntity *pEntity ); |
|
virtual void RemoveAdditionalEntity( CBaseEntity *pEntity ); |
|
|
|
void RecordDataIntoTrack( CBaseEntity *entity, LagRecordList *track, bool wantsAnims ); |
|
bool BacktrackEntity( CBaseEntity *entity, float flTargetTime, LagRecordList *track, LagRecord *restore, LagRecord *change, bool wantsAnims ); |
|
void RestoreEntityFromRecords( CBaseEntity *entity, LagRecord *restore, LagRecord *change, bool wantsAnims ); |
|
private: |
|
|
|
|
|
void ClearHistory() |
|
{ |
|
FOR_EACH_MAP( m_CompensatedEntities, i ) |
|
{ |
|
delete m_CompensatedEntities[ i ]; |
|
} |
|
m_CompensatedEntities.Purge(); |
|
} |
|
|
|
struct EntityLagData |
|
{ |
|
EntityLagData() : m_bRestoreEntity( false ) |
|
{ |
|
} |
|
|
|
// True if lag compensation altered entity data |
|
bool m_bRestoreEntity; |
|
// keep a list of lag records for each player |
|
LagRecordList m_LagRecords; |
|
|
|
// Entity data before we moved him back |
|
LagRecord m_RestoreData; |
|
// Entity data where we moved him back |
|
LagRecord m_ChangeData; |
|
}; |
|
|
|
CUtlMap< EHANDLE, EntityLagData * > m_CompensatedEntities; |
|
|
|
// True if at least one entity was changed |
|
bool m_bNeedToRestore; |
|
CBasePlayer *m_pCurrentPlayer; // The player we are doing lag compensation for |
|
|
|
LagCompensationType m_lagCompensationType; |
|
Vector m_weaponPos; |
|
QAngle m_weaponAngles; |
|
float m_weaponRange; |
|
bool m_isCurrentlyDoingCompensation; // Sentinel to prevent calling StartLagCompensation a second time before a Finish. |
|
|
|
// List of additional entities flagged by mappers for lag compensation (shouldn't be more than a few) |
|
CUtlRBTree< EHANDLE > m_AdditionalEntities; |
|
}; |
|
|
|
#endif |