| 3860 | } |
| 3861 | |
| 3862 | void CClient::SaveReplay(const int Length, const char *pFilename) |
| 3863 | { |
| 3864 | if(!g_Config.m_ClReplays) |
| 3865 | { |
| 3866 | m_pConsole->Print(IConsole::OUTPUT_LEVEL_STANDARD, "replay", "Feature is disabled. Please enable it via configuration."); |
| 3867 | GameClient()->Echo(Localize("Replay feature is disabled!")); |
| 3868 | return; |
| 3869 | } |
| 3870 | |
| 3871 | if(!DemoRecorder(RECORDER_REPLAYS)->IsRecording()) |
| 3872 | { |
| 3873 | m_pConsole->Print(IConsole::OUTPUT_LEVEL_STANDARD, "replay", "ERROR: demorecorder isn't recording. Try to rejoin to fix that."); |
| 3874 | } |
| 3875 | else if(DemoRecorder(RECORDER_REPLAYS)->Length() < 1) |
| 3876 | { |
| 3877 | m_pConsole->Print(IConsole::OUTPUT_LEVEL_STANDARD, "replay", "ERROR: demorecorder isn't recording for at least 1 second."); |
| 3878 | } |
| 3879 | else |
| 3880 | { |
| 3881 | char aFilename[IO_MAX_PATH_LENGTH]; |
| 3882 | if(pFilename[0] == '\0') |
| 3883 | { |
| 3884 | char aTimestamp[20]; |
| 3885 | str_timestamp(aTimestamp, sizeof(aTimestamp)); |
| 3886 | str_format(aFilename, sizeof(aFilename), "demos/replays/%s_%s_(replay).demo", GameClient()->Map()->BaseName(), aTimestamp); |
| 3887 | } |
| 3888 | else |
| 3889 | { |
| 3890 | str_format(aFilename, sizeof(aFilename), "demos/replays/%s.demo", pFilename); |
| 3891 | IOHANDLE Handle = m_pStorage->OpenFile(aFilename, IOFLAG_WRITE, IStorage::TYPE_SAVE); |
| 3892 | if(!Handle) |
| 3893 | { |
| 3894 | m_pConsole->Print(IConsole::OUTPUT_LEVEL_STANDARD, "replay", "ERROR: invalid filename. Try a different one!"); |
| 3895 | return; |
| 3896 | } |
| 3897 | io_close(Handle); |
| 3898 | m_pStorage->RemoveFile(aFilename, IStorage::TYPE_SAVE); |
| 3899 | } |
| 3900 | |
| 3901 | // Stop the recorder to correctly slice the demo after |
| 3902 | DemoRecorder(RECORDER_REPLAYS)->Stop(IDemoRecorder::EStopMode::KEEP_FILE); |
| 3903 | |
| 3904 | // Slice the demo to get only the last cl_replay_length seconds |
| 3905 | const char *pSrc = m_aDemoRecorder[RECORDER_REPLAYS].CurrentFilename(); |
| 3906 | const int EndTick = GameTick(g_Config.m_ClDummy); |
| 3907 | const int StartTick = EndTick - Length * GameTickSpeed(); |
| 3908 | |
| 3909 | m_pConsole->Print(IConsole::OUTPUT_LEVEL_STANDARD, "replay", "Saving replay..."); |
| 3910 | |
| 3911 | // Create a job to do this slicing in background because it can be a bit long depending on the file size |
| 3912 | std::shared_ptr<CDemoEdit> pDemoEditTask = std::make_shared<CDemoEdit>(GameClient()->NetVersion(), &m_SnapshotDelta, m_pStorage, pSrc, aFilename, StartTick, EndTick); |
| 3913 | Engine()->AddJob(pDemoEditTask); |
| 3914 | m_EditJobs.push_back(pDemoEditTask); |
| 3915 | |
| 3916 | // And we restart the recorder |
| 3917 | DemoRecorder_UpdateReplayRecorder(); |
| 3918 | } |
| 3919 | } |
no test coverage detected