4245: Further fixes for cpu/zoom on large maps with entityex r=def- a=trml

Attempt to fix #4244

Added network clipping to entity ex for projectiles and pickups, and made snapping of gamecontroller happen before gameworld (as suggested in #4236), which should help when zooming out on large maps in general (where the number of entities exceeds the maximum number of snap items).

Also added bounds checks for switchers in the client.

## 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: trml <trml@users.noreply.github.com>
This commit is contained in:
bors[bot] 2021-10-26 09:50:51 +00:00 committed by GitHub
commit 5df2febd58
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 19 additions and 15 deletions

View file

@ -318,7 +318,7 @@ void CItems::OnRender()
{
for(auto *pProj = (CProjectile *)GameClient()->m_PredictedWorld.FindFirst(CGameWorld::ENTTYPE_PROJECTILE); pProj; pProj = (CProjectile *)pProj->NextEntity())
{
if(!IsSuper && pProj->m_Number > 0 && !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 && !Collision()->m_pSwitchers[pProj->m_Number].m_Status[OwnTeam] && (pProj->m_Explosive ? BlinkingProjEx : BlinkingProj))
continue;
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())
{
if(!IsSuper && pPickup->m_Layer == LAYER_SWITCH && pPickup->m_Number > 0 && !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 && !Collision()->m_pSwitchers[pPickup->m_Number].m_Status[OwnTeam] && BlinkingPickup)
continue;
if(pPickup->InDDNetTile())
@ -358,7 +358,7 @@ void CItems::OnRender()
bool Inactive = false;
if(pEntEx)
Inactive = !IsSuper && pEntEx->m_SwitchNumber > 0 && !Collision()->m_pSwitchers[pEntEx->m_SwitchNumber].m_Status[OwnTeam];
Inactive = !IsSuper && pEntEx->m_SwitchNumber > 0 && pEntEx->m_SwitchNumber < Collision()->m_NumSwitchers && !Collision()->m_pSwitchers[pEntEx->m_SwitchNumber].m_Status[OwnTeam];
if(Item.m_Type == NETOBJTYPE_PROJECTILE || Item.m_Type == NETOBJTYPE_DDNETPROJECTILE)
{

View file

@ -17,7 +17,7 @@ void CPickup::Tick()
{
if(GameWorld()->m_WorldConfig.m_IsVanilla && distance(m_Pos, pChr->m_Pos) >= 20.0f * 2) // pickup distance is shorter on vanilla due to using ClosestEntity
continue;
if(m_Layer == LAYER_SWITCH && m_Number > 0 && !GameWorld()->Collision()->m_pSwitchers[m_Number].m_Status[pChr->Team()])
if(m_Layer == LAYER_SWITCH && m_Number > 0 && m_Number < Collision()->m_NumSwitchers && !GameWorld()->Collision()->m_pSwitchers[m_Number].m_Status[pChr->Team()])
continue;
bool sound = false;
// player picked us up, is someone was hooking us, let them go

View file

@ -110,7 +110,7 @@ void CProjectile::Tick()
CCharacter *apEnts[MAX_CLIENTS];
int Num = GameWorld()->FindEntities(CurPos, 1.0f, (CEntity **)apEnts, MAX_CLIENTS, CGameWorld::ENTTYPE_CHARACTER);
for(int i = 0; i < Num; ++i)
if(apEnts[i] && (m_Layer != LAYER_SWITCH || (m_Layer == LAYER_SWITCH && m_Number > 0 && GameWorld()->Collision()->m_pSwitchers[m_Number].m_Status[apEnts[i]->Team()])))
if(apEnts[i] && (m_Layer != LAYER_SWITCH || (m_Layer == LAYER_SWITCH && m_Number > 0 && m_Number < Collision()->m_NumSwitchers && GameWorld()->Collision()->m_pSwitchers[m_Number].m_Status[apEnts[i]->Team()])))
apEnts[i]->Freeze();
}
if(Collide && m_Bouncing != 0)

View file

@ -160,13 +160,16 @@ void CPickup::Snap(int SnappingClient)
if(SnappingClient > -1 && (GameServer()->m_apPlayers[SnappingClient]->GetTeam() == -1 || GameServer()->m_apPlayers[SnappingClient]->IsPaused()) && GameServer()->m_apPlayers[SnappingClient]->m_SpectatorID != SPEC_FREEVIEW)
Char = GameServer()->GetPlayerChar(GameServer()->m_apPlayers[SnappingClient]->m_SpectatorID);
CNetObj_EntityEx *pEntData = static_cast<CNetObj_EntityEx *>(Server()->SnapNewItem(NETOBJTYPE_ENTITYEX, GetID(), sizeof(CNetObj_EntityEx)));
if(!pEntData)
return;
if(!NetworkClipped(SnappingClient))
{
CNetObj_EntityEx *pEntData = static_cast<CNetObj_EntityEx *>(Server()->SnapNewItem(NETOBJTYPE_ENTITYEX, GetID(), sizeof(CNetObj_EntityEx)));
if(!pEntData)
return;
pEntData->m_SwitchNumber = m_Number;
pEntData->m_Layer = m_Layer;
pEntData->m_EntityClass = ENTITYCLASS_PICKUP;
pEntData->m_SwitchNumber = m_Number;
pEntData->m_Layer = m_Layer;
pEntData->m_EntityClass = ENTITYCLASS_PICKUP;
}
int SnappingClientVersion = SnappingClient >= 0 ? GameServer()->GetClientVersion(SnappingClient) : CLIENT_VERSIONNR;
if(SnappingClientVersion < VERSION_DDNET_SWITCH)

View file

@ -300,6 +300,9 @@ void CProjectile::Snap(int SnappingClient)
{
float Ct = (Server()->Tick() - m_StartTick) / (float)Server()->TickSpeed();
if(NetworkClipped(SnappingClient, GetPos(Ct)))
return;
if(m_LifeSpan == -2)
{
CNetObj_EntityEx *pEntData = static_cast<CNetObj_EntityEx *>(Server()->SnapNewItem(NETOBJTYPE_ENTITYEX, GetID(), sizeof(CNetObj_EntityEx)));
@ -311,9 +314,6 @@ void CProjectile::Snap(int SnappingClient)
pEntData->m_EntityClass = ENTITYCLASS_PROJECTILE;
}
if(NetworkClipped(SnappingClient, GetPos(Ct)))
return;
int SnappingClientVersion = SnappingClient >= 0 ? GameServer()->GetClientVersion(SnappingClient) : CLIENT_VERSIONNR;
if(SnappingClientVersion < VERSION_DDNET_SWITCH)
{

View file

@ -3617,6 +3617,8 @@ void CGameContext::OnSnap(int ClientID)
Server()->SendMsg(&Msg, MSGFLAG_RECORD | MSGFLAG_NOSEND, ClientID);
}
m_pController->Snap(ClientID);
for(auto &pPlayer : m_apPlayers)
{
if(pPlayer)
@ -3627,7 +3629,6 @@ void CGameContext::OnSnap(int ClientID)
m_apPlayers[ClientID]->FakeSnap();
m_World.Snap(ClientID);
m_pController->Snap(ClientID);
m_Events.Snap(ClientID);
}
void CGameContext::OnPreSnap() {}