208 lines
5.2 KiB
C++
208 lines
5.2 KiB
C++
//========= 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;
|
|
|
|
for( int i=0; i<MAXSTUDIOPOSEPARAM; i++ )
|
|
{
|
|
m_flPoseParameters[i] = src.m_flPoseParameters[i];
|
|
}
|
|
}
|
|
|
|
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();
|
|
}
|
|
|
|
for( int i=0; i<MAXSTUDIOPOSEPARAM; i++ )
|
|
{
|
|
m_flPoseParameters[i] = 0;
|
|
}
|
|
}
|
|
|
|
// 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;
|
|
|
|
float m_flPoseParameters[MAXSTUDIOPOSEPARAM];
|
|
};
|
|
|
|
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 |