4341: Make laser doors show correctly when spectating other players r=def- a=trml

Makes the server send the switch state of other players while spectating others, otherwise the switch state of your own player (including when spectating in freeview).

Also changed the client a little to both handle situations where the server only sends one SWITCHSTATE netobject (then it just uses that team) or all (then it chooses the team that maintains the above behavior). I'm not sure if the latter would really be useful (but since the netobject contains a team it would be possible to do so).

## Checklist

- [x] 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: trml <trml@users.noreply.github.com>
This commit is contained in:
bors[bot] 2021-11-09 08:40:52 +00:00 committed by GitHub
commit 0443a3ef65
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 24 additions and 9 deletions

View file

@ -310,7 +310,7 @@ void CItems::OnRender()
bool BlinkingProj = (Ticks % 20) < 2; bool BlinkingProj = (Ticks % 20) < 2;
bool BlinkingProjEx = (Ticks % 6) < 2; bool BlinkingProjEx = (Ticks % 6) < 2;
bool BlinkingLight = (Ticks % 6) < 2; bool BlinkingLight = (Ticks % 6) < 2;
int OwnTeam = m_pClient->OwnTeam(); int SwitcherTeam = m_pClient->SwitchStateTeam();
int DraggerStartTick = maximum((Client()->GameTick(g_Config.m_ClDummy) / 7) * 7, Client()->GameTick(g_Config.m_ClDummy) - 4); int DraggerStartTick = maximum((Client()->GameTick(g_Config.m_ClDummy) / 7) * 7, Client()->GameTick(g_Config.m_ClDummy) - 4);
bool UsePredicted = GameClient()->Predict() && GameClient()->AntiPingGunfire(); bool UsePredicted = GameClient()->Predict() && GameClient()->AntiPingGunfire();
@ -318,7 +318,7 @@ void CItems::OnRender()
{ {
for(auto *pProj = (CProjectile *)GameClient()->m_PredictedWorld.FindFirst(CGameWorld::ENTTYPE_PROJECTILE); pProj; pProj = (CProjectile *)pProj->NextEntity()) for(auto *pProj = (CProjectile *)GameClient()->m_PredictedWorld.FindFirst(CGameWorld::ENTTYPE_PROJECTILE); pProj; pProj = (CProjectile *)pProj->NextEntity())
{ {
if(!IsSuper && pProj->m_Number > 0 && pProj->m_Number < Collision()->m_NumSwitchers + 1 && !Collision()->m_pSwitchers[pProj->m_Number].m_Status[OwnTeam] && (pProj->m_Explosive ? BlinkingProjEx : BlinkingProj)) if(!IsSuper && pProj->m_Number > 0 && pProj->m_Number < Collision()->m_NumSwitchers + 1 && !Collision()->m_pSwitchers[pProj->m_Number].m_Status[SwitcherTeam] && (pProj->m_Explosive ? BlinkingProjEx : BlinkingProj))
continue; continue;
CProjectileData Data = pProj->GetData(); CProjectileData Data = pProj->GetData();
@ -334,7 +334,7 @@ void CItems::OnRender()
} }
for(auto *pPickup = (CPickup *)GameClient()->m_PredictedWorld.FindFirst(CGameWorld::ENTTYPE_PICKUP); pPickup; pPickup = (CPickup *)pPickup->NextEntity()) for(auto *pPickup = (CPickup *)GameClient()->m_PredictedWorld.FindFirst(CGameWorld::ENTTYPE_PICKUP); pPickup; pPickup = (CPickup *)pPickup->NextEntity())
{ {
if(!IsSuper && pPickup->m_Layer == LAYER_SWITCH && pPickup->m_Number > 0 && pPickup->m_Number < Collision()->m_NumSwitchers + 1 && !Collision()->m_pSwitchers[pPickup->m_Number].m_Status[OwnTeam] && BlinkingPickup) if(!IsSuper && pPickup->m_Layer == LAYER_SWITCH && pPickup->m_Number > 0 && pPickup->m_Number < Collision()->m_NumSwitchers + 1 && !Collision()->m_pSwitchers[pPickup->m_Number].m_Status[SwitcherTeam] && BlinkingPickup)
continue; continue;
if(pPickup->InDDNetTile()) if(pPickup->InDDNetTile())
@ -358,7 +358,7 @@ void CItems::OnRender()
bool Inactive = false; bool Inactive = false;
if(pEntEx) if(pEntEx)
Inactive = !IsSuper && pEntEx->m_SwitchNumber > 0 && pEntEx->m_SwitchNumber < Collision()->m_NumSwitchers + 1 && !Collision()->m_pSwitchers[pEntEx->m_SwitchNumber].m_Status[OwnTeam]; Inactive = !IsSuper && pEntEx->m_SwitchNumber > 0 && pEntEx->m_SwitchNumber < Collision()->m_NumSwitchers + 1 && !Collision()->m_pSwitchers[pEntEx->m_SwitchNumber].m_Status[SwitcherTeam];
if(Item.m_Type == NETOBJTYPE_PROJECTILE || Item.m_Type == NETOBJTYPE_DDNETPROJECTILE) if(Item.m_Type == NETOBJTYPE_PROJECTILE || Item.m_Type == NETOBJTYPE_DDNETPROJECTILE)
{ {

View file

@ -277,6 +277,8 @@ void CGameClient::OnInit()
m_DDRaceMsgSent[1] = false; m_DDRaceMsgSent[1] = false;
m_ShowOthers[0] = -1; m_ShowOthers[0] = -1;
m_ShowOthers[1] = -1; m_ShowOthers[1] = -1;
m_SwitchStateTeam[0] = -1;
m_SwitchStateTeam[1] = -1;
m_LastZoom = .0; m_LastZoom = .0;
m_LastScreenAspect = .0; m_LastScreenAspect = .0;
@ -1146,6 +1148,8 @@ void CGameClient::OnNewSnapshot()
#endif #endif
bool FoundGameInfoEx = false; bool FoundGameInfoEx = false;
bool GotSwitchStateTeam = false;
m_SwitchStateTeam[g_Config.m_ClDummy] = -1;
for(auto &Client : m_aClients) for(auto &Client : m_aClients)
{ {
@ -1440,6 +1444,12 @@ void CGameClient::OnNewSnapshot()
Collision()->m_pSwitchers[i].m_Type[Team] = TILE_SWITCHCLOSE; Collision()->m_pSwitchers[i].m_Type[Team] = TILE_SWITCHCLOSE;
Collision()->m_pSwitchers[i].m_EndTick[Team] = 0; Collision()->m_pSwitchers[i].m_EndTick[Team] = 0;
} }
if(!GotSwitchStateTeam)
m_SwitchStateTeam[g_Config.m_ClDummy] = Team;
else
m_SwitchStateTeam[g_Config.m_ClDummy] = -1;
GotSwitchStateTeam = true;
} }
} }
} }
@ -2591,11 +2601,11 @@ bool CGameClient::IsOtherTeam(int ClientID)
return m_Teams.Team(ClientID) != m_Teams.Team(m_Snap.m_LocalClientID); return m_Teams.Team(ClientID) != m_Teams.Team(m_Snap.m_LocalClientID);
} }
int CGameClient::OwnTeam() int CGameClient::SwitchStateTeam()
{ {
if(m_Snap.m_LocalClientID < 0) if(m_SwitchStateTeam[g_Config.m_ClDummy] >= 0)
return 0; return m_SwitchStateTeam[g_Config.m_ClDummy];
else if(m_aClients[m_Snap.m_LocalClientID].m_Team == TEAM_SPECTATORS && m_Snap.m_SpecInfo.m_SpectatorID == SPEC_FREEVIEW) else if(m_Snap.m_LocalClientID < 0)
return 0; return 0;
else if(m_Snap.m_SpecInfo.m_Active && m_Snap.m_SpecInfo.m_SpectatorID != SPEC_FREEVIEW) else if(m_Snap.m_SpecInfo.m_Active && m_Snap.m_SpecInfo.m_SpectatorID != SPEC_FREEVIEW)
return m_Teams.Team(m_Snap.m_SpecInfo.m_SpectatorID); return m_Teams.Team(m_Snap.m_SpecInfo.m_SpectatorID);

View file

@ -520,7 +520,7 @@ public:
void DummyResetInput(); void DummyResetInput();
void Echo(const char *pString); void Echo(const char *pString);
bool IsOtherTeam(int ClientID); bool IsOtherTeam(int ClientID);
int OwnTeam(); int SwitchStateTeam();
bool IsLocalCharSuper(); bool IsLocalCharSuper();
bool CanDisplayWarning(); bool CanDisplayWarning();
bool IsDisplayingWarning(); bool IsDisplayingWarning();
@ -657,6 +657,7 @@ private:
int m_IsDummySwapping; int m_IsDummySwapping;
CCharOrder m_CharOrder; CCharOrder m_CharOrder;
class CCharacter m_aLastWorldCharacters[MAX_CLIENTS]; class CCharacter m_aLastWorldCharacters[MAX_CLIENTS];
int m_SwitchStateTeam[NUM_DUMMIES];
enum enum
{ {

View file

@ -632,6 +632,10 @@ void IGameController::Snap(int SnappingClient)
if(GameServer()->Collision()->m_pSwitchers) if(GameServer()->Collision()->m_pSwitchers)
{ {
int Team = pPlayer && pPlayer->GetCharacter() ? pPlayer->GetCharacter()->Team() : 0; int Team = pPlayer && pPlayer->GetCharacter() ? pPlayer->GetCharacter()->Team() : 0;
if(pPlayer && (pPlayer->GetTeam() == TEAM_SPECTATORS || pPlayer->IsPaused()) && pPlayer->m_SpectatorID != SPEC_FREEVIEW && GameServer()->m_apPlayers[pPlayer->m_SpectatorID] && GameServer()->m_apPlayers[pPlayer->m_SpectatorID]->GetCharacter())
Team = GameServer()->m_apPlayers[pPlayer->m_SpectatorID]->GetCharacter()->Team();
CNetObj_SwitchState *pSwitchState = static_cast<CNetObj_SwitchState *>(Server()->SnapNewItem(NETOBJTYPE_SWITCHSTATE, Team, sizeof(CNetObj_SwitchState))); CNetObj_SwitchState *pSwitchState = static_cast<CNetObj_SwitchState *>(Server()->SnapNewItem(NETOBJTYPE_SWITCHSTATE, Team, sizeof(CNetObj_SwitchState)));
if(!pSwitchState) if(!pSwitchState)
return; return;