source-engine/engine/NetworkStringTableItem.cpp

233 lines
4.7 KiB
C++

//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include "quakedef.h"
#include "networkstringtableitem.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
CNetworkStringTableItem::CNetworkStringTableItem( void )
{
m_pUserData = NULL;
m_nUserDataLength = 0;
m_nTickChanged = 0;
#ifndef SHARED_NET_STRING_TABLES
m_nTickCreated = 0;
m_pChangeList = NULL;
#endif
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
CNetworkStringTableItem::~CNetworkStringTableItem( void )
{
#ifndef SHARED_NET_STRING_TABLES
if ( m_pChangeList )
{
// free changelist and elements
for ( int i=0; i < m_pChangeList->Count(); i++ )
{
itemchange_s item = m_pChangeList->Element( i );
if ( item.data )
delete[] item.data;
}
delete m_pChangeList; // destructor calls Purge()
m_pUserData = NULL;
}
#endif
if ( m_pUserData )
{
delete[] m_pUserData;
}
}
#ifndef SHARED_NET_STRING_TABLES
void CNetworkStringTableItem::EnableChangeHistory( void )
{
if ( m_pChangeList )
return; // already enabled
m_pChangeList = new CUtlVector<itemchange_s>;
Assert ( m_pChangeList );
}
void CNetworkStringTableItem::UpdateChangeList( int tick, int length, const void *userData )
{
int count = m_pChangeList->Count();
itemchange_s item;
if ( count > 0 )
{
// check if different from last change in list
item = m_pChangeList->Element( count-1 );
if ( !item.data && !userData )
return; // both NULL data
if ( item.length == length )
{
if ( item.data && userData )
{
if ( Q_memcmp( (void*)userData, (void*)item.data, length ) == 0 )
{
return; // no data or size change
}
}
}
if ( item.tick == tick )
{
// two changes within same tick frame, remove last change from list
if ( item.data )
{
delete[] item.data;
}
m_pChangeList->Remove( count-1 );
}
}
item.tick = tick;
// add new user data and time stamp
if ( userData && length )
{
item.data = new unsigned char[length];
item.length = length;
Q_memcpy( item.data, userData, length );
}
else
{
item.data = NULL;
item.length = 0;
}
m_pChangeList->AddToTail( item );
}
int CNetworkStringTableItem::RestoreTick( int tick )
{
Assert( m_pChangeList->Count()>0 );
int index = 1;
itemchange_s *item = &m_pChangeList->Element( 0 );
while ( index < m_pChangeList->Count() )
{
itemchange_s *nextitem = &m_pChangeList->Element( index );
if ( nextitem->tick > tick )
{
break;
}
item = nextitem;
index++;
}
if ( item->tick > tick )
{
// this string was created after tick, so ignore it right now
m_pUserData = NULL;
m_nUserDataLength = 0;
m_nTickChanged = 0;
}
else
{
// restore user data for this string
m_pUserData = item->data;
m_nUserDataLength = item->length;
m_nTickChanged = item->tick;
}
return m_nTickChanged;
}
#endif
//-----------------------------------------------------------------------------
// Purpose:
// Input : *string -
//-----------------------------------------------------------------------------
bool CNetworkStringTableItem::SetUserData( int tick, int length, const void *userData )
{
#ifndef SHARED_NET_STRING_TABLES
if ( m_pChangeList )
{
UpdateChangeList( tick, length, userData );
return false;
}
Assert ( m_nTickCreated > 0 && m_nTickCreated <= tick );
#endif
Assert ( m_nTickChanged > 0 && m_nTickChanged <= tick );
Assert ( length < CNetworkStringTableItem::MAX_USERDATA_SIZE );
// no old or new data
if ( !userData && !m_pUserData )
return false;
if ( m_pUserData &&
length == m_nUserDataLength &&
!Q_memcmp( m_pUserData, (void*)userData, length ) )
{
return false; // old & new data are equal
}
if ( m_pUserData )
delete[] m_pUserData;
m_nUserDataLength = length;
if ( length > 0 )
{
m_pUserData = new unsigned char[ALIGN_VALUE( length, 4 )];
Q_memcpy( m_pUserData, userData, length );
}
else
{
m_pUserData = NULL;
}
m_nTickChanged = tick;
return true;
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : stringNumber -
// Output : const void
//-----------------------------------------------------------------------------
const void *CNetworkStringTableItem::GetUserData( int *length )
{
if ( length )
*length = m_nUserDataLength;
return ( const void * )m_pUserData;
}