infinite length and a lot of changes including notifications are now chat messages

This commit is contained in:
archimede67 2019-06-05 19:17:55 +02:00
parent 2e27a22927
commit 929bf57bf6
11 changed files with 60 additions and 94 deletions

View file

@ -19,14 +19,6 @@ enum
typedef bool (*CLIENTFUNC_FILTER)(const void *pData, int DataSize, void *pUser); typedef bool (*CLIENTFUNC_FILTER)(const void *pData, int DataSize, void *pUser);
class CHudNotification
{
public:
const char *m_pTitle;
const char *m_pMessage;
int64 m_ExpireTime;
};
class IClient : public IInterface class IClient : public IInterface
{ {
MACRO_INTERFACE("client", 0) MACRO_INTERFACE("client", 0)
@ -34,8 +26,6 @@ protected:
// quick access to state of the client // quick access to state of the client
int m_State; int m_State;
CHudNotification m_CurrentNotification;
// quick access to time variables // quick access to time variables
int m_PrevGameTick[2]; int m_PrevGameTick[2];
int m_CurGameTick[2]; int m_CurGameTick[2];
@ -82,9 +72,6 @@ public:
STATE_QUITING, STATE_QUITING,
}; };
CHudNotification *CurrentNotification() { return &m_CurrentNotification; };
bool HasNotification() { return m_CurrentNotification.m_pTitle; };
// //
inline int State() const { return m_State; } inline int State() const { return m_State; }
@ -250,6 +237,7 @@ public:
virtual const char *NetVersion() = 0; virtual const char *NetVersion() = 0;
virtual void OnDummyDisconnect() = 0; virtual void OnDummyDisconnect() = 0;
virtual void Echo(const char *pString) = 0;
}; };
extern IGameClient *CreateGameClient(); extern IGameClient *CreateGameClient();

View file

