mirror of
https://github.com/ddnet/ddnet.git
synced 2024-11-10 10:08:18 +00:00
Merge #4158
4158: Make emoticons smoother r=heinrich5991 a=Jupeyy It's still not 100% the same as with high bandwidth, but atleast animation wise it should look the same. The client doesn't predict if an emote actually is triggered, so it still only triggeres them every second tick without high bandwidth. ~Since this changes demo playing quite a bit, it should defs be tested~(not really xd) fixes #4156 ## Checklist - [ ] Tested the change ingame - [ ] Provided screenshots if it is a visual change - [ ] Tested in combination with possibly related configuration options - [ ] Written a unit test if it works standalone, system.c especially - [ ] Considered possible null pointers and out of bounds array indexing - [ ] Changed no physics that affect existing maps - [ ] Tested the change with [ASan+UBSan or valgrind's memcheck](https://github.com/ddnet/ddnet/#using-addresssanitizer--undefinedbehavioursanitizer-or-valgrinds-memcheck) (optional) Co-authored-by: heinrich5991 <heinrich5991@gmail.com>
This commit is contained in:
commit
18eabe0038
|
@ -36,6 +36,7 @@ protected:
|
||||||
int m_CurGameTick[NUM_DUMMIES];
|
int m_CurGameTick[NUM_DUMMIES];
|
||||||
float m_GameIntraTick[NUM_DUMMIES];
|
float m_GameIntraTick[NUM_DUMMIES];
|
||||||
float m_GameTickTime[NUM_DUMMIES];
|
float m_GameTickTime[NUM_DUMMIES];
|
||||||
|
float m_GameIntraTickSincePrev[NUM_DUMMIES];
|
||||||
|
|
||||||
int m_PredTick[NUM_DUMMIES];
|
int m_PredTick[NUM_DUMMIES];
|
||||||
float m_PredIntraTick[NUM_DUMMIES];
|
float m_PredIntraTick[NUM_DUMMIES];
|
||||||
|
@ -90,6 +91,7 @@ public:
|
||||||
inline int PredGameTick(int Dummy) const { return m_PredTick[Dummy]; }
|
inline int PredGameTick(int Dummy) const { return m_PredTick[Dummy]; }
|
||||||
inline float IntraGameTick(int Dummy) const { return m_GameIntraTick[Dummy]; }
|
inline float IntraGameTick(int Dummy) const { return m_GameIntraTick[Dummy]; }
|
||||||
inline float PredIntraGameTick(int Dummy) const { return m_PredIntraTick[Dummy]; }
|
inline float PredIntraGameTick(int Dummy) const { return m_PredIntraTick[Dummy]; }
|
||||||
|
inline float IntraGameTickSincePrev(int Dummy) const { return m_GameIntraTickSincePrev[Dummy]; }
|
||||||
inline float GameTickTime(int Dummy) const { return m_GameTickTime[Dummy]; }
|
inline float GameTickTime(int Dummy) const { return m_GameTickTime[Dummy]; }
|
||||||
inline int GameTickSpeed() const { return m_GameTickSpeed; }
|
inline int GameTickSpeed() const { return m_GameTickSpeed; }
|
||||||
|
|
||||||
|
|
|
@ -266,7 +266,7 @@ void CSmoothTime::Update(CGraph *pGraph, int64_t Target, int TimeLeft, int Adjus
|
||||||
}
|
}
|
||||||
|
|
||||||
CClient::CClient() :
|
CClient::CClient() :
|
||||||
m_DemoPlayer(&m_SnapshotDelta)
|
m_DemoPlayer(&m_SnapshotDelta, [&]() { UpdateDemoIntraTimers(); })
|
||||||
{
|
{
|
||||||
for(auto &DemoRecorder : m_DemoRecorder)
|
for(auto &DemoRecorder : m_DemoRecorder)
|
||||||
DemoRecorder = CDemoRecorder(&m_SnapshotDelta);
|
DemoRecorder = CDemoRecorder(&m_SnapshotDelta);
|
||||||
|
@ -2654,6 +2654,17 @@ void DemoPlayer()->SetPause(int paused)
|
||||||
demorec_playback_unpause();
|
demorec_playback_unpause();
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
|
void CClient::UpdateDemoIntraTimers()
|
||||||
|
{
|
||||||
|
// update timers
|
||||||
|
const CDemoPlayer::CPlaybackInfo *pInfo = m_DemoPlayer.Info();
|
||||||
|
m_CurGameTick[g_Config.m_ClDummy] = pInfo->m_Info.m_CurrentTick;
|
||||||
|
m_PrevGameTick[g_Config.m_ClDummy] = pInfo->m_PreviousTick;
|
||||||
|
m_GameIntraTick[g_Config.m_ClDummy] = pInfo->m_IntraTick;
|
||||||
|
m_GameTickTime[g_Config.m_ClDummy] = pInfo->m_TickTime;
|
||||||
|
m_GameIntraTickSincePrev[g_Config.m_ClDummy] = pInfo->m_IntraTickSincePrev;
|
||||||
|
};
|
||||||
|
|
||||||
void CClient::Update()
|
void CClient::Update()
|
||||||
{
|
{
|
||||||
if(State() == IClient::STATE_DEMOPLAYBACK)
|
if(State() == IClient::STATE_DEMOPLAYBACK)
|
||||||
|
@ -2779,6 +2790,7 @@ void CClient::Update()
|
||||||
|
|
||||||
m_GameIntraTick[g_Config.m_ClDummy] = (Now - PrevtickStart) / (float)(CurtickStart - PrevtickStart);
|
m_GameIntraTick[g_Config.m_ClDummy] = (Now - PrevtickStart) / (float)(CurtickStart - PrevtickStart);
|
||||||
m_GameTickTime[g_Config.m_ClDummy] = (Now - PrevtickStart) / (float)Freq; //(float)SERVER_TICK_SPEED);
|
m_GameTickTime[g_Config.m_ClDummy] = (Now - PrevtickStart) / (float)Freq; //(float)SERVER_TICK_SPEED);
|
||||||
|
m_GameIntraTickSincePrev[g_Config.m_ClDummy] = (Now - PrevtickStart) / (float)(Freq / SERVER_TICK_SPEED);
|
||||||
|
|
||||||
CurtickStart = NewPredTick * time_freq() / 50;
|
CurtickStart = NewPredTick * time_freq() / 50;
|
||||||
PrevtickStart = PrevPredTick * time_freq() / 50;
|
PrevtickStart = PrevPredTick * time_freq() / 50;
|
||||||
|
|
|
@ -279,6 +279,8 @@ class CClient : public IClient, public CDemoPlayer::IListener
|
||||||
IOHANDLE m_BenchmarkFile;
|
IOHANDLE m_BenchmarkFile;
|
||||||
int64_t m_BenchmarkStopTime;
|
int64_t m_BenchmarkStopTime;
|
||||||
|
|
||||||
|
void UpdateDemoIntraTimers();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
IEngine *Engine() { return m_pEngine; }
|
IEngine *Engine() { return m_pEngine; }
|
||||||
IEngineGraphics *Graphics() { return m_pGraphics; }
|
IEngineGraphics *Graphics() { return m_pGraphics; }
|
||||||
|
|
|
@ -403,7 +403,19 @@ void CDemoRecorder::AddDemoMarker()
|
||||||
m_pConsole->Print(IConsole::OUTPUT_LEVEL_STANDARD, "demo_recorder", "Added timeline marker", gs_DemoPrintColor);
|
m_pConsole->Print(IConsole::OUTPUT_LEVEL_STANDARD, "demo_recorder", "Added timeline marker", gs_DemoPrintColor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CDemoPlayer::CDemoPlayer(class CSnapshotDelta *pSnapshotDelta, TUpdateIntraTimesFunc &&UpdateIntraTimesFunc)
|
||||||
|
{
|
||||||
|
Construct(pSnapshotDelta);
|
||||||
|
|
||||||
|
m_UpdateIntraTimesFunc = UpdateIntraTimesFunc;
|
||||||
|
}
|
||||||
|
|
||||||
CDemoPlayer::CDemoPlayer(class CSnapshotDelta *pSnapshotDelta)
|
CDemoPlayer::CDemoPlayer(class CSnapshotDelta *pSnapshotDelta)
|
||||||
|
{
|
||||||
|
Construct(pSnapshotDelta);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CDemoPlayer::Construct(class CSnapshotDelta *pSnapshotDelta)
|
||||||
{
|
{
|
||||||
m_File = 0;
|
m_File = 0;
|
||||||
m_pKeyFrames = 0;
|
m_pKeyFrames = 0;
|
||||||
|
@ -553,6 +565,15 @@ void CDemoPlayer::DoTick()
|
||||||
m_Info.m_Info.m_CurrentTick = m_Info.m_NextTick;
|
m_Info.m_Info.m_CurrentTick = m_Info.m_NextTick;
|
||||||
ChunkTick = m_Info.m_Info.m_CurrentTick;
|
ChunkTick = m_Info.m_Info.m_CurrentTick;
|
||||||
|
|
||||||
|
int64_t Freq = time_freq();
|
||||||
|
int64_t CurtickStart = (m_Info.m_Info.m_CurrentTick) * Freq / SERVER_TICK_SPEED;
|
||||||
|
int64_t PrevtickStart = (m_Info.m_PreviousTick) * Freq / SERVER_TICK_SPEED;
|
||||||
|
m_Info.m_IntraTick = (m_Info.m_CurrentTime - PrevtickStart) / (float)(CurtickStart - PrevtickStart);
|
||||||
|
m_Info.m_IntraTickSincePrev = (m_Info.m_CurrentTime - PrevtickStart) / (float)(Freq / SERVER_TICK_SPEED);
|
||||||
|
m_Info.m_TickTime = (m_Info.m_CurrentTime - PrevtickStart) / (float)Freq;
|
||||||
|
if(m_UpdateIntraTimesFunc)
|
||||||
|
m_UpdateIntraTimesFunc();
|
||||||
|
|
||||||
while(1)
|
while(1)
|
||||||
{
|
{
|
||||||
if(ReadChunkHeader(&ChunkType, &ChunkSize, &ChunkTick))
|
if(ReadChunkHeader(&ChunkType, &ChunkSize, &ChunkTick))
|
||||||
|
@ -1005,7 +1026,10 @@ int CDemoPlayer::Update(bool RealTime)
|
||||||
int64_t CurtickStart = (m_Info.m_Info.m_CurrentTick) * Freq / SERVER_TICK_SPEED;
|
int64_t CurtickStart = (m_Info.m_Info.m_CurrentTick) * Freq / SERVER_TICK_SPEED;
|
||||||
int64_t PrevtickStart = (m_Info.m_PreviousTick) * Freq / SERVER_TICK_SPEED;
|
int64_t PrevtickStart = (m_Info.m_PreviousTick) * Freq / SERVER_TICK_SPEED;
|
||||||
m_Info.m_IntraTick = (m_Info.m_CurrentTime - PrevtickStart) / (float)(CurtickStart - PrevtickStart);
|
m_Info.m_IntraTick = (m_Info.m_CurrentTime - PrevtickStart) / (float)(CurtickStart - PrevtickStart);
|
||||||
|
m_Info.m_IntraTickSincePrev = (m_Info.m_CurrentTime - PrevtickStart) / (float)(Freq / SERVER_TICK_SPEED);
|
||||||
m_Info.m_TickTime = (m_Info.m_CurrentTime - PrevtickStart) / (float)Freq;
|
m_Info.m_TickTime = (m_Info.m_CurrentTime - PrevtickStart) / (float)Freq;
|
||||||
|
if(m_UpdateIntraTimesFunc)
|
||||||
|
m_UpdateIntraTimesFunc();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(m_Info.m_Info.m_CurrentTick == m_Info.m_PreviousTick ||
|
if(m_Info.m_Info.m_CurrentTick == m_Info.m_PreviousTick ||
|
||||||
|
@ -1019,10 +1043,8 @@ int CDemoPlayer::Update(bool RealTime)
|
||||||
m_pConsole->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "demo_player", aBuf);
|
m_pConsole->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "demo_player", aBuf);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
m_Time += m_TickTime;
|
m_Time += m_TickTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,9 +7,12 @@
|
||||||
|
|
||||||
#include <engine/demo.h>
|
#include <engine/demo.h>
|
||||||
#include <engine/shared/protocol.h>
|
#include <engine/shared/protocol.h>
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
#include "snapshot.h"
|
#include "snapshot.h"
|
||||||
|
|
||||||
|
typedef std::function<void()> TUpdateIntraTimesFunc;
|
||||||
|
|
||||||
class CDemoRecorder : public IDemoRecorder
|
class CDemoRecorder : public IDemoRecorder
|
||||||
{
|
{
|
||||||
class IConsole *m_pConsole;
|
class IConsole *m_pConsole;
|
||||||
|
@ -75,12 +78,15 @@ public:
|
||||||
int m_PreviousTick;
|
int m_PreviousTick;
|
||||||
|
|
||||||
float m_IntraTick;
|
float m_IntraTick;
|
||||||
|
float m_IntraTickSincePrev;
|
||||||
float m_TickTime;
|
float m_TickTime;
|
||||||
};
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
IListener *m_pListener;
|
IListener *m_pListener;
|
||||||
|
|
||||||
|
TUpdateIntraTimesFunc m_UpdateIntraTimesFunc;
|
||||||
|
|
||||||
// Playback
|
// Playback
|
||||||
struct CKeyFrame
|
struct CKeyFrame
|
||||||
{
|
{
|
||||||
|
@ -120,6 +126,9 @@ private:
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CDemoPlayer(class CSnapshotDelta *pSnapshotDelta);
|
CDemoPlayer(class CSnapshotDelta *pSnapshotDelta);
|
||||||
|
CDemoPlayer(class CSnapshotDelta *pSnapshotDelta, TUpdateIntraTimesFunc &&UpdateIntraTimesFunc);
|
||||||
|
|
||||||
|
void Construct(class CSnapshotDelta *pSnapshotDelta);
|
||||||
|
|
||||||
void SetListener(IListener *pListener);
|
void SetListener(IListener *pListener);
|
||||||
|
|
||||||
|
|
|
@ -605,10 +605,10 @@ void CPlayers::RenderPlayer(
|
||||||
Graphics()->QuadsSetRotation(0);
|
Graphics()->QuadsSetRotation(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(g_Config.m_ClShowEmotes && !m_pClient->m_aClients[ClientID].m_EmoticonIgnore && m_pClient->m_aClients[ClientID].m_EmoticonStart != -1 && m_pClient->m_aClients[ClientID].m_EmoticonStart <= Client()->GameTick(g_Config.m_ClDummy) && m_pClient->m_aClients[ClientID].m_EmoticonStart + 2 * Client()->GameTickSpeed() > Client()->GameTick(g_Config.m_ClDummy))
|
if(g_Config.m_ClShowEmotes && !m_pClient->m_aClients[ClientID].m_EmoticonIgnore && m_pClient->m_aClients[ClientID].m_EmoticonStart != -1 && m_pClient->m_aClients[ClientID].m_EmoticonStart <= (double)Client()->GameTick(g_Config.m_ClDummy) + Client()->IntraGameTickSincePrev(g_Config.m_ClDummy) && m_pClient->m_aClients[ClientID].m_EmoticonStart + 2 * Client()->GameTickSpeed() > ((double)Client()->GameTick(g_Config.m_ClDummy) + Client()->IntraGameTickSincePrev(g_Config.m_ClDummy)))
|
||||||
{
|
{
|
||||||
int SinceStart = Client()->GameTick(g_Config.m_ClDummy) - m_pClient->m_aClients[ClientID].m_EmoticonStart;
|
float SinceStart = (float)((double)Client()->GameTick(g_Config.m_ClDummy) + Client()->IntraGameTickSincePrev(g_Config.m_ClDummy)) - m_pClient->m_aClients[ClientID].m_EmoticonStart;
|
||||||
int FromEnd = m_pClient->m_aClients[ClientID].m_EmoticonStart + 2 * Client()->GameTickSpeed() - Client()->GameTick(g_Config.m_ClDummy);
|
float FromEnd = m_pClient->m_aClients[ClientID].m_EmoticonStart + 2 * Client()->GameTickSpeed() - ((double)Client()->GameTick(g_Config.m_ClDummy) + Client()->IntraGameTickSincePrev(g_Config.m_ClDummy));
|
||||||
|
|
||||||
float a = 1;
|
float a = 1;
|
||||||
|
|
||||||
|
|
|
@ -739,7 +739,7 @@ void CGameClient::OnMessage(int MsgId, CUnpacker *pUnpacker, bool IsDummy)
|
||||||
|
|
||||||
// apply
|
// apply
|
||||||
m_aClients[pMsg->m_ClientID].m_Emoticon = pMsg->m_Emoticon;
|
m_aClients[pMsg->m_ClientID].m_Emoticon = pMsg->m_Emoticon;
|
||||||
m_aClients[pMsg->m_ClientID].m_EmoticonStart = Client()->GameTick(g_Config.m_ClDummy);
|
m_aClients[pMsg->m_ClientID].m_EmoticonStart = (double)Client()->GameTick(g_Config.m_ClDummy) + Client()->IntraGameTickSincePrev(g_Config.m_ClDummy);
|
||||||
}
|
}
|
||||||
else if(MsgId == NETMSGTYPE_SV_SOUNDGLOBAL)
|
else if(MsgId == NETMSGTYPE_SV_SOUNDGLOBAL)
|
||||||
{
|
{
|
||||||
|
|
|
@ -334,7 +334,7 @@ public:
|
||||||
int m_SkinColor;
|
int m_SkinColor;
|
||||||
int m_Team;
|
int m_Team;
|
||||||
int m_Emoticon;
|
int m_Emoticon;
|
||||||
int m_EmoticonStart;
|
double m_EmoticonStart;
|
||||||
bool m_Solo;
|
bool m_Solo;
|
||||||
bool m_Jetpack;
|
bool m_Jetpack;
|
||||||
bool m_NoCollision;
|
bool m_NoCollision;
|
||||||
|
|
Loading…
Reference in a new issue