Reworked the race recorder

This commit is contained in:
Redix 2017-09-09 23:10:42 +02:00
parent 9e52957423
commit 5cc0d16029
7 changed files with 169 additions and 166 deletions

View file

@ -175,12 +175,13 @@ public:
//DDRace
virtual const char* GetCurrentMap() = 0;
virtual int GetCurrentMapCrc() = 0;
virtual const char* GetCurrentMapPath() = 0;
virtual const char* RaceRecordStart(const char *pFilename) = 0;
virtual void RaceRecordStop() = 0;
virtual bool RaceRecordIsRecording() = 0;
virtual const char *GetCurrentMap() = 0;
virtual const char *GetCurrentMapPath() = 0;
virtual void RaceRecord_GetName(char *pBuf, int Size, int Time = -1) = 0;
virtual void RaceRecord_Start() = 0;
virtual void RaceRecord_Stop() = 0;
virtual bool RaceRecord_IsRecording() = 0;
virtual void Ghost_GetPath(char *pBuf, int Size, int Time = -1) = 0;
virtual void GhostRecorder_Start() = 0;

View file

@ -3586,45 +3586,16 @@ int main(int argc, const char **argv) // ignore_convention
// DDRace
const char* CClient::GetCurrentMap()
const char *CClient::GetCurrentMap()
{
return m_aCurrentMap;
}
int CClient::GetCurrentMapCrc()
{
return m_pMap->Crc();
}
const char* CClient::GetCurrentMapPath()
const char *CClient::GetCurrentMapPath()
{
return m_aCurrentMapPath;
}
const char* CClient::RaceRecordStart(const char *pFilename)
{
char aFilename[128];
str_format(aFilename, sizeof(aFilename), "demos/%s_%s.demo", m_aCurrentMap, pFilename);
if(State() != STATE_ONLINE)
dbg_msg("demorec/record", "client is not online");
else
m_DemoRecorder[RECORDER_RACE].Start(Storage(), m_pConsole, aFilename, GameClient()->NetVersion(), m_aCurrentMap, m_pMap->Crc(), "client", m_pMap->MapSize(), 0, m_pMap->File());
return m_aCurrentMap;
}
void CClient::RaceRecordStop()
{
if(m_DemoRecorder[RECORDER_RACE].IsRecording())
m_DemoRecorder[RECORDER_RACE].Stop();
}
bool CClient::RaceRecordIsRecording()
{
return m_DemoRecorder[RECORDER_RACE].IsRecording();
}
void ClearFilename(char *pStr)
{
while(*pStr)
@ -3635,6 +3606,48 @@ void ClearFilename(char *pStr)
}
}
void CClient::RaceRecord_GetName(char *pBuf, int Size, int Time)
{
// check the player name
char aPlayerName[MAX_NAME_LENGTH];
str_copy(aPlayerName, g_Config.m_PlayerName, sizeof(aPlayerName));
ClearFilename(aPlayerName);
if(Time < 0)
str_format(pBuf, Size, "%s_tmp_%d", m_aCurrentMap, pid());
else if(g_Config.m_ClDemoName)
str_format(pBuf, Size, "%s_%d.%03d_%s", m_aCurrentMap, Time / 1000, Time % 1000, aPlayerName);
else
str_format(pBuf, Size, "%s_%d.%03d", m_aCurrentMap, Time / 1000, Time % 1000);
}
void CClient::RaceRecord_Start()
{
if(State() != IClient::STATE_ONLINE)
m_pConsole->Print(IConsole::OUTPUT_LEVEL_STANDARD, "demorec/record", "client is not online");
else
{
char aDemoName[128];
char aFilename[128];
RaceRecord_GetName(aDemoName, sizeof(aDemoName));
str_format(aFilename, sizeof(aFilename), "demos/%s.demo", aDemoName);
m_DemoRecorder[RECORDER_RACE].Start(Storage(), m_pConsole, aFilename, GameClient()->NetVersion(), m_aCurrentMap, m_pMap->Crc(), "client", m_pMap->MapSize(), 0, m_pMap->File());
}
}
void CClient::RaceRecord_Stop()
{
if(m_DemoRecorder[RECORDER_RACE].IsRecording())
m_DemoRecorder[RECORDER_RACE].Stop();
}
bool CClient::RaceRecord_IsRecording()
{
return m_DemoRecorder[RECORDER_RACE].IsRecording();
}
void CClient::Ghost_GetPath(char *pBuf, int Size, int Time)
{
// check the player name

View file

@ -383,12 +383,13 @@ public:
void GenerateTimeoutSeed();
void GenerateTimeoutCodes();
virtual const char* GetCurrentMap();
virtual int GetCurrentMapCrc();
virtual const char* GetCurrentMapPath();
virtual const char* RaceRecordStart(const char *pFilename);
virtual void RaceRecordStop();
virtual bool RaceRecordIsRecording();
const char *GetCurrentMap();
const char *GetCurrentMapPath();
void RaceRecord_GetName(char *pBuf, int Size, int Time = -1);
void RaceRecord_Start();
void RaceRecord_Stop();
bool RaceRecord_IsRecording();
void Ghost_GetPath(char *pBuf, int Size, int Time = -1);
void GhostRecorder_Start();

View file

@ -327,6 +327,8 @@ public:
void DemolistPopulate();
bool m_Dummy;
const char *GetCurrentDemoFolder() const { return m_aCurrentDemoFolder; }
// Ghost
struct CGhostItem
{

View file

@ -9,85 +9,68 @@
#include "race.h"
#include "race_demo.h"
CRaceDemo::CRaceDemo()
{
m_RaceState = RACE_NONE;
m_RecordStopTime = 0;
m_Time = 0;
m_DemoStartTick = 0;
}
void CRaceDemo::Stop()
{
if(Client()->RaceRecordIsRecording())
Client()->RaceRecordStop();
char aFilename[512];
str_format(aFilename, sizeof(aFilename), "demos/%s_tmp_%d.demo", m_pMap, pid());
Storage()->RemoveFile(aFilename, IStorage::TYPE_SAVE);
m_Time = 0;
m_RaceState = RACE_NONE;
m_RecordStopTime = 0;
m_DemoStartTick = 0;
}
CRaceDemo::CRaceDemo() : m_RaceState(RACE_NONE), m_RecordStartTick(-1), m_RecordStopTick(-1), m_Time(0) {}
void CRaceDemo::OnStateChange(int NewState, int OldState)
{
if(OldState == IClient::STATE_ONLINE)
Stop();
StopRecord();
}
void CRaceDemo::OnRender()
{
if(!g_Config.m_ClAutoRaceRecord || !m_pClient->m_Snap.m_pGameInfoObj || m_pClient->m_Snap.m_SpecInfo.m_Active || Client()->State() != IClient::STATE_ONLINE)
if(!g_Config.m_ClAutoRaceRecord || !m_pClient->m_Snap.m_pLocalCharacter)
return;
// only for race
CServerInfo ServerInfo;
Client()->GetServerInfo(&ServerInfo);
if(!IsRace(&ServerInfo) || !m_pClient->m_NewTick)
return;
// start the demo
if((m_RaceState != RACE_STARTED || !m_IsSolo) && m_DemoStartTick < Client()->GameTick() && CRaceHelper::IsStart(m_pClient, m_pClient->m_PredictedPrevChar.m_Pos, m_pClient->m_LocalCharacterPos))
if((m_RaceState == RACE_NONE || !m_IsSolo) && m_RecordStartTick + Client()->GameTickSpeed() < Client()->GameTick())
{
OnReset();
char aBuf[512];
str_format(aBuf, sizeof(aBuf), "tmp_%d", pid());
m_pMap = Client()->RaceRecordStart(aBuf);
m_DemoStartTick = Client()->GameTick() + Client()->GameTickSpeed();
m_RaceState = RACE_STARTED;
vec2 PrevPos = vec2(m_pClient->m_Snap.m_pLocalPrevCharacter->m_X, m_pClient->m_Snap.m_pLocalPrevCharacter->m_Y);
vec2 Pos = vec2(m_pClient->m_Snap.m_pLocalCharacter->m_X, m_pClient->m_Snap.m_pLocalCharacter->m_Y);
if(CRaceHelper::IsStart(m_pClient, m_pClient->m_PredictedPrevChar.m_Pos, m_pClient->m_LocalCharacterPos))
{
if(m_RaceState == RACE_STARTED)
OnReset();
Client()->RaceRecord_Start();
m_RecordStartTick = Client()->GameTick();
m_RaceState = RACE_STARTED;
}
}
// stop the demo
if(m_RaceState == RACE_FINISHED && m_RecordStopTime < Client()->GameTick() && m_Time > 0)
{
CheckDemo();
OnReset();
}
if(m_RaceState == RACE_FINISHED && m_RecordStopTick <= Client()->GameTick())
StopRecord(m_Time);
}
void CRaceDemo::OnReset()
{
if(Client()->State() == IClient::STATE_ONLINE)
Stop();
}
void CRaceDemo::OnShutdown()
{
Stop();
StopRecord();
}
void CRaceDemo::OnMessage(int MsgType, void *pRawMsg)
{
if(!g_Config.m_ClAutoRaceRecord || Client()->State() != IClient::STATE_ONLINE || m_pClient->m_Snap.m_SpecInfo.m_Active)
if(!g_Config.m_ClAutoRaceRecord || m_pClient->m_Snap.m_SpecInfo.m_Active)
return;
// only for race
CServerInfo ServerInfo;
Client()->GetServerInfo(&ServerInfo);
if(!IsRace(&ServerInfo))
return;
// check for messages from server
if(MsgType == NETMSGTYPE_SV_KILLMSG)
{
CNetMsg_Sv_KillMsg *pMsg = (CNetMsg_Sv_KillMsg *)pRawMsg;
if(pMsg->m_Victim == m_pClient->m_Snap.m_LocalClientID && m_RaceState == RACE_FINISHED)
{
// check for new record
CheckDemo();
OnReset();
}
if(pMsg->m_Victim == m_pClient->m_Snap.m_LocalClientID)
StopRecord(m_Time);
}
else if(MsgType == NETMSGTYPE_SV_CHAT)
{
@ -99,7 +82,7 @@ void CRaceDemo::OnMessage(int MsgType, void *pRawMsg)
if(Time > 0 && str_comp(aName, m_pClient->m_aClients[m_pClient->m_Snap.m_LocalClientID].m_aName) == 0)
{
m_RaceState = RACE_FINISHED;
m_RecordStopTime = Client()->GameTick() + Client()->GameTickSpeed();
m_RecordStopTick = Client()->GameTick() + Client()->GameTickSpeed();
m_Time = Time;
}
}
@ -111,78 +94,87 @@ void CRaceDemo::OnMapLoad()
m_IsSolo = true;
}
void CRaceDemo::CheckDemo()
void CRaceDemo::StopRecord(int Time)
{
// stop the demo recording
Client()->RaceRecordStop();
if(Client()->RaceRecord_IsRecording())
Client()->RaceRecord_Stop();
char aDemoName[128];
char aTmpFilename[512];
Client()->RaceRecord_GetName(aDemoName, sizeof(aDemoName));
str_format(aTmpFilename, sizeof(aTmpFilename), "demos/%s.demo", aDemoName);
if(Time > 0 && CheckDemo(Time))
{
// save file
char aNewFilename[512];
Client()->RaceRecord_GetName(aDemoName, sizeof(aDemoName), m_Time);
str_format(aNewFilename, sizeof(aNewFilename), "demos/%s.demo", aDemoName);
Storage()->RenameFile(aTmpFilename, aNewFilename, IStorage::TYPE_SAVE);
}
else // no new record
Storage()->RemoveFile(aTmpFilename, IStorage::TYPE_SAVE);
m_Time = 0;
m_RaceState = RACE_NONE;
m_RecordStartTick = -1;
m_RecordStopTick = -1;
}
bool CRaceDemo::CheckDemo(int Time) const
{
if(str_comp(m_pClient->m_pMenus->GetCurrentDemoFolder(), "demos") != 0)
return true;
char aTmpDemoName[128];
str_format(aTmpDemoName, sizeof(aTmpDemoName), "%s_tmp_%d", m_pMap, pid());
Client()->RaceRecord_GetName(aTmpDemoName, sizeof(aTmpDemoName));
// loop through demo files
m_pClient->m_pMenus->DemolistPopulate();
for(int i = 0; i < m_pClient->m_pMenus->m_lDemos.size(); i++)
{
const char *pDemo = m_pClient->m_pMenus->m_lDemos[i].m_aName;
if(str_comp(pDemo, aTmpDemoName) == 0)
// skip temp file
const char *pDemoName = m_pClient->m_pMenus->m_lDemos[i].m_aName;
if(str_comp(pDemoName, aTmpDemoName) == 0)
continue;
int MapLen = str_length(m_pMap);
if(str_comp_num(pDemo, m_pMap, MapLen) == 0 && pDemo[MapLen] == '_')
{
// set cursor
pDemo += MapLen + 1;
int Time = CRaceHelper::TimeFromSecondsStr(pDemo);
if(Time > 0 && m_Time < Time)
{
// save new record
SaveDemo(m_pMap);
int MapLen = str_length(Client()->GetCurrentMap());
if(str_comp_num(pDemoName, Client()->GetCurrentMap(), MapLen) != 0 || pDemoName[MapLen] != '_')
continue;
// delete old demo
char aFilename[512];
str_format(aFilename, sizeof(aFilename), "demos/%s.demo", m_pClient->m_pMenus->m_lDemos[i].m_aName);
Storage()->RemoveFile(aFilename, IStorage::TYPE_SAVE);
// set cursor
pDemoName += MapLen + 1;
if(g_Config.m_ClDemoName)
{
char aPlayerName[MAX_NAME_LENGTH];
str_copy(aPlayerName, g_Config.m_PlayerName, sizeof(aPlayerName));
char *pStr = aPlayerName;
while(*pStr)
{
if(*pStr == '\\' || *pStr == '/' || *pStr == '|' || *pStr == ':' || *pStr == '*' || *pStr == '?' || *pStr == '<' || *pStr == '>' || *pStr == '"')
*pStr = '%';
pStr++;
}
m_Time = 0;
return;
if(!str_find(pDemoName, aPlayerName))
continue;
}
}
// save demo if there is none
SaveDemo(m_pMap);
m_Time = 0;
}
void CRaceDemo::SaveDemo(const char* pDemo)
{
char aNewFilename[512];
char aOldFilename[512];
if(g_Config.m_ClDemoName)
{
char aPlayerName[MAX_NAME_LENGTH];
str_copy(aPlayerName, m_pClient->m_aClients[m_pClient->m_Snap.m_LocalClientID].m_aName, sizeof(aPlayerName));
// check the player name
for(int i = 0; i < MAX_NAME_LENGTH; i++)
int DemoTime = CRaceHelper::TimeFromSecondsStr(pDemoName);
if(DemoTime > 0)
{
if(!aPlayerName[i])
break;
if(Time >= DemoTime) // found a better demo
return false;
if(aPlayerName[i] == '\\' || aPlayerName[i] == '/' || aPlayerName[i] == '|' || aPlayerName[i] == ':' || aPlayerName[i] == '*' || aPlayerName[i] == '?' || aPlayerName[i] == '<' || aPlayerName[i] == '>' || aPlayerName[i] == '"')
aPlayerName[i] = '%';
str_format(aNewFilename, sizeof(aNewFilename), "demos/%s_%d.%03d_%s.demo", pDemo, m_Time / 1000, m_Time % 1000, aPlayerName);
// delete old demo
char aFilename[512];
str_format(aFilename, sizeof(aFilename), "demos/%s", m_pClient->m_pMenus->m_lDemos[i].m_aFilename);
Storage()->RemoveFile(aFilename, IStorage::TYPE_SAVE);
}
}
else
str_format(aNewFilename, sizeof(aNewFilename), "demos/%s_%d.%03d.demo", pDemo, m_Time / 1000, m_Time % 1000);
str_format(aOldFilename, sizeof(aOldFilename), "demos/%s_tmp_%d.demo", m_pMap, pid());
Storage()->RenameFile(aOldFilename, aNewFilename, IStorage::TYPE_SAVE);
dbg_msg("racedemo", "saved better demo");
return true;
}

View file

@ -3,23 +3,10 @@
#ifndef GAME_CLIENT_COMPONENTS_RACE_DEMO_H
#define GAME_CLIENT_COMPONENTS_RACE_DEMO_H
#include <game/client/gameclient.h>
#include <game/client/component.h>
class CRaceDemo : public CComponent
{
int m_RecordStopTime;
int m_DemoStartTick;
int m_Time;
const char *m_pMap;
void Stop();
public:
bool m_IsSolo;
int m_RaceState;
enum
{
RACE_NONE = 0,
@ -27,16 +14,23 @@ public:
RACE_FINISHED,
};
int m_RaceState;
int m_RecordStartTick;
int m_RecordStopTick;
int m_Time;
void StopRecord(int Time = -1);
bool CheckDemo(int Time) const;
public:
bool m_IsSolo;
CRaceDemo();
virtual void OnReset();
virtual void OnStateChange(int NewState, int OldState);
virtual void OnRender();
virtual void OnShutdown();
virtual void OnMessage(int MsgType, void *pRawMsg);
virtual void OnMapLoad();
void CheckDemo();
void SaveDemo(const char* pDemo);
};
#endif

View file

@ -874,7 +874,7 @@ void CGameClient::OnStateChange(int NewState, int OldState)
void CGameClient::OnShutdown()
{
m_pRaceDemo->OnShutdown();
m_pRaceDemo->OnReset();
m_pGhost->OnReset();
}