@ -781,7 +781,7 @@ void CClient::Disconnect()
DisconnectWithReason(0); DisconnectWithReason(0);
// make sure to remove replay tmp demo // make sure to remove replay tmp demo
if(g_Config.m_ClRaceReplays) if(g_Config.m_ClReplays)
{ {
Storage()->RemoveFile((&m_DemoRecorder[RECORDER_REPLAYS])->GetCurrentFilename(), IStorage::TYPE_SAVE); Storage()->RemoveFile((&m_DemoRecorder[RECORDER_REPLAYS])->GetCurrentFilename(), IStorage::TYPE_SAVE);
} }
@ -1077,15 +1077,6 @@ void CClient::Render()
int64 Now = time_get(); int64 Now = time_get();
g_Config.m_ClAntiPing = (m_PredictedTime.Get(Now)-m_GameTime[g_Config.m_ClDummy].Get(Now))*1000/(float)time_freq() > g_Config.m_ClAntiPingLimit; g_Config.m_ClAntiPing = (m_PredictedTime.Get(Now)-m_GameTime[g_Config.m_ClDummy].Get(Now))*1000/(float)time_freq() > g_Config.m_ClAntiPingLimit;
} }
if(HasNotification())
{
int64 Now = time_get();
if(CurrentNotification()->m_ExpireTime < Now)
{
EndNotification();
}
}
} }
const char *CClient::LoadMap(const char *pName, const char *pFilename, SHA256_DIGEST *pWantedSha256, unsigned WantedCrc) const char *CClient::LoadMap(const char *pName, const char *pFilename, SHA256_DIGEST *pWantedSha256, unsigned WantedCrc)
@ -2676,12 +2667,12 @@ void CClient::Update()
std::shared_ptr<CDemoEdit> e = m_EditJobs.front(); std::shared_ptr<CDemoEdit> e = m_EditJobs.front();
if(e->Status() == IJob::STATE_DONE) if(e->Status() == IJob::STATE_DONE)
{ {
// Notify the player via console and a hud notification
char aBuf[256]; char aBuf[256];
str_format(aBuf, sizeof(aBuf), "Successfully saved the replay to %s!", e->Destination()); str_format(aBuf, sizeof(aBuf), "Successfully saved the replay to %s!", e->Destination());
m_pConsole->Print(IConsole::OUTPUT_LEVEL_STANDARD, "replay", aBuf); m_pConsole->Print(IConsole::OUTPUT_LEVEL_STANDARD, "replay", aBuf);
Notify(Localize("Replay"), Localize("Successfully saved the replay!")); GameClient()->Echo(Localize("Successfully saved the replay!"));
m_EditJobs.pop_front(); m_EditJobs.pop_front();
} }
} }
@ -3330,17 +3321,18 @@ void CClient::Con_SaveReplay(IConsole::IResult *pResult, void *pUserData)
void CClient::SaveReplay(const int Length) void CClient::SaveReplay(const int Length)
{ {
if(!g_Config.m_ClRaceReplays) if(!g_Config.m_ClReplays)
{ {
m_pConsole->Print(IConsole::OUTPUT_LEVEL_STANDARD, "replay", "Feature is disabled. Please enable it via configuration."); m_pConsole->Print(IConsole::OUTPUT_LEVEL_STANDARD, "replay", "Feature is disabled. Please enable it via configuration.");
Notify(Localize("Replay"), Localize("Replay feature is disabled!")); char aBuf[64];
GameClient()->Echo(Localize("Replay feature is disabled!"));
} }
else else
{ {
if(!DemoRecorder(RECORDER_REPLAYS)->IsRecording()) if(!DemoRecorder(RECORDER_REPLAYS)->IsRecording())
{
m_pConsole->Print(IConsole::OUTPUT_LEVEL_STANDARD, "replay", "Error: demorecorder isn't recording. Try to rejoin to fix that."); 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 else
{ {
// First we stop the recorder to slice correctly the demo after // First we stop the recorder to slice correctly the demo after
@ -3357,6 +3349,8 @@ void CClient::SaveReplay(const int Length)
const int EndTick = GameTick(); const int EndTick = GameTick();
const int StartTick = EndTick - Length * GameTickSpeed(); const int StartTick = EndTick - Length * GameTickSpeed();
m_pConsole->Print(IConsole::OUTPUT_LEVEL_STANDARD, "replay", "Saving replay...");
// Create a job to do this slicing in background because it can be a bit long depending on the file size // Create a job to do this slicing in background because it can be a bit long depending on the file size
std::shared_ptr<CDemoEdit> pDemoEditTask = std::make_shared<CDemoEdit>(GameClient()->NetVersion(), &m_SnapshotDelta, m_pStorage, pSrc, aFilename, StartTick, EndTick); std::shared_ptr<CDemoEdit> pDemoEditTask = std::make_shared<CDemoEdit>(GameClient()->NetVersion(), &m_SnapshotDelta, m_pStorage, pSrc, aFilename, StartTick, EndTick);
Engine()->AddJob(pDemoEditTask); Engine()->AddJob(pDemoEditTask);
@ -3368,20 +3362,6 @@ void CClient::SaveReplay(const int Length)
} }
} }
void CClient::Notify(const char *pTitle, const char *pMessage)
{
EndNotification();
new CHudNotification(m_CurrentNotification);
m_CurrentNotification.m_pTitle = pTitle;
m_CurrentNotification.m_pMessage = pMessage;
m_CurrentNotification.m_ExpireTime = time_get() + g_Config.m_ClNotificationTime * time_freq();
}
void CClient::EndNotification()
{
mem_zero(&m_CurrentNotification, sizeof(m_CurrentNotification));
}
void CClient::DemoSlice(const char *pDstPath, CLIENTFUNC_FILTER pfnFilter, void *pUser) void CClient::DemoSlice(const char *pDstPath, CLIENTFUNC_FILTER pfnFilter, void *pUser)
{ {
if(m_DemoPlayer.IsPlaying()) if(m_DemoPlayer.IsPlaying())
@ -3513,7 +3493,7 @@ void CClient::DemoRecorder_HandleAutoStart()
void CClient::DemoRecorder_StartReplayRecorder() void CClient::DemoRecorder_StartReplayRecorder()
{ {
if(g_Config.m_ClRaceReplays) if(g_Config.m_ClReplays)
{ {
DemoRecorder_Stop(RECORDER_REPLAYS); DemoRecorder_Stop(RECORDER_REPLAYS);
char aBuf[512]; char aBuf[512];
@ -3699,6 +3679,26 @@ void CClient::ConchainPassword(IConsole::IResult *pResult, void *pUserData, ICon
pSelf->m_SendPassword = true; pSelf->m_SendPassword = true;
} }
void CClient::ConchainReplays(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData)
{
CClient *pSelf = (CClient *)pUserData;
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();
}
}
}
void CClient::RegisterCommands() void CClient::RegisterCommands()
{ {
m_pConsole = Kernel()->RequestInterface<IConsole>(); m_pConsole = Kernel()->RequestInterface<IConsole>();
@ -3740,6 +3740,7 @@ void CClient::RegisterCommands()
m_pConsole->Register("save_replay", "?i[length]", CFGFLAG_CLIENT, Con_SaveReplay, this, "Save a replay of the last defined amount of seconds"); m_pConsole->Register("save_replay", "?i[length]", CFGFLAG_CLIENT, Con_SaveReplay, this, "Save a replay of the last defined amount of seconds");
m_pConsole->Chain("cl_timeout_seed", ConchainTimeoutSeed, this); m_pConsole->Chain("cl_timeout_seed", ConchainTimeoutSeed, this);
m_pConsole->Chain("cl_replays", ConchainReplays, this);
m_pConsole->Chain("password", ConchainPassword, this); m_pConsole->Chain("password", ConchainPassword, this);

View file

@ -93,6 +93,7 @@ class CClient : public IClient, public CDemoPlayer::IListener
int64 m_LocalStartTime; int64 m_LocalStartTime;
int m_DebugFont; int m_DebugFont;
int m_DebugSoundIndex = 0;
int64 m_LastRenderTime; int64 m_LastRenderTime;
float m_RenderFrameTimeLow; float m_RenderFrameTimeLow;
@ -361,6 +362,7 @@ public:
static void ConchainWindowVSync(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData); static void ConchainWindowVSync(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData);
static void ConchainTimeoutSeed(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData); static void ConchainTimeoutSeed(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData);
static void ConchainPassword(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData); static void ConchainPassword(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData);
static void ConchainReplays(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData);
static void Con_DemoSlice(IConsole::IResult *pResult, void *pUserData); static void Con_DemoSlice(IConsole::IResult *pResult, void *pUserData);
static void Con_DemoSliceBegin(IConsole::IResult *pResult, void *pUserData); static void Con_DemoSliceBegin(IConsole::IResult *pResult, void *pUserData);
@ -417,12 +419,9 @@ public:
virtual void DemoSlice(const char *pDstPath, CLIENTFUNC_FILTER pfnFilter, void *pUser); virtual void DemoSlice(const char *pDstPath, CLIENTFUNC_FILTER pfnFilter, void *pUser);
virtual void SaveReplay(const int Length); virtual void SaveReplay(const int Length);
virtual void Notify(const char * pTitle, const char * pMessage);
bool EditorHasUnsavedData() { return m_pEditor->HasUnsavedData(); } bool EditorHasUnsavedData() { return m_pEditor->HasUnsavedData(); }
virtual IFriends* Foes() {return &m_Foes; } virtual IFriends* Foes() {return &m_Foes; }
virtual void EndNotification();
void GetSmoothTick(int *pSmoothTick, float *pSmoothIntraTick, float MixAmount); void GetSmoothTick(int *pSmoothTick, float *pSmoothIntraTick, float MixAmount);
}; };

View file

@ -264,9 +264,8 @@ MACRO_CONFIG_INT(ConnTimeoutProtection, conn_timeout_protection, 1000, 5, 10000,
MACRO_CONFIG_INT(ClShowIDs, cl_show_ids, 0, 0, 1, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Whether to show client ids in scoreboard") MACRO_CONFIG_INT(ClShowIDs, cl_show_ids, 0, 0, 1, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Whether to show client ids in scoreboard")
MACRO_CONFIG_INT(ClScoreboardOnDeath, cl_scoreboard_on_death, 1, 0, 1, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Whether to show scoreboard after death or not") MACRO_CONFIG_INT(ClScoreboardOnDeath, cl_scoreboard_on_death, 1, 0, 1, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Whether to show scoreboard after death or not")
MACRO_CONFIG_INT(ClAutoRaceRecord, cl_auto_race_record, 1, 0, 1, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Save the best demo of each race") MACRO_CONFIG_INT(ClAutoRaceRecord, cl_auto_race_record, 1, 0, 1, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Save the best demo of each race")
MACRO_CONFIG_INT(ClRaceReplays, cl_race_replays, 0, 0, 1, CFGFLAG_CLIENT | CFGFLAG_SAVE, "Enable replays") MACRO_CONFIG_INT(ClReplays, cl_replays, 0, 0, 1, CFGFLAG_CLIENT | CFGFLAG_SAVE, "Enable/disable replays")
MACRO_CONFIG_INT(ClReplayLength, cl_replay_length, 10, 5, 60, CFGFLAG_CLIENT | CFGFLAG_SAVE, "Set the length of the replays") MACRO_CONFIG_INT(ClReplayLength, cl_replay_length, 30, 10, 0, CFGFLAG_CLIENT | CFGFLAG_SAVE, "Set the default length of the replays")
MACRO_CONFIG_INT(ClNotificationTime, cl_notification_time, 3, 1, 10, CFGFLAG_CLIENT | CFGFLAG_SAVE, "Set the duration of the notifications (how many seconds they should stay on the screen)")
MACRO_CONFIG_INT(ClRaceRecordServerControl, cl_race_record_server_control, 1, 0, 1, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Let the server start the race recorder") MACRO_CONFIG_INT(ClRaceRecordServerControl, cl_race_record_server_control, 1, 0, 1, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Let the server start the race recorder")
MACRO_CONFIG_INT(ClDemoName, cl_demo_name, 1, 0, 1, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Save the player name within the demo") MACRO_CONFIG_INT(ClDemoName, cl_demo_name, 1, 0, 1, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Save the player name within the demo")
MACRO_CONFIG_INT(ClDemoAssumeRace, cl_demo_assume_race, 1, 0, 1, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Assume that demos are race demos") MACRO_CONFIG_INT(ClDemoAssumeRace, cl_demo_assume_race, 1, 0, 1, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Assume that demos are race demos")

View file

@ -138,7 +138,12 @@ void CChat::ConShowChat(IConsole::IResult *pResult, void *pUserData)
void CChat::ConEcho(IConsole::IResult *pResult, void *pUserData) void CChat::ConEcho(IConsole::IResult *pResult, void *pUserData)
{ {
((CChat *)pUserData)->AddLine(-2, 0, pResult->GetString(0)); ((CChat *)pUserData)->Echo(pResult->GetString(0));
}
void CChat::Echo(const char *pString)
{
AddLine(-2, 0, pString);
} }
void CChat::OnConsoleInit() void CChat::OnConsoleInit()

View file

@ -101,6 +101,7 @@ public:
void Say(int Team, const char *pLine); void Say(int Team, const char *pLine);
void SayChat(const char *pLine); void SayChat(const char *pLine);
void RegisterCommand(const char *pName, const char *pParams, int flags, const char *pHelp); void RegisterCommand(const char *pName, const char *pParams, int flags, const char *pHelp);
void Echo(const char *pString);
virtual void OnWindowResize(); virtual void OnWindowResize();
virtual void OnReset(); virtual void OnReset();

View file

@ -807,41 +807,10 @@ void CHud::OnRender()
if(g_Config.m_ClShowRecord) if(g_Config.m_ClShowRecord)
RenderRecord(); RenderRecord();
RenderNotification();
} }
RenderCursor(); RenderCursor();
} }
void CHud::RenderNotification()
{
if (Client()->State() == IClient::STATE_DEMOPLAYBACK || !Client()->HasNotification())
return;
const CHudNotification *pNotif = Client()->CurrentNotification();
const char *pTitle = pNotif->m_pTitle;
const char *pMessage = pNotif->m_pMessage;
float TextWidth = 120.0f;
float Height = 40.0f;
Graphics()->TextureSet(-1);
Graphics()->QuadsBegin();
Graphics()->SetColor(0, 0, 0, 0.40f);
RenderTools()->DrawRoundRect(150.0f*Graphics()->ScreenAspect() - TextWidth / 2.0f, 40, TextWidth, Height, 5.0f);
Graphics()->QuadsEnd();
TextRender()->TextColor(1, 1, 1, 1);
float FontSize = 9.0f;
float w = TextRender()->TextWidth(0, FontSize, pTitle, -1);
TextRender()->Text(0, 150.0f*Graphics()->ScreenAspect() - w/2.0f, 50.0f, FontSize, pTitle, TextWidth - 20);
FontSize = 6.0f;
w = TextRender()->TextWidth(0, FontSize, pMessage, strlen(pMessage));
TextRender()->Text(0, 150.0f*Graphics()->ScreenAspect() - w/2.0f, 62.0f, FontSize, pMessage, TextWidth - 20);
}
void CHud::OnMessage(int MsgType, void *pRawMsg) void CHud::OnMessage(int MsgType, void *pRawMsg)
{ {
if(MsgType == NETMSGTYPE_SV_DDRACETIME) if(MsgType == NETMSGTYPE_SV_DDRACETIME)

View file

@ -68,7 +68,6 @@ public:
virtual void OnWindowResize(); virtual void OnWindowResize();
virtual void OnReset(); virtual void OnReset();
virtual void OnRender(); virtual void OnRender();
virtual void RenderNotification();
virtual void OnInit(); virtual void OnInit();
// DDRace // DDRace

View file

@ -2000,24 +2000,22 @@ void CMenus::RenderSettingsDDNet(CUIRect MainView)
{ {
CUIRect Button, Label; CUIRect Button, Label;
Left.HSplitTop(20.0f, &Button, &Left); Left.HSplitTop(20.0f, &Button, &Left);
Button.VSplitMid(&LeftLeft, &Button); Button.VSplitLeft(160.0f, &LeftLeft, &Button);
Button.VSplitLeft(80.0f, &Label, &Button); Button.VSplitLeft(140.0f, &Label, &Button);
Button.HMargin(2.0f, &Button); Button.HMargin(2.0f, &Button);
char aBuf[256]; char aBuf[256];
str_format(aBuf, sizeof(aBuf), Localize("Length: %d"), g_Config.m_ClReplayLength); str_format(aBuf, sizeof(aBuf), Localize("Default length: %d"), g_Config.m_ClReplayLength);
UI()->DoLabelScaled(&Label, aBuf, 14.0f, -1); UI()->DoLabelScaled(&Label, aBuf, 14.0f, -1);
int FakeLength = g_Config.m_ClReplayLength - 5; // minimum length is 5 not 0 int NewValue = (int)(DoScrollbarH(&g_Config.m_ClReplayLength, &Button, (minimum(g_Config.m_ClReplayLength, 600) - 10) / 590.0f)*590.0f) + 10;
if(g_Config.m_ClReplayLength < 600 || NewValue < 600)
g_Config.m_ClReplayLength = minimum(NewValue, 600);
FakeLength = (int)(DoScrollbarH(&FakeLength, &Button, FakeLength / 55.0f)*55.0f); if(DoButton_CheckBox(&g_Config.m_ClReplays, Localize("Enable replays"), g_Config.m_ClReplays, &LeftLeft))
g_Config.m_ClReplayLength = FakeLength + 5;
if(DoButton_CheckBox(&g_Config.m_ClRaceReplays, Localize("Enable replays"), g_Config.m_ClRaceReplays, &LeftLeft))
{ {
g_Config.m_ClRaceReplays ^= 1; g_Config.m_ClReplays ^= 1;
if(!g_Config.m_ClRaceReplays) if(!g_Config.m_ClReplays)
{ {
// stop recording and remove the tmp demo file // stop recording and remove the tmp demo file
Client()->DemoRecorder_Stop(RECORDER_REPLAYS, true); Client()->DemoRecorder_Stop(RECORDER_REPLAYS, true);

View file

@ -2134,3 +2134,8 @@ vec2 CGameClient::GetSmoothPos(int ClientID)
} }
return Pos; return Pos;
} }
void CGameClient::Echo(const char *pString)
{
m_pChat->Echo(pString);
}

View file

@ -417,6 +417,8 @@ public:
CGameWorld m_PredictedWorld; CGameWorld m_PredictedWorld;
CGameWorld m_PrevPredictedWorld; CGameWorld m_PrevPredictedWorld;
void Echo(const char *pString);
private: private:
bool m_DDRaceMsgSent[2]; bool m_DDRaceMsgSent[2];
int m_ShowOthers[2]; int m_ShowOthers[2];