Merge pull request #7837 from Robyt3/Demo-Recorder-Improvements

Refactor demo recorder usage
This commit is contained in:
Dennis Felsing 2024-01-21 22:39:46 +00:00 committed by GitHub
commit fca6e0abe3
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 161 additions and 151 deletions

View file

@ -165,7 +165,7 @@ public:
#endif
virtual void DemoRecorder_Start(const char *pFilename, bool WithTimestamp, int Recorder, bool Verbose = false) = 0;
virtual void DemoRecorder_HandleAutoStart() = 0;
virtual void DemoRecorder_Stop(int Recorder, bool RemoveFile = false) = 0;
virtual void DemoRecorder_UpdateReplayRecorder() = 0;
virtual class IDemoRecorder *DemoRecorder(int Recorder) = 0;
virtual void AutoScreenshot_Start() = 0;
virtual void AutoStatScreenshot_Start() = 0;

View file

@ -532,11 +532,13 @@ void CClient::DisconnectWithReason(const char *pReason)
m_pConsole->Print(IConsole::OUTPUT_LEVEL_STANDARD, "client", aBuf, gs_ClientNetworkPrintColor);
// stop demo playback and recorder
// make sure to remove replay tmp demo
m_DemoPlayer.Stop();
for(int i = 0; i < RECORDER_MAX; i++)
DemoRecorder_Stop(i);
for(int Recorder = 0; Recorder < RECORDER_MAX; Recorder++)
{
DemoRecorder(Recorder)->Stop(Recorder == RECORDER_REPLAYS ? IDemoRecorder::EStopMode::REMOVE_FILE : IDemoRecorder::EStopMode::KEEP_FILE);
}
//
m_aRconAuthed[0] = 0;
mem_zero(m_aRconUsername, sizeof(m_aRconUsername));
mem_zero(m_aRconPassword, sizeof(m_aRconPassword));
@ -581,14 +583,9 @@ void CClient::DisconnectWithReason(const char *pReason)
void CClient::Disconnect()
{
m_ButtonRender = false;
if(m_State != IClient::STATE_OFFLINE)
DisconnectWithReason(0);
// make sure to remove replay tmp demo
if(g_Config.m_ClReplays)
{
DemoRecorder_Stop(RECORDER_REPLAYS, true);
DisconnectWithReason(nullptr);
}
}
@ -946,8 +943,10 @@ const char *CClient::LoadMap(const char *pName, const char *pFilename, SHA256_DI
}
// stop demo recording if we loaded a new map
for(int i = 0; i < RECORDER_MAX; i++)
DemoRecorder_Stop(i, i == RECORDER_REPLAYS);
for(int Recorder = 0; Recorder < RECORDER_MAX; Recorder++)
{
DemoRecorder(Recorder)->Stop(Recorder == RECORDER_REPLAYS ? IDemoRecorder::EStopMode::REMOVE_FILE : IDemoRecorder::EStopMode::KEEP_FILE);
}
char aBuf[256];
str_format(aBuf, sizeof(aBuf), "loaded map '%s'", pFilename);
@ -2352,22 +2351,20 @@ void CClient::Update()
{
if(State() == IClient::STATE_DEMOPLAYBACK)
{
#if defined(CONF_VIDEORECORDER)
if(m_DemoPlayer.IsPlaying() && IVideo::Current())
{
IVideo::Current()->NextVideoFrame();
IVideo::Current()->NextAudioFrameTimeline([this](short *pFinalOut, unsigned Frames) {
Sound()->Mix(pFinalOut, Frames);
});
}
else if(m_ButtonRender)
Disconnect();
#endif
m_DemoPlayer.Update();
if(m_DemoPlayer.IsPlaying())
{
#if defined(CONF_VIDEORECORDER)
if(IVideo::Current())
{
IVideo::Current()->NextVideoFrame();
IVideo::Current()->NextAudioFrameTimeline([this](short *pFinalOut, unsigned Frames) {
Sound()->Mix(pFinalOut, Frames);
});
}
#endif
m_DemoPlayer.Update();
// update timers
const CDemoPlayer::CPlaybackInfo *pInfo = m_DemoPlayer.Info();
m_aCurGameTick[g_Config.m_ClDummy] = pInfo->m_Info.m_CurrentTick;
@ -2377,7 +2374,8 @@ void CClient::Update()
}
else
{
// disconnect on error
// Disconnect when demo playback stopped, either due to playback error
// or because the end of the demo was reached when rendering it.
DisconnectWithReason(m_DemoPlayer.ErrorMessage());
if(m_DemoPlayer.ErrorMessage()[0] != '\0')
{
@ -3472,26 +3470,32 @@ void CClient::SaveReplay(const int Length, const char *pFilename)
}
if(!DemoRecorder(RECORDER_REPLAYS)->IsRecording())
{
m_pConsole->Print(IConsole::OUTPUT_LEVEL_STANDARD, "replay", "ERROR: demorecorder isn't recording. Try to rejoin to fix that.");
}
else if(DemoRecorder(RECORDER_REPLAYS)->Length() < 1)
{
m_pConsole->Print(IConsole::OUTPUT_LEVEL_STANDARD, "replay", "ERROR: demorecorder isn't recording for at least 1 second.");
}
else
{
// First we stop the recorder to slice correctly the demo after
DemoRecorder_Stop(RECORDER_REPLAYS);
char aDate[64];
str_timestamp(aDate, sizeof(aDate));
DemoRecorder(RECORDER_REPLAYS)->Stop(IDemoRecorder::EStopMode::KEEP_FILE);
char aFilename[IO_MAX_PATH_LENGTH];
if(str_comp(pFilename, "") == 0)
str_format(aFilename, sizeof(aFilename), "demos/replays/%s_%s (replay).demo", m_aCurrentMap, aDate);
if(pFilename[0] == '\0')
{
char aTimestamp[20];
str_timestamp(aTimestamp, sizeof(aTimestamp));
str_format(aFilename, sizeof(aFilename), "demos/replays/%s_%s_(replay).demo", m_aCurrentMap, aTimestamp);
}
else
{
str_format(aFilename, sizeof(aFilename), "demos/replays/%s.demo", pFilename);
char *pSrc = m_aDemoRecorder[RECORDER_REPLAYS].GetCurrentFilename();
}
// Slice the demo to get only the last cl_replay_length seconds
const char *pSrc = m_aDemoRecorder[RECORDER_REPLAYS].CurrentFilename();
const int EndTick = GameTick(g_Config.m_ClDummy);
const int StartTick = EndTick - Length * GameTickSpeed();
@ -3503,7 +3507,7 @@ void CClient::SaveReplay(const int Length, const char *pFilename)
m_EditJobs.push_back(pDemoEditTask);
// And we restart the recorder
DemoRecorder_StartReplayRecorder();
DemoRecorder_UpdateReplayRecorder();
}
}
@ -3586,7 +3590,6 @@ const char *CClient::DemoPlayer_Render(const char *pFilename, int StorageType, c
const char *pError = DemoPlayer_Play(pFilename, StorageType);
if(pError)
return pError;
m_ButtonRender = true;
this->CClient::StartVideo(NULL, this, pVideoName);
m_DemoPlayer.Play();
@ -3632,19 +3635,23 @@ void CClient::DemoRecorder_Start(const char *pFilename, bool WithTimestamp, int
if(State() != IClient::STATE_ONLINE)
{
if(Verbose)
{
m_pConsole->Print(IConsole::OUTPUT_LEVEL_STANDARD, "demorec/record", "client is not online");
}
}
else
{
char aFilename[IO_MAX_PATH_LENGTH];
if(WithTimestamp)
{
char aDate[20];
str_timestamp(aDate, sizeof(aDate));
str_format(aFilename, sizeof(aFilename), "demos/%s_%s.demo", pFilename, aDate);
char aTimestamp[20];
str_timestamp(aTimestamp, sizeof(aTimestamp));
str_format(aFilename, sizeof(aFilename), "demos/%s_%s.demo", pFilename, aTimestamp);
}
else
{
str_format(aFilename, sizeof(aFilename), "demos/%s.demo", pFilename);
}
m_aDemoRecorder[Recorder].Start(Storage(), m_pConsole, aFilename, GameClient()->NetVersion(), m_aCurrentMap, m_pMap->Sha256(), m_pMap->Crc(), "client", m_pMap->MapSize(), 0, m_pMap->File());
}
@ -3654,10 +3661,12 @@ void CClient::DemoRecorder_HandleAutoStart()
{
if(g_Config.m_ClAutoDemoRecord)
{
DemoRecorder_Stop(RECORDER_AUTO);
char aBuf[512];
str_format(aBuf, sizeof(aBuf), "auto/%s", m_aCurrentMap);
DemoRecorder_Start(aBuf, true, RECORDER_AUTO);
DemoRecorder(RECORDER_AUTO)->Stop(IDemoRecorder::EStopMode::KEEP_FILE);
char aFilename[IO_MAX_PATH_LENGTH];
str_format(aFilename, sizeof(aFilename), "auto/%s", m_aCurrentMap);
DemoRecorder_Start(aFilename, true, RECORDER_AUTO);
if(g_Config.m_ClAutoDemoMax)
{
// clean up auto recorded demos
@ -3665,34 +3674,22 @@ void CClient::DemoRecorder_HandleAutoStart()
AutoDemos.Init(Storage(), "demos/auto", "" /* empty for wild card */, ".demo", g_Config.m_ClAutoDemoMax);
}
}
if(!DemoRecorder(RECORDER_REPLAYS)->IsRecording())
{
DemoRecorder_StartReplayRecorder();
}
DemoRecorder_UpdateReplayRecorder();
}
void CClient::DemoRecorder_StartReplayRecorder()
void CClient::DemoRecorder_UpdateReplayRecorder()
{
if(g_Config.m_ClReplays)
if(!g_Config.m_ClReplays && DemoRecorder(RECORDER_REPLAYS)->IsRecording())
{
DemoRecorder_Stop(RECORDER_REPLAYS);
char aBuf[512];
str_format(aBuf, sizeof(aBuf), "replays/replay_tmp-%s", m_aCurrentMap);
DemoRecorder_Start(aBuf, true, RECORDER_REPLAYS);
DemoRecorder(RECORDER_REPLAYS)->Stop(IDemoRecorder::EStopMode::REMOVE_FILE);
}
}
void CClient::DemoRecorder_Stop(int Recorder, bool RemoveFile)
{
m_aDemoRecorder[Recorder].Stop();
if(RemoveFile)
if(g_Config.m_ClReplays && !DemoRecorder(RECORDER_REPLAYS)->IsRecording())
{
const char *pFilename = m_aDemoRecorder[Recorder].GetCurrentFilename();
if(pFilename[0] != '\0')
{
Storage()->RemoveFile(pFilename, IStorage::TYPE_SAVE);
m_aDemoRecorder[Recorder].ClearCurrentFilename();
}
char aFilename[IO_MAX_PATH_LENGTH];
str_format(aFilename, sizeof(aFilename), "replays/replay_tmp_%s", m_aCurrentMap);
DemoRecorder_Start(aFilename, true, RECORDER_REPLAYS);
}
}
@ -3725,7 +3722,7 @@ void CClient::Con_Record(IConsole::IResult *pResult, void *pUserData)
void CClient::Con_StopRecord(IConsole::IResult *pResult, void *pUserData)
{
CClient *pSelf = (CClient *)pUserData;
pSelf->DemoRecorder_Stop(RECORDER_MANUAL);
pSelf->DemoRecorder(RECORDER_MANUAL)->Stop(IDemoRecorder::EStopMode::KEEP_FILE);
}
void CClient::Con_AddDemoMarker(IConsole::IResult *pResult, void *pUserData)
@ -4019,17 +4016,7 @@ void CClient::ConchainReplays(IConsole::IResult *pResult, void *pUserData, ICons
pfnCallback(pResult, pCallbackUserData);
if(pResult->NumArguments())
{
int Status = pResult->GetInteger(0);
if(Status == 0)
{
// stop recording and remove the tmp demo file
pSelf->DemoRecorder_Stop(RECORDER_REPLAYS, true);
}
else
{
// start recording
pSelf->DemoRecorder_HandleAutoStart();
}
pSelf->DemoRecorder_UpdateReplayRecorder();
}
}
@ -4562,7 +4549,9 @@ void CClient::RaceRecord_Start(const char *pFilename)
void CClient::RaceRecord_Stop()
{
if(m_aDemoRecorder[RECORDER_RACE].IsRecording())
m_aDemoRecorder[RECORDER_RACE].Stop();
{
m_aDemoRecorder[RECORDER_RACE].Stop(IDemoRecorder::EStopMode::KEEP_FILE);
}
}
bool CClient::RaceRecord_IsRecording()

View file

@ -119,7 +119,6 @@ class CClient : public IClient, public CDemoPlayer::IListener
int m_UseTempRconCommands = 0;
char m_aPassword[sizeof(g_Config.m_Password)] = "";
bool m_SendPassword = false;
bool m_ButtonRender = false;
// version-checking
char m_aVersionStr[10] = "0";
@ -437,8 +436,7 @@ public:
const char *DemoPlayer_Play(const char *pFilename, int StorageType) override;
void DemoRecorder_Start(const char *pFilename, bool WithTimestamp, int Recorder, bool Verbose = false) override;
void DemoRecorder_HandleAutoStart() override;
void DemoRecorder_StartReplayRecorder();
void DemoRecorder_Stop(int Recorder, bool RemoveFile = false) override;
void DemoRecorder_UpdateReplayRecorder() override;
void DemoRecorder_AddDemoMarker(int Recorder);
IDemoRecorder *DemoRecorder(int Recorder) override;

View file

@ -101,11 +101,17 @@ class IDemoRecorder : public IInterface
{
MACRO_INTERFACE("demorecorder")
public:
enum class EStopMode
{
KEEP_FILE,
REMOVE_FILE,
};
virtual ~IDemoRecorder() {}
virtual bool IsRecording() const = 0;
virtual int Stop() = 0;
virtual int Stop(IDemoRecorder::EStopMode Mode, const char *pTargetFilename = "") = 0;
virtual int Length() const = 0;
virtual char *GetCurrentFilename() = 0;
virtual const char *CurrentFilename() const = 0;
};
class IDemoEditor : public IInterface

View file

@ -3412,12 +3412,14 @@ void CServer::DemoRecorder_HandleAutoStart()
{
if(Config()->m_SvAutoDemoRecord)
{
m_aDemoRecorder[RECORDER_AUTO].Stop();
m_aDemoRecorder[RECORDER_AUTO].Stop(IDemoRecorder::EStopMode::KEEP_FILE);
char aTimestamp[20];
str_timestamp(aTimestamp, sizeof(aTimestamp));
char aFilename[IO_MAX_PATH_LENGTH];
char aDate[20];
str_timestamp(aDate, sizeof(aDate));
str_format(aFilename, sizeof(aFilename), "demos/auto/server/%s_%s.demo", m_aCurrentMap, aDate);
str_format(aFilename, sizeof(aFilename), "demos/auto/server/%s_%s.demo", m_aCurrentMap, aTimestamp);
m_aDemoRecorder[RECORDER_AUTO].Start(Storage(), m_pConsole, aFilename, GameServer()->NetVersion(), m_aCurrentMap, m_aCurrentMapSha256[MAP_TYPE_SIX], m_aCurrentMapCrc[MAP_TYPE_SIX], "server", m_aCurrentMapSize[MAP_TYPE_SIX], m_apCurrentMapData[MAP_TYPE_SIX]);
if(Config()->m_SvAutoDemoMax)
{
// clean up auto recorded demos
@ -3431,14 +3433,9 @@ void CServer::SaveDemo(int ClientID, float Time)
{
if(IsRecording(ClientID))
{
m_aDemoRecorder[ClientID].Stop();
// rename the demo
char aOldFilename[IO_MAX_PATH_LENGTH];
char aNewFilename[IO_MAX_PATH_LENGTH];
str_format(aOldFilename, sizeof(aOldFilename), "demos/%s_%d_%d_tmp.demo", m_aCurrentMap, m_NetServer.Address().port, ClientID);
str_format(aNewFilename, sizeof(aNewFilename), "demos/%s_%s_%05.2f.demo", m_aCurrentMap, m_aClients[ClientID].m_aName, Time);
Storage()->RenameFile(aOldFilename, aNewFilename, IStorage::TYPE_SAVE);
m_aDemoRecorder[ClientID].Stop(IDemoRecorder::EStopMode::KEEP_FILE, aNewFilename);
}
}
@ -3456,11 +3453,7 @@ void CServer::StopRecord(int ClientID)
{
if(IsRecording(ClientID))
{
m_aDemoRecorder[ClientID].Stop();
char aFilename[IO_MAX_PATH_LENGTH];
str_format(aFilename, sizeof(aFilename), "demos/%s_%d_%d_tmp.demo", m_aCurrentMap, m_NetServer.Address().port, ClientID);
Storage()->RemoveFile(aFilename, IStorage::TYPE_SAVE);
m_aDemoRecorder[ClientID].Stop(IDemoRecorder::EStopMode::REMOVE_FILE);
}
}
@ -3476,22 +3469,13 @@ void CServer::StopDemos()
if(!m_aDemoRecorder[i].IsRecording())
continue;
m_aDemoRecorder[i].Stop();
// remove tmp demos
if(i < MAX_CLIENTS)
{
char aPath[256];
str_format(aPath, sizeof(aPath), "demos/%s_%d_%d_tmp.demo", m_aCurrentMap, m_NetServer.Address().port, i);
Storage()->RemoveFile(aPath, IStorage::TYPE_SAVE);
}
m_aDemoRecorder[i].Stop(i < MAX_CLIENTS ? IDemoRecorder::EStopMode::REMOVE_FILE : IDemoRecorder::EStopMode::KEEP_FILE);
}
}
void CServer::ConRecord(IConsole::IResult *pResult, void *pUser)
{
CServer *pServer = (CServer *)pUser;
char aFilename[IO_MAX_PATH_LENGTH];
if(pServer->IsRecording(RECORDER_MANUAL))
{
@ -3499,20 +3483,23 @@ void CServer::ConRecord(IConsole::IResult *pResult, void *pUser)
return;
}
char aFilename[IO_MAX_PATH_LENGTH];
if(pResult->NumArguments())
{
str_format(aFilename, sizeof(aFilename), "demos/%s.demo", pResult->GetString(0));
}
else
{
char aDate[20];
str_timestamp(aDate, sizeof(aDate));
str_format(aFilename, sizeof(aFilename), "demos/demo_%s.demo", aDate);
char aTimestamp[20];
str_timestamp(aTimestamp, sizeof(aTimestamp));
str_format(aFilename, sizeof(aFilename), "demos/demo_%s.demo", aTimestamp);
}
pServer->m_aDemoRecorder[RECORDER_MANUAL].Start(pServer->Storage(), pServer->Console(), aFilename, pServer->GameServer()->NetVersion(), pServer->m_aCurrentMap, pServer->m_aCurrentMapSha256[MAP_TYPE_SIX], pServer->m_aCurrentMapCrc[MAP_TYPE_SIX], "server", pServer->m_aCurrentMapSize[MAP_TYPE_SIX], pServer->m_apCurrentMapData[MAP_TYPE_SIX]);
}
void CServer::ConStopRecord(IConsole::IResult *pResult, void *pUser)
{
((CServer *)pUser)->m_aDemoRecorder[RECORDER_MANUAL].Stop();
((CServer *)pUser)->m_aDemoRecorder[RECORDER_MANUAL].Stop(IDemoRecorder::EStopMode::KEEP_FILE);
}
void CServer::ConMapReload(IConsole::IResult *pResult, void *pUser)

View file

@ -62,18 +62,15 @@ int CDemoRecorder::Start(class IStorage *pStorage, class IConsole *pConsole, con
{
dbg_assert(m_File == 0, "Demo recorder already recording");
m_pfnFilter = pfnFilter;
m_pUser = pUser;
m_pMapData = pMapData;
m_pConsole = pConsole;
m_pStorage = pStorage;
IOHANDLE DemoFile = pStorage->OpenFile(pFilename, IOFLAG_WRITE, IStorage::TYPE_SAVE);
if(!DemoFile)
{
if(m_pConsole)
{
char aBuf[256];
char aBuf[64 + IO_MAX_PATH_LENGTH];
str_format(aBuf, sizeof(aBuf), "Unable to open '%s' for recording", pFilename);
m_pConsole->Print(IConsole::OUTPUT_LEVEL_STANDARD, "demo_recorder", aBuf, gs_DemoPrintColor);
}
@ -186,6 +183,10 @@ int CDemoRecorder::Start(class IStorage *pStorage, class IConsole *pConsole, con
str_format(aBuf, sizeof(aBuf), "Recording to '%s'", pFilename);
m_pConsole->Print(IConsole::OUTPUT_LEVEL_STANDARD, "demo_recorder", aBuf, gs_DemoPrintColor);
}
m_pfnFilter = pfnFilter;
m_pUser = pUser;
m_File = DemoFile;
str_copy(m_aCurrentFilename, pFilename);
@ -337,33 +338,68 @@ void CDemoRecorder::RecordMessage(const void *pData, int Size)
Write(CHUNKTYPE_MESSAGE, pData, Size);
}
int CDemoRecorder::Stop()
int CDemoRecorder::Stop(IDemoRecorder::EStopMode Mode, const char *pTargetFilename)
{
if(!m_File)
return -1;
// add the demo length to the header
io_seek(m_File, gs_LengthOffset, IOSEEK_START);
unsigned char aLength[sizeof(int32_t)];
uint_to_bytes_be(aLength, Length());
io_write(m_File, aLength, sizeof(aLength));
// add the timeline markers to the header
io_seek(m_File, gs_NumMarkersOffset, IOSEEK_START);
unsigned char aNumMarkers[sizeof(int32_t)];
uint_to_bytes_be(aNumMarkers, m_NumTimelineMarkers);
io_write(m_File, aNumMarkers, sizeof(aNumMarkers));
for(int i = 0; i < m_NumTimelineMarkers; i++)
if(Mode == IDemoRecorder::EStopMode::KEEP_FILE)
{
unsigned char aMarker[sizeof(int32_t)];
uint_to_bytes_be(aMarker, m_aTimelineMarkers[i]);
io_write(m_File, aMarker, sizeof(aMarker));
// add the demo length to the header
io_seek(m_File, gs_LengthOffset, IOSEEK_START);
unsigned char aLength[sizeof(int32_t)];
uint_to_bytes_be(aLength, Length());
io_write(m_File, aLength, sizeof(aLength));
// add the timeline markers to the header
io_seek(m_File, gs_NumMarkersOffset, IOSEEK_START);
unsigned char aNumMarkers[sizeof(int32_t)];
uint_to_bytes_be(aNumMarkers, m_NumTimelineMarkers);
io_write(m_File, aNumMarkers, sizeof(aNumMarkers));
for(int i = 0; i < m_NumTimelineMarkers; i++)
{
unsigned char aMarker[sizeof(int32_t)];
uint_to_bytes_be(aMarker, m_aTimelineMarkers[i]);
io_write(m_File, aMarker, sizeof(aMarker));
}
}
io_close(m_File);
m_File = 0;
if(Mode == IDemoRecorder::EStopMode::REMOVE_FILE)
{
if(!m_pStorage->RemoveFile(m_aCurrentFilename, IStorage::TYPE_SAVE))
{
if(m_pConsole)
{
char aBuf[64 + IO_MAX_PATH_LENGTH];
str_format(aBuf, sizeof(aBuf), "Could not remove demo file '%s'.", m_aCurrentFilename);
m_pConsole->Print(IConsole::OUTPUT_LEVEL_STANDARD, "demo_recorder", aBuf, gs_DemoPrintColor);
}
return -1;
}
}
else if(pTargetFilename[0] != '\0')
{
if(!m_pStorage->RenameFile(m_aCurrentFilename, pTargetFilename, IStorage::TYPE_SAVE))
{
if(m_pConsole)
{
char aBuf[64 + 2 * IO_MAX_PATH_LENGTH];
str_format(aBuf, sizeof(aBuf), "Could not move demo file '%s' to '%s'.", m_aCurrentFilename, pTargetFilename);
m_pConsole->Print(IConsole::OUTPUT_LEVEL_STANDARD, "demo_recorder", aBuf, gs_DemoPrintColor);
}
return -1;
}
}
if(m_pConsole)
m_pConsole->Print(IConsole::OUTPUT_LEVEL_STANDARD, "demo_recorder", "Stopped recording", gs_DemoPrintColor);
{
char aBuf[64 + IO_MAX_PATH_LENGTH];
str_format(aBuf, sizeof(aBuf), "Stopped recording to '%s'", m_aCurrentFilename);
m_pConsole->Print(IConsole::OUTPUT_LEVEL_STANDARD, "demo_recorder", aBuf, gs_DemoPrintColor);
}
return 0;
}
@ -1229,5 +1265,5 @@ void CDemoEditor::Slice(const char *pDemo, const char *pDst, int StartTick, int
}
DemoPlayer.Stop();
DemoRecorder.Stop();
DemoRecorder.Stop(IDemoRecorder::EStopMode::KEEP_FILE);
}

View file

@ -18,17 +18,21 @@ typedef std::function<void()> TUpdateIntraTimesFunc;
class CDemoRecorder : public IDemoRecorder
{
class IConsole *m_pConsole;
class IStorage *m_pStorage;
IOHANDLE m_File;
char m_aCurrentFilename[IO_MAX_PATH_LENGTH];
int m_LastTickMarker;
int m_LastKeyFrame;
int m_FirstTick;
unsigned char m_aLastSnapshotData[CSnapshot::MAX_SIZE];
class CSnapshotDelta *m_pSnapshotDelta;
int m_NumTimelineMarkers;
int m_aTimelineMarkers[MAX_TIMELINE_MARKERS];
bool m_NoMapData;
unsigned char *m_pMapData;
DEMOFUNC_FILTER m_pfnFilter;
void *m_pUser;
@ -42,7 +46,7 @@ public:
~CDemoRecorder() override;
int Start(class IStorage *pStorage, class IConsole *pConsole, const char *pFilename, const char *pNetversion, const char *pMap, const SHA256_DIGEST &Sha256, unsigned MapCrc, const char *pType, unsigned MapSize, unsigned char *pMapData, IOHANDLE MapFile = nullptr, DEMOFUNC_FILTER pfnFilter = nullptr, void *pUser = nullptr);
int Stop() override;
int Stop(IDemoRecorder::EStopMode Mode, const char *pTargetFilename = "") override;
void AddDemoMarker();
void AddDemoMarker(int Tick);
@ -51,8 +55,7 @@ public:
void RecordMessage(const void *pData, int Size);
bool IsRecording() const override { return m_File != nullptr; }
char *GetCurrentFilename() override { return m_aCurrentFilename; }
void ClearCurrentFilename() { m_aCurrentFilename[0] = '\0'; }
const char *CurrentFilename() const override { return m_aCurrentFilename; }
int Length() const override { return (m_LastTickMarker - m_FirstTick) / SERVER_TICK_SPEED; }
};

View file

@ -105,13 +105,13 @@ void CMenus::RenderGame(CUIRect MainView)
ButtonBar.VSplitRight(140.0f, &ButtonBar, &Button);
static CButtonContainer s_DemoButton;
bool Recording = DemoRecorder(RECORDER_MANUAL)->IsRecording();
const bool Recording = DemoRecorder(RECORDER_MANUAL)->IsRecording();
if(DoButton_Menu(&s_DemoButton, Recording ? Localize("Stop record") : Localize("Record demo"), 0, &Button))
{
if(!Recording)
Client()->DemoRecorder_Start(Client()->GetCurrentMap(), true, RECORDER_MANUAL);
else
Client()->DemoRecorder_Stop(RECORDER_MANUAL);
Client()->DemoRecorder(RECORDER_MANUAL)->Stop(IDemoRecorder::EStopMode::KEEP_FILE);
}
static CButtonContainer s_SpectateButton;

View file

@ -3194,16 +3194,7 @@ void CMenus::RenderSettingsDDNet(CUIRect MainView)
if(DoButton_CheckBox(&g_Config.m_ClReplays, Localize("Enable replays"), g_Config.m_ClReplays, &Button))
{
g_Config.m_ClReplays ^= 1;
if(!g_Config.m_ClReplays)
{
// stop recording and remove the tmp demo file
Client()->DemoRecorder_Stop(RECORDER_REPLAYS, true);
}
else
{
// start recording
Client()->DemoRecorder_HandleAutoStart();
}
Client()->DemoRecorder_UpdateReplayRecorder();
}
Left.HSplitTop(20.0f, &Button, &Left);