Store dummy snapshots for better dummy switching

This commit is contained in:
def 2014-05-03 20:24:45 +02:00
parent d57634792d
commit 820926d836
2 changed files with 262 additions and 78 deletions

View file

@ -315,8 +315,10 @@ CClient::CClient() : m_DemoPlayer(&m_SnapshotDelta), m_DemoRecorder(&m_SnapshotD
m_aServerAddressStr[0] = 0; m_aServerAddressStr[0] = 0;
mem_zero(m_aSnapshots, sizeof(m_aSnapshots)); mem_zero(m_aSnapshots, sizeof(m_aSnapshots));
m_SnapshotStorage.Init(); m_SnapshotStorage[0].Init();
m_RecivedSnapshots = 0; m_SnapshotStorage[1].Init();
m_RecivedSnapshots[0] = 0;
m_RecivedSnapshots[1] = 0;
m_VersionInfo.m_State = CVersionInfo::STATE_INIT; m_VersionInfo.m_State = CVersionInfo::STATE_INIT;
} }
@ -577,19 +579,15 @@ void CClient::OnEnterGame()
m_CurrentInput = 0; m_CurrentInput = 0;
// reset snapshots // reset snapshots
m_aSnapshots[SNAP_CURRENT] = 0; m_aSnapshots[g_Config.m_ClDummy][SNAP_CURRENT] = 0;
m_aSnapshots[SNAP_PREV] = 0; m_aSnapshots[g_Config.m_ClDummy][SNAP_PREV] = 0;
m_SnapshotStorage.PurgeAll(); m_SnapshotStorage[g_Config.m_ClDummy].PurgeAll();
m_RecivedSnapshots = 0; m_RecivedSnapshots[g_Config.m_ClDummy] = 0;
m_SnapshotParts = 0; m_SnapshotParts = 0;
m_PredTick[0] = 0; m_PredTick[g_Config.m_ClDummy] = 0;
m_PredTick[1] = 0; m_CurrentRecvTick[g_Config.m_ClDummy] = 0;
m_CurrentRecvTick[0] = 0; m_CurGameTick[g_Config.m_ClDummy] = 0;
m_CurrentRecvTick[1] = 0; m_PrevGameTick[g_Config.m_ClDummy] = 0;
m_CurGameTick[0] = 0;
m_CurGameTick[1] = 0;
m_PrevGameTick[0] = 0;
m_PrevGameTick[1] = 0;
} }
void CClient::EnterGame() void CClient::EnterGame()
@ -669,9 +667,9 @@ void CClient::DisconnectWithReason(const char *pReason)
mem_zero(&m_ServerAddress, sizeof(m_ServerAddress)); mem_zero(&m_ServerAddress, sizeof(m_ServerAddress));
// clear snapshots // clear snapshots
m_aSnapshots[SNAP_CURRENT] = 0; m_aSnapshots[g_Config.m_ClDummy][SNAP_CURRENT] = 0;
m_aSnapshots[SNAP_PREV] = 0; m_aSnapshots[g_Config.m_ClDummy][SNAP_PREV] = 0;
m_RecivedSnapshots = 0; m_RecivedSnapshots[g_Config.m_ClDummy] = 0;
} }
void CClient::Disconnect() void CClient::Disconnect()
@ -809,8 +807,8 @@ void *CClient::SnapGetItem(int SnapID, int Index, CSnapItem *pItem)
{ {
CSnapshotItem *i; CSnapshotItem *i;
dbg_assert(SnapID >= 0 && SnapID < NUM_SNAPSHOT_TYPES, "invalid SnapID"); dbg_assert(SnapID >= 0 && SnapID < NUM_SNAPSHOT_TYPES, "invalid SnapID");
i = m_aSnapshots[SnapID]->m_pAltSnap->GetItem(Index); i = m_aSnapshots[g_Config.m_ClDummy][SnapID]->m_pAltSnap->GetItem(Index);
pItem->m_DataSize = m_aSnapshots[SnapID]->m_pAltSnap->GetItemSize(Index); pItem->m_DataSize = m_aSnapshots[g_Config.m_ClDummy][SnapID]->m_pAltSnap->GetItemSize(Index);
pItem->m_Type = i->Type(); pItem->m_Type = i->Type();
pItem->m_ID = i->ID(); pItem->m_ID = i->ID();
return (void *)i->Data(); return (void *)i->Data();
@ -820,12 +818,12 @@ void CClient::SnapInvalidateItem(int SnapID, int Index)
{ {
CSnapshotItem *i; CSnapshotItem *i;
dbg_assert(SnapID >= 0 && SnapID < NUM_SNAPSHOT_TYPES, "invalid SnapID"); dbg_assert(SnapID >= 0 && SnapID < NUM_SNAPSHOT_TYPES, "invalid SnapID");
i = m_aSnapshots[SnapID]->m_pAltSnap->GetItem(Index); i = m_aSnapshots[g_Config.m_ClDummy][SnapID]->m_pAltSnap->GetItem(Index);
if(i) if(i)
{ {
if((char *)i < (char *)m_aSnapshots[SnapID]->m_pAltSnap || (char *)i > (char *)m_aSnapshots[SnapID]->m_pAltSnap + m_aSnapshots[SnapID]->m_SnapSize) if((char *)i < (char *)m_aSnapshots[g_Config.m_ClDummy][SnapID]->m_pAltSnap || (char *)i > (char *)m_aSnapshots[g_Config.m_ClDummy][SnapID]->m_pAltSnap + m_aSnapshots[g_Config.m_ClDummy][SnapID]->m_SnapSize)
m_pConsole->Print(IConsole::OUTPUT_LEVEL_DEBUG, "client", "snap invalidate problem"); m_pConsole->Print(IConsole::OUTPUT_LEVEL_DEBUG, "client", "snap invalidate problem");
if((char *)i >= (char *)m_aSnapshots[SnapID]->m_pSnap && (char *)i < (char *)m_aSnapshots[SnapID]->m_pSnap + m_aSnapshots[SnapID]->m_SnapSize) if((char *)i >= (char *)m_aSnapshots[g_Config.m_ClDummy][SnapID]->m_pSnap && (char *)i < (char *)m_aSnapshots[g_Config.m_ClDummy][SnapID]->m_pSnap + m_aSnapshots[g_Config.m_ClDummy][SnapID]->m_SnapSize)
m_pConsole->Print(IConsole::OUTPUT_LEVEL_DEBUG, "client", "snap invalidate problem"); m_pConsole->Print(IConsole::OUTPUT_LEVEL_DEBUG, "client", "snap invalidate problem");
i->m_TypeAndID = -1; i->m_TypeAndID = -1;
} }
@ -836,12 +834,12 @@ void *CClient::SnapFindItem(int SnapID, int Type, int ID)
// TODO: linear search. should be fixed. // TODO: linear search. should be fixed.
int i; int i;
if(!m_aSnapshots[SnapID]) if(!m_aSnapshots[g_Config.m_ClDummy][SnapID])
return 0x0; return 0x0;
for(i = 0; i < m_aSnapshots[SnapID]->m_pSnap->NumItems(); i++) for(i = 0; i < m_aSnapshots[g_Config.m_ClDummy][SnapID]->m_pSnap->NumItems(); i++)
{ {
CSnapshotItem *pItem = m_aSnapshots[SnapID]->m_pAltSnap->GetItem(i); CSnapshotItem *pItem = m_aSnapshots[g_Config.m_ClDummy][SnapID]->m_pAltSnap->GetItem(i);
if(pItem->Type() == Type && pItem->ID() == ID) if(pItem->Type() == Type && pItem->ID() == ID)
return (void *)pItem->Data(); return (void *)pItem->Data();
} }
@ -851,9 +849,9 @@ void *CClient::SnapFindItem(int SnapID, int Type, int ID)
int CClient::SnapNumItems(int SnapID) int CClient::SnapNumItems(int SnapID)
{ {
dbg_assert(SnapID >= 0 && SnapID < NUM_SNAPSHOT_TYPES, "invalid SnapID"); dbg_assert(SnapID >= 0 && SnapID < NUM_SNAPSHOT_TYPES, "invalid SnapID");
if(!m_aSnapshots[SnapID]) if(!m_aSnapshots[g_Config.m_ClDummy][SnapID])
return 0; return 0;
return m_aSnapshots[SnapID]->m_pSnap->NumItems(); return m_aSnapshots[g_Config.m_ClDummy][SnapID]->m_pSnap->NumItems();
} }
void CClient::SnapSetStaticsize(int ItemType, int Size) void CClient::SnapSetStaticsize(int ItemType, int Size)
@ -1014,7 +1012,7 @@ const char *CClient::LoadMap(const char *pName, const char *pFilename, unsigned
char aBuf[256]; char aBuf[256];
str_format(aBuf, sizeof(aBuf), "loaded map '%s'", pFilename); str_format(aBuf, sizeof(aBuf), "loaded map '%s'", pFilename);
m_pConsole->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "client", aBuf); m_pConsole->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "client", aBuf);
m_RecivedSnapshots = 0; m_RecivedSnapshots[g_Config.m_ClDummy] = 0;
str_copy(m_aCurrentMap, pName, sizeof(m_aCurrentMap)); str_copy(m_aCurrentMap, pName, sizeof(m_aCurrentMap));
m_CurrentMapCrc = m_pMap->Crc(); m_CurrentMapCrc = m_pMap->Crc();
@ -1604,9 +1602,9 @@ void CClient::ProcessServerPacket(CNetChunk *pPacket)
// find delta // find delta
if(DeltaTick >= 0) if(DeltaTick >= 0)
{ {
int DeltashotSize = m_SnapshotStorage.Get(DeltaTick, 0, &pDeltaShot, 0); int DeltashotSize = m_SnapshotStorage[g_Config.m_ClDummy].Get(DeltaTick, 0, &pDeltaShot, 0);
if(DeltashotSize < 0 || g_Config.m_ClDummy != m_LastDummy) if(DeltashotSize < 0)
{ {
// couldn't find the delta snapshots that the server used // couldn't find the delta snapshots that the server used
// to compress this snapshot. force the server to resync // to compress this snapshot. force the server to resync
@ -1675,14 +1673,14 @@ void CClient::ProcessServerPacket(CNetChunk *pPacket)
// purge old snapshots // purge old snapshots
PurgeTick = DeltaTick; PurgeTick = DeltaTick;
if(m_aSnapshots[SNAP_PREV] && m_aSnapshots[SNAP_PREV]->m_Tick < PurgeTick) if(m_aSnapshots[g_Config.m_ClDummy][SNAP_PREV] && m_aSnapshots[g_Config.m_ClDummy][SNAP_PREV]->m_Tick < PurgeTick)
PurgeTick = m_aSnapshots[SNAP_PREV]->m_Tick; PurgeTick = m_aSnapshots[g_Config.m_ClDummy][SNAP_PREV]->m_Tick;
if(m_aSnapshots[SNAP_CURRENT] && m_aSnapshots[SNAP_CURRENT]->m_Tick < PurgeTick) if(m_aSnapshots[g_Config.m_ClDummy][SNAP_CURRENT] && m_aSnapshots[g_Config.m_ClDummy][SNAP_CURRENT]->m_Tick < PurgeTick)
PurgeTick = m_aSnapshots[SNAP_CURRENT]->m_Tick; PurgeTick = m_aSnapshots[g_Config.m_ClDummy][SNAP_CURRENT]->m_Tick;
m_SnapshotStorage.PurgeUntil(PurgeTick); m_SnapshotStorage[g_Config.m_ClDummy].PurgeUntil(PurgeTick);
// add new // add new
m_SnapshotStorage.Add(GameTick, time_get(), SnapSize, pTmpBuffer3, 1); m_SnapshotStorage[g_Config.m_ClDummy].Add(GameTick, time_get(), SnapSize, pTmpBuffer3, 1);
// add snapshot to demo // add snapshot to demo
if(m_DemoRecorder.IsRecording()) if(m_DemoRecorder.IsRecording())
@ -1692,26 +1690,26 @@ void CClient::ProcessServerPacket(CNetChunk *pPacket)
} }
// apply snapshot, cycle pointers // apply snapshot, cycle pointers
m_RecivedSnapshots++; m_RecivedSnapshots[g_Config.m_ClDummy]++;
m_CurrentRecvTick[g_Config.m_ClDummy] = GameTick; m_CurrentRecvTick[g_Config.m_ClDummy] = GameTick;
// we got two snapshots until we see us self as connected // we got two snapshots until we see us self as connected
if(m_RecivedSnapshots == 2) if(m_RecivedSnapshots[g_Config.m_ClDummy] == 2)
{ {
// start at 200ms and work from there // start at 200ms and work from there
m_PredictedTime[g_Config.m_ClDummy].Init(GameTick*time_freq()/50); m_PredictedTime[g_Config.m_ClDummy].Init(GameTick*time_freq()/50);
m_PredictedTime[g_Config.m_ClDummy].SetAdjustSpeed(1, 1000.0f); m_PredictedTime[g_Config.m_ClDummy].SetAdjustSpeed(1, 1000.0f);
m_GameTime[g_Config.m_ClDummy].Init((GameTick-1)*time_freq()/50); m_GameTime[g_Config.m_ClDummy].Init((GameTick-1)*time_freq()/50);
m_aSnapshots[SNAP_PREV] = m_SnapshotStorage.m_pFirst; m_aSnapshots[g_Config.m_ClDummy][SNAP_PREV] = m_SnapshotStorage[g_Config.m_ClDummy].m_pFirst;
m_aSnapshots[SNAP_CURRENT] = m_SnapshotStorage.m_pLast; m_aSnapshots[g_Config.m_ClDummy][SNAP_CURRENT] = m_SnapshotStorage[g_Config.m_ClDummy].m_pLast;
m_LocalStartTime = time_get(); m_LocalStartTime = time_get();
SetState(IClient::STATE_ONLINE); SetState(IClient::STATE_ONLINE);
DemoRecorder_HandleAutoStart(); DemoRecorder_HandleAutoStart();
} }
// adjust game time // adjust game time
if(m_RecivedSnapshots > 2) if(m_RecivedSnapshots[g_Config.m_ClDummy] > 2)
{ {
int64 Now = m_GameTime[g_Config.m_ClDummy].Get(time_get()); int64 Now = m_GameTime[g_Config.m_ClDummy].Get(time_get());
int64 TickStart = GameTick*time_freq()/50; int64 TickStart = GameTick*time_freq()/50;
@ -1750,15 +1748,201 @@ void CClient::ProcessServerPacketDummy(CNetChunk *pPacket)
if(Sys) if(Sys)
{ {
// system message if(Msg == NETMSG_CON_READY)
if(Msg == NETMSG_MAP_CHANGE || Msg == NETMSG_MAP_DATA || Msg == NETMSG_PING || Msg == NETMSG_RCON_CMD_ADD || Msg == NETMSG_RCON_CMD_REM || Msg == NETMSG_RCON_AUTH_STATUS || Msg == NETMSG_RCON_LINE || Msg == NETMSG_PING_REPLY || Msg == NETMSG_INPUTTIMING || Msg == NETMSG_SNAP || Msg == NETMSG_SNAPSINGLE || Msg == NETMSG_SNAPEMPTY)
{
return; // no need of all that stuff for the dummy
}
else if(Msg == NETMSG_CON_READY)
{ {
GameClient()->OnConnected(); GameClient()->OnConnected();
} }
else if(Msg == NETMSG_SNAP || Msg == NETMSG_SNAPSINGLE || Msg == NETMSG_SNAPEMPTY)
{
int NumParts = 1;
int Part = 0;
int GameTick = Unpacker.GetInt();
int DeltaTick = GameTick-Unpacker.GetInt();
int PartSize = 0;
int Crc = 0;
int CompleteSize = 0;
const char *pData = 0;
// only allow packets from the server we actually want
if(net_addr_comp(&pPacket->m_Address, &m_ServerAddress))
return;
// we are not allowed to process snapshot yet
if(State() < IClient::STATE_LOADING)
return;
if(Msg == NETMSG_SNAP)
{
NumParts = Unpacker.GetInt();
Part = Unpacker.GetInt();
}
if(Msg != NETMSG_SNAPEMPTY)
{
Crc = Unpacker.GetInt();
PartSize = Unpacker.GetInt();
}
pData = (const char *)Unpacker.GetRaw(PartSize);
if(Unpacker.Error())
return;
if(GameTick >= m_CurrentRecvTick[!g_Config.m_ClDummy])
{
if(GameTick != m_CurrentRecvTick[!g_Config.m_ClDummy])
{
m_SnapshotParts = 0;
m_CurrentRecvTick[!g_Config.m_ClDummy] = GameTick;
}
// TODO: clean this up abit
mem_copy((char*)m_aSnapshotIncommingData + Part*MAX_SNAPSHOT_PACKSIZE, pData, PartSize);
m_SnapshotParts |= 1<<Part;
if(m_SnapshotParts == (unsigned)((1<<NumParts)-1))
{
static CSnapshot Emptysnap;
CSnapshot *pDeltaShot = &Emptysnap;
int PurgeTick;
void *pDeltaData;
int DeltaSize;
unsigned char aTmpBuffer2[CSnapshot::MAX_SIZE];
unsigned char aTmpBuffer3[CSnapshot::MAX_SIZE];
CSnapshot *pTmpBuffer3 = (CSnapshot*)aTmpBuffer3; // Fix compiler warning for strict-aliasing
int SnapSize;
CompleteSize = (NumParts-1) * MAX_SNAPSHOT_PACKSIZE + PartSize;
// reset snapshoting
m_SnapshotParts = 0;
// find snapshot that we should use as delta
Emptysnap.Clear();
// find delta
if(DeltaTick >= 0)
{
int DeltashotSize = m_SnapshotStorage[!g_Config.m_ClDummy].Get(DeltaTick, 0, &pDeltaShot, 0);
if(DeltashotSize < 0)
{
// couldn't find the delta snapshots that the server used
// to compress this snapshot. force the server to resync
if(g_Config.m_Debug)
{
char aBuf[256];
str_format(aBuf, sizeof(aBuf), "error, couldn't find the delta snapshot");
m_pConsole->Print(IConsole::OUTPUT_LEVEL_DEBUG, "client", aBuf);
}
// ack snapshot
// TODO: combine this with the input message
m_AckGameTick[!g_Config.m_ClDummy] = -1;
return;
}
}
// decompress snapshot
pDeltaData = m_SnapshotDelta.EmptyDelta();
DeltaSize = sizeof(int)*3;
if(CompleteSize)
{
int IntSize = CVariableInt::Decompress(m_aSnapshotIncommingData, CompleteSize, aTmpBuffer2);
if(IntSize < 0) // failure during decompression, bail
return;
pDeltaData = aTmpBuffer2;
DeltaSize = IntSize;
}
// unpack delta
SnapSize = m_SnapshotDelta.UnpackDelta(pDeltaShot, pTmpBuffer3, pDeltaData, DeltaSize);
if(SnapSize < 0)
{
m_pConsole->Print(IConsole::OUTPUT_LEVEL_DEBUG, "client", "delta unpack failed!");
return;
}
if(Msg != NETMSG_SNAPEMPTY && pTmpBuffer3->Crc() != Crc)
{
if(g_Config.m_Debug)
{
char aBuf[256];
str_format(aBuf, sizeof(aBuf), "snapshot crc error #%d - tick=%d wantedcrc=%d gotcrc=%d compressed_size=%d delta_tick=%d",
m_SnapCrcErrors, GameTick, Crc, pTmpBuffer3->Crc(), CompleteSize, DeltaTick);
m_pConsole->Print(IConsole::OUTPUT_LEVEL_DEBUG, "client", aBuf);
}
m_SnapCrcErrors++;
if(m_SnapCrcErrors > 10)
{
// to many errors, send reset
m_AckGameTick[!g_Config.m_ClDummy] = -1;
SendInput();
m_SnapCrcErrors = 0;
}
return;
}
else
{
if(m_SnapCrcErrors)
m_SnapCrcErrors--;
}
// purge old snapshots
PurgeTick = DeltaTick;
if(m_aSnapshots[!g_Config.m_ClDummy][SNAP_PREV] && m_aSnapshots[!g_Config.m_ClDummy][SNAP_PREV]->m_Tick < PurgeTick)
PurgeTick = m_aSnapshots[!g_Config.m_ClDummy][SNAP_PREV]->m_Tick;
if(m_aSnapshots[!g_Config.m_ClDummy][SNAP_CURRENT] && m_aSnapshots[!g_Config.m_ClDummy][SNAP_CURRENT]->m_Tick < PurgeTick)
PurgeTick = m_aSnapshots[!g_Config.m_ClDummy][SNAP_CURRENT]->m_Tick;
m_SnapshotStorage[!g_Config.m_ClDummy].PurgeUntil(PurgeTick);
// add new
m_SnapshotStorage[!g_Config.m_ClDummy].Add(GameTick, time_get(), SnapSize, pTmpBuffer3, 1);
// add snapshot to demo
//if(m_DemoRecorder.IsRecording())
//{
// // write snapshot
// m_DemoRecorder.RecordSnapshot(GameTick, pTmpBuffer3, SnapSize);
//}
// apply snapshot, cycle pointers
m_RecivedSnapshots[!g_Config.m_ClDummy]++;
m_CurrentRecvTick[!g_Config.m_ClDummy] = GameTick;
// we got two snapshots until we see us self as connected
if(m_RecivedSnapshots[!g_Config.m_ClDummy] == 2)
{
// start at 200ms and work from there
m_PredictedTime[!g_Config.m_ClDummy].Init(GameTick*time_freq()/50);
m_PredictedTime[!g_Config.m_ClDummy].SetAdjustSpeed(1, 1000.0f);
m_GameTime[!g_Config.m_ClDummy].Init((GameTick-1)*time_freq()/50);
m_aSnapshots[!g_Config.m_ClDummy][SNAP_PREV] = m_SnapshotStorage[!g_Config.m_ClDummy].m_pFirst;
m_aSnapshots[!g_Config.m_ClDummy][SNAP_CURRENT] = m_SnapshotStorage[!g_Config.m_ClDummy].m_pLast;
m_LocalStartTime = time_get();
SetState(IClient::STATE_ONLINE);
//DemoRecorder_HandleAutoStart();
}
// adjust game time
if(m_RecivedSnapshots[!g_Config.m_ClDummy] > 2)
{
int64 Now = m_GameTime[!g_Config.m_ClDummy].Get(time_get());
int64 TickStart = GameTick*time_freq()/50;
int64 TimeLeft = (TickStart-Now)*1000 / time_freq();
m_GameTime[!g_Config.m_ClDummy].Update(&m_GametimeMarginGraph, (GameTick-1)*time_freq()/50, TimeLeft, 0);
}
// ack snapshot
m_AckGameTick[!g_Config.m_ClDummy] = GameTick;
}
}
}
} }
else else
{ {
@ -1832,12 +2016,12 @@ void CClient::OnDemoPlayerSnapshot(void *pData, int Size)
m_PrevGameTick[g_Config.m_ClDummy] = pInfo->m_PreviousTick; m_PrevGameTick[g_Config.m_ClDummy] = pInfo->m_PreviousTick;
// handle snapshots // handle snapshots
pTemp = m_aSnapshots[SNAP_PREV]; pTemp = m_aSnapshots[g_Config.m_ClDummy][SNAP_PREV];
m_aSnapshots[SNAP_PREV] = m_aSnapshots[SNAP_CURRENT]; m_aSnapshots[g_Config.m_ClDummy][SNAP_PREV] = m_aSnapshots[g_Config.m_ClDummy][SNAP_CURRENT];
m_aSnapshots[SNAP_CURRENT] = pTemp; m_aSnapshots[g_Config.m_ClDummy][SNAP_CURRENT] = pTemp;
mem_copy(m_aSnapshots[SNAP_CURRENT]->m_pSnap, pData, Size); mem_copy(m_aSnapshots[g_Config.m_ClDummy][SNAP_CURRENT]->m_pSnap, pData, Size);
mem_copy(m_aSnapshots[SNAP_CURRENT]->m_pAltSnap, pData, Size); mem_copy(m_aSnapshots[g_Config.m_ClDummy][SNAP_CURRENT]->m_pAltSnap, pData, Size);
GameClient()->OnNewSnapshot(); GameClient()->OnNewSnapshot();
} }
@ -1910,7 +2094,7 @@ void CClient::Update()
Disconnect(); Disconnect();
} }
} }
else if(State() == IClient::STATE_ONLINE && m_RecivedSnapshots >= 3) else if(State() == IClient::STATE_ONLINE && m_RecivedSnapshots[g_Config.m_ClDummy] >= 3)
{ {
// switch snapshot // switch snapshot
int Repredict = 0; int Repredict = 0;
@ -1920,22 +2104,22 @@ void CClient::Update()
while(1) while(1)
{ {
CSnapshotStorage::CHolder *pCur = m_aSnapshots[SNAP_CURRENT]; CSnapshotStorage::CHolder *pCur = m_aSnapshots[g_Config.m_ClDummy][SNAP_CURRENT];
int64 TickStart = (pCur->m_Tick)*time_freq()/50; int64 TickStart = (pCur->m_Tick)*time_freq()/50;
if(TickStart < Now) if(TickStart < Now)
{ {
CSnapshotStorage::CHolder *pNext = m_aSnapshots[SNAP_CURRENT]->m_pNext; CSnapshotStorage::CHolder *pNext = m_aSnapshots[g_Config.m_ClDummy][SNAP_CURRENT]->m_pNext;
if(pNext) if(pNext)
{ {
m_aSnapshots[SNAP_PREV] = m_aSnapshots[SNAP_CURRENT]; m_aSnapshots[g_Config.m_ClDummy][SNAP_PREV] = m_aSnapshots[g_Config.m_ClDummy][SNAP_CURRENT];
m_aSnapshots[SNAP_CURRENT] = pNext; m_aSnapshots[g_Config.m_ClDummy][SNAP_CURRENT] = pNext;
// set ticks // set ticks
m_CurGameTick[g_Config.m_ClDummy] = m_aSnapshots[SNAP_CURRENT]->m_Tick; m_CurGameTick[g_Config.m_ClDummy] = m_aSnapshots[g_Config.m_ClDummy][SNAP_CURRENT]->m_Tick;
m_PrevGameTick[g_Config.m_ClDummy] = m_aSnapshots[SNAP_PREV]->m_Tick; m_PrevGameTick[g_Config.m_ClDummy] = m_aSnapshots[g_Config.m_ClDummy][SNAP_PREV]->m_Tick;
if(m_aSnapshots[SNAP_CURRENT] && m_aSnapshots[SNAP_PREV]) if(m_aSnapshots[g_Config.m_ClDummy][SNAP_CURRENT] && m_aSnapshots[g_Config.m_ClDummy][SNAP_PREV])
{ {
GameClient()->OnNewSnapshot(); GameClient()->OnNewSnapshot();
Repredict = 1; Repredict = 1;
@ -1948,10 +2132,10 @@ void CClient::Update()
break; break;
} }
if(m_aSnapshots[SNAP_CURRENT] && m_aSnapshots[SNAP_PREV]) if(m_aSnapshots[g_Config.m_ClDummy][SNAP_CURRENT] && m_aSnapshots[g_Config.m_ClDummy][SNAP_PREV])
{ {
int64 CurtickStart = (m_aSnapshots[SNAP_CURRENT]->m_Tick)*time_freq()/50; int64 CurtickStart = (m_aSnapshots[g_Config.m_ClDummy][SNAP_CURRENT]->m_Tick)*time_freq()/50;
int64 PrevtickStart = (m_aSnapshots[SNAP_PREV]->m_Tick)*time_freq()/50; int64 PrevtickStart = (m_aSnapshots[g_Config.m_ClDummy][SNAP_PREV]->m_Tick)*time_freq()/50;
int PrevPredTick = (int)(PredNow*50/time_freq()); int PrevPredTick = (int)(PredNow*50/time_freq());
int NewPredTick = PrevPredTick+1; int NewPredTick = PrevPredTick+1;
@ -1962,10 +2146,10 @@ void CClient::Update()
PrevtickStart = PrevPredTick*time_freq()/50; PrevtickStart = PrevPredTick*time_freq()/50;
m_PredIntraTick[g_Config.m_ClDummy] = (PredNow - PrevtickStart) / (float)(CurtickStart-PrevtickStart); m_PredIntraTick[g_Config.m_ClDummy] = (PredNow - PrevtickStart) / (float)(CurtickStart-PrevtickStart);
if(NewPredTick < m_aSnapshots[SNAP_PREV]->m_Tick-SERVER_TICK_SPEED || NewPredTick > m_aSnapshots[SNAP_PREV]->m_Tick+SERVER_TICK_SPEED) if(NewPredTick < m_aSnapshots[g_Config.m_ClDummy][SNAP_PREV]->m_Tick-SERVER_TICK_SPEED || NewPredTick > m_aSnapshots[g_Config.m_ClDummy][SNAP_PREV]->m_Tick+SERVER_TICK_SPEED)
{ {
m_pConsole->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "client", "prediction time reset!"); m_pConsole->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "client", "prediction time reset!");
m_PredictedTime[g_Config.m_ClDummy].Init(m_aSnapshots[SNAP_CURRENT]->m_Tick*time_freq()/50); m_PredictedTime[g_Config.m_ClDummy].Init(m_aSnapshots[g_Config.m_ClDummy][SNAP_CURRENT]->m_Tick*time_freq()/50);
} }
if(NewPredTick > m_PredTick[g_Config.m_ClDummy]) if(NewPredTick > m_PredTick[g_Config.m_ClDummy])
@ -2525,18 +2709,18 @@ const char *CClient::DemoPlayer_Play(const char *pFilename, int StorageType)
// setup buffers // setup buffers
mem_zero(m_aDemorecSnapshotData, sizeof(m_aDemorecSnapshotData)); mem_zero(m_aDemorecSnapshotData, sizeof(m_aDemorecSnapshotData));
m_aSnapshots[SNAP_CURRENT] = &m_aDemorecSnapshotHolders[SNAP_CURRENT]; m_aSnapshots[g_Config.m_ClDummy][SNAP_CURRENT] = &m_aDemorecSnapshotHolders[SNAP_CURRENT];
m_aSnapshots[SNAP_PREV] = &m_aDemorecSnapshotHolders[SNAP_PREV]; m_aSnapshots[g_Config.m_ClDummy][SNAP_PREV] = &m_aDemorecSnapshotHolders[SNAP_PREV];
m_aSnapshots[SNAP_CURRENT]->m_pSnap = (CSnapshot *)m_aDemorecSnapshotData[SNAP_CURRENT][0]; m_aSnapshots[g_Config.m_ClDummy][SNAP_CURRENT]->m_pSnap = (CSnapshot *)m_aDemorecSnapshotData[SNAP_CURRENT][0];
m_aSnapshots[SNAP_CURRENT]->m_pAltSnap = (CSnapshot *)m_aDemorecSnapshotData[SNAP_CURRENT][1]; m_aSnapshots[g_Config.m_ClDummy][SNAP_CURRENT]->m_pAltSnap = (CSnapshot *)m_aDemorecSnapshotData[SNAP_CURRENT][1];
m_aSnapshots[SNAP_CURRENT]->m_SnapSize = 0; m_aSnapshots[g_Config.m_ClDummy][SNAP_CURRENT]->m_SnapSize = 0;
m_aSnapshots[SNAP_CURRENT]->m_Tick = -1; m_aSnapshots[g_Config.m_ClDummy][SNAP_CURRENT]->m_Tick = -1;
m_aSnapshots[SNAP_PREV]->m_pSnap = (CSnapshot *)m_aDemorecSnapshotData[SNAP_PREV][0]; m_aSnapshots[g_Config.m_ClDummy][SNAP_PREV]->m_pSnap = (CSnapshot *)m_aDemorecSnapshotData[SNAP_PREV][0];
m_aSnapshots[SNAP_PREV]->m_pAltSnap = (CSnapshot *)m_aDemorecSnapshotData[SNAP_PREV][1]; m_aSnapshots[g_Config.m_ClDummy][SNAP_PREV]->m_pAltSnap = (CSnapshot *)m_aDemorecSnapshotData[SNAP_PREV][1];
m_aSnapshots[SNAP_PREV]->m_SnapSize = 0; m_aSnapshots[g_Config.m_ClDummy][SNAP_PREV]->m_SnapSize = 0;
m_aSnapshots[SNAP_PREV]->m_Tick = -1; m_aSnapshots[g_Config.m_ClDummy][SNAP_PREV]->m_Tick = -1;
// enter demo playback state // enter demo playback state
SetState(IClient::STATE_DEMOPLAYBACK); SetState(IClient::STATE_DEMOPLAYBACK);

View file

@ -155,10 +155,10 @@ class CClient : public IClient, public CDemoPlayer::IListner
CGraph m_FpsGraph; CGraph m_FpsGraph;
// the game snapshots are modifiable by the game // the game snapshots are modifiable by the game
class CSnapshotStorage m_SnapshotStorage; class CSnapshotStorage m_SnapshotStorage[2];
CSnapshotStorage::CHolder *m_aSnapshots[NUM_SNAPSHOT_TYPES]; CSnapshotStorage::CHolder *m_aSnapshots[2][NUM_SNAPSHOT_TYPES];
int m_RecivedSnapshots; int m_RecivedSnapshots[2];
char m_aSnapshotIncommingData[CSnapshot::MAX_SIZE]; char m_aSnapshotIncommingData[CSnapshot::MAX_SIZE];
class CSnapshotStorage::CHolder m_aDemorecSnapshotHolders[NUM_SNAPSHOT_TYPES]; class CSnapshotStorage::CHolder m_aDemorecSnapshotHolders[NUM_SNAPSHOT_TYPES];