Make sixup TriggeredEvents reliable

Relevant upstream commit:
d2924b5ad6

Closes https://github.com/ChillerDragon/ddnet/issues/7

The snap item obj_character contains a field called m_TriggeredEvents
https://chillerdragon.github.io/teeworlds-protocol/07/snap_items.html#obj_character

It is responsible for effects and sounds. Those flags are set in the gamecore.
So if the servers gamecore ticks twice and resets the flags before a snap is
sent the client misses the information. Which is not too big of a
problem since the client has his own gamecore running (prediction) which
also sets those flags. But it is still wrong and teeworlds does always
include the triggered events in the snap.

So this commit fixes it using the same approach as teeworlds.
By not resetting the triggered events until a snap was sent.
This commit is contained in:
ChillerDragon 2024-04-29 08:25:34 +08:00
parent d265057591
commit 5f784cbcda
6 changed files with 47 additions and 12 deletions

View file

@ -28,6 +28,7 @@ CCharacter::CCharacter(CGameWorld *pWorld, CNetObj_PlayerInput LastInput) :
{ {
m_Health = 0; m_Health = 0;
m_Armor = 0; m_Armor = 0;
m_TriggeredEvents7 = 0;
m_StrongWeakId = 0; m_StrongWeakId = 0;
m_Input = LastInput; m_Input = LastInput;
@ -861,6 +862,17 @@ void CCharacter::TickDeferred()
if(Events & COREEVENT_HOOK_HIT_NOHOOK) if(Events & COREEVENT_HOOK_HIT_NOHOOK)
GameServer()->CreateSound(m_Pos, SOUND_HOOK_NOATTACH, TeamMaskExceptSelf); GameServer()->CreateSound(m_Pos, SOUND_HOOK_NOATTACH, TeamMaskExceptSelf);
if(Events & COREEVENT_GROUND_JUMP)
m_TriggeredEvents7 |= protocol7::COREEVENTFLAG_GROUND_JUMP;
if(Events & COREEVENT_AIR_JUMP)
m_TriggeredEvents7 |= protocol7::COREEVENTFLAG_AIR_JUMP;
if(Events & COREEVENT_HOOK_ATTACH_PLAYER)
m_TriggeredEvents7 |= protocol7::COREEVENTFLAG_HOOK_ATTACH_PLAYER;
if(Events & COREEVENT_HOOK_ATTACH_GROUND)
m_TriggeredEvents7 |= protocol7::COREEVENTFLAG_HOOK_ATTACH_GROUND;
if(Events & COREEVENT_HOOK_HIT_NOHOOK)
m_TriggeredEvents7 |= protocol7::COREEVENTFLAG_HOOK_HIT_NOHOOK;
} }
if(m_pPlayer->GetTeam() == TEAM_SPECTATORS) if(m_pPlayer->GetTeam() == TEAM_SPECTATORS)
@ -1122,18 +1134,7 @@ void CCharacter::SnapCharacter(int SnappingClient, int Id)
pCharacter->m_Health = Health; pCharacter->m_Health = Health;
pCharacter->m_Armor = Armor; pCharacter->m_Armor = Armor;
int TriggeredEvents7 = 0; pCharacter->m_TriggeredEvents = m_TriggeredEvents7;
if(m_Core.m_TriggeredEvents & COREEVENT_GROUND_JUMP)
TriggeredEvents7 |= protocol7::COREEVENTFLAG_GROUND_JUMP;
if(m_Core.m_TriggeredEvents & COREEVENT_AIR_JUMP)
TriggeredEvents7 |= protocol7::COREEVENTFLAG_AIR_JUMP;
if(m_Core.m_TriggeredEvents & COREEVENT_HOOK_ATTACH_PLAYER)
TriggeredEvents7 |= protocol7::COREEVENTFLAG_HOOK_ATTACH_PLAYER;
if(m_Core.m_TriggeredEvents & COREEVENT_HOOK_ATTACH_GROUND)
TriggeredEvents7 |= protocol7::COREEVENTFLAG_HOOK_ATTACH_GROUND;
if(m_Core.m_TriggeredEvents & COREEVENT_HOOK_HIT_NOHOOK)
TriggeredEvents7 |= protocol7::COREEVENTFLAG_HOOK_HIT_NOHOOK;
pCharacter->m_TriggeredEvents = TriggeredEvents7;
} }
} }
@ -1277,6 +1278,11 @@ void CCharacter::Snap(int SnappingClient)
pDDNetCharacter->m_TargetY = m_Core.m_Input.m_TargetY; pDDNetCharacter->m_TargetY = m_Core.m_Input.m_TargetY;
} }
void CCharacter::PostSnap()
{
m_TriggeredEvents7 = 0;
}
// DDRace // DDRace
bool CCharacter::CanCollide(int ClientId) bool CCharacter::CanCollide(int ClientId)

View file

@ -38,6 +38,7 @@ public:
void TickDeferred() override; void TickDeferred() override;
void TickPaused() override; void TickPaused() override;
void Snap(int SnappingClient) override; void Snap(int SnappingClient) override;
void PostSnap() override;
void SwapClients(int Client1, int Client2) override; void SwapClients(int Client1, int Client2) override;
bool CanSnapCharacter(int SnappingClient); bool CanSnapCharacter(int SnappingClient);
@ -144,6 +145,8 @@ private:
int m_Health; int m_Health;
int m_Armor; int m_Armor;
int m_TriggeredEvents7;
// the player core for the physics // the player core for the physics
CCharacterCore m_Core; CCharacterCore m_Core;
CGameTeams *m_pTeams = nullptr; CGameTeams *m_pTeams = nullptr;

View file

@ -122,6 +122,12 @@ public: // TODO: Maybe make protected
*/ */
virtual void Snap(int SnappingClient) {} virtual void Snap(int SnappingClient) {}
/*
Function: PostSnap
Called after all clients received their snapshot.
*/
virtual void PostSnap() {}
/* /*
Function: SwapClients Function: SwapClients
Called when two players have swapped their client ids. Called when two players have swapped their client ids.

View file

@ -4235,6 +4235,7 @@ void CGameContext::OnSnap(int ClientId)
void CGameContext::OnPreSnap() {} void CGameContext::OnPreSnap() {}
void CGameContext::OnPostSnap() void CGameContext::OnPostSnap()
{ {
m_World.PostSnap();
m_Events.Clear(); m_Events.Clear();
} }

View file

@ -129,6 +129,19 @@ void CGameWorld::Snap(int SnappingClient)
} }
} }
void CGameWorld::PostSnap()
{
for(auto *pEnt : m_apFirstEntityTypes)
{
for(; pEnt;)
{
m_pNextTraverseEntity = pEnt->m_pNextTypeEntity;
pEnt->PostSnap();
pEnt = m_pNextTraverseEntity;
}
}
}
void CGameWorld::Reset() void CGameWorld::Reset()
{ {
// reset all entities // reset all entities

View file

@ -133,6 +133,12 @@ public:
*/ */
void Snap(int SnappingClient); void Snap(int SnappingClient);
/*
Function: PostSnap
Called after all clients received their snapshot.
*/
void PostSnap();
/* /*
Function: Tick Function: Tick
Calls Tick on all the entities in the world to progress Calls Tick on all the entities in the world to progress