6790: Prevent /swap with paused players r=def- a=Robyt3

Prevent swapping if either of the players is paused (i.e. their character is not in the gameworld), as this can cause them to be stuck in midair after swapping, which can be exploited to skip parts.

## Checklist

- [X] Tested the change ingame
- [ ] Provided screenshots if it is a visual change
- [X] Tested in combination with possibly related configuration options (servers with `sv_pauseable 0` were and are unaffected)
- [ ] Written a unit test (especially base/) or added coverage to integration test
- [ ] 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)


6793: Use `std::vector` and `std::deque` instead of most `std::list`s r=def- a=Robyt3

Use `std::vector` in cases where elements are only inserted at the end of the collection.

Use `std::deque` in cases where elements are only inserted/deleted at the beginning/end of the collection.

Use `std::list` in the remaining single case where elements are being removed from arbitrary positions and added at either the beginning or the end of the collection.

Adjust variables names. Don't use separate prefix for `std::deque`s and `std::list`s, as they are only used very rarely. Closes #6779.

## 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 (especially base/) or added coverage to integration test
- [ ] 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: Robert Müller <robytemueller@gmail.com>
This commit is contained in:
bors[bot] 2023-07-01 16:04:13 +00:00 committed by GitHub
commit 4bd14933b8
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
18 changed files with 65 additions and 61 deletions

View file

@ -2879,18 +2879,18 @@ void CClient::Update()
if(State() == IClient::STATE_ONLINE)
{
if(!m_lpEditJobs.empty())
if(!m_EditJobs.empty())
{
std::shared_ptr<CDemoEdit> e = m_lpEditJobs.front();
if(e->Status() == IJob::STATE_DONE)
std::shared_ptr<CDemoEdit> pJob = m_EditJobs.front();
if(pJob->Status() == IJob::STATE_DONE)
{
char aBuf[256];
str_format(aBuf, sizeof(aBuf), "Successfully saved the replay to %s!", e->Destination());
char aBuf[IO_MAX_PATH_LENGTH + 64];
str_format(aBuf, sizeof(aBuf), "Successfully saved the replay to %s!", pJob->Destination());
m_pConsole->Print(IConsole::OUTPUT_LEVEL_STANDARD, "replay", aBuf);
GameClient()->Echo(Localize("Successfully saved the replay!"));
m_lpEditJobs.pop_front();
m_EditJobs.pop_front();
}
}
}
@ -3818,7 +3818,7 @@ void CClient::SaveReplay(const int Length, const char *pFilename)
// 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);
Engine()->AddJob(pDemoEditTask);
m_lpEditJobs.push_back(pDemoEditTask);
m_EditJobs.push_back(pDemoEditTask);
// And we restart the recorder
DemoRecorder_StartReplayRecorder();

View file

@ -3,7 +3,7 @@
#ifndef ENGINE_CLIENT_CLIENT_H
#define ENGINE_CLIENT_CLIENT_H
#include <list>
#include <deque>
#include <memory>
#include <base/hash.h>
@ -246,7 +246,7 @@ class CClient : public IClient, public CDemoPlayer::IListener
CSnapshotDelta m_SnapshotDelta;
std::list<std::shared_ptr<CDemoEdit>> m_lpEditJobs;
std::deque<std::shared_ptr<CDemoEdit>> m_EditJobs;
//
bool m_CanReceiveServerCapabilities;

View file

@ -1858,7 +1858,7 @@ static inline int GetCacheIndex(int Type, bool SendClient)
CServer::CCache::CCache()
{
m_Cache.clear();
m_vCache.clear();
}
CServer::CCache::~CCache()
@ -1873,12 +1873,12 @@ CServer::CCache::CCacheChunk::CCacheChunk(const void *pData, int Size)
void CServer::CCache::AddChunk(const void *pData, int Size)
{
m_Cache.emplace_back(pData, Size);
m_vCache.emplace_back(pData, Size);
}
void CServer::CCache::Clear()
{
m_Cache.clear();
m_vCache.clear();
}
void CServer::CacheServerInfo(CCache *pCache, int Type, bool SendClients)
@ -2178,12 +2178,12 @@ void CServer::SendServerInfo(const NETADDR *pAddr, int Token, int Type, bool Sen
Packet.m_Address = *pAddr;
Packet.m_Flags = NETSENDFLAG_CONNLESS;
for(const auto &Chunk : pCache->m_Cache)
for(const auto &Chunk : pCache->m_vCache)
{
p.Reset();
if(Type == SERVERINFO_EXTENDED)
{
if(&Chunk == &pCache->m_Cache.front())
if(&Chunk == &pCache->m_vCache.front())
p.AddRaw(SERVERBROWSE_INFO_EXTENDED, sizeof(SERVERBROWSE_INFO_EXTENDED));
else
p.AddRaw(SERVERBROWSE_INFO_EXTENDED_MORE, sizeof(SERVERBROWSE_INFO_EXTENDED_MORE));
@ -2222,7 +2222,7 @@ void CServer::GetServerInfoSixup(CPacker *pPacker, int Token, bool SendClients)
SendClients = SendClients && Token != -1;
CCache::CCacheChunk &FirstChunk = m_aSixupServerInfoCache[SendClients].m_Cache.front();
CCache::CCacheChunk &FirstChunk = m_aSixupServerInfoCache[SendClients].m_vCache.front();
pPacker->AddRaw(FirstChunk.m_vData.data(), FirstChunk.m_vData.size());
}

View file

@ -350,11 +350,12 @@ public:
public:
CCacheChunk(const void *pData, int Size);
CCacheChunk(const CCacheChunk &) = delete;
CCacheChunk(CCacheChunk &&) = default;
std::vector<uint8_t> m_vData;
};
std::list<CCacheChunk> m_Cache;
std::vector<CCacheChunk> m_vCache;
CCache();
~CCache();

View file

@ -1029,9 +1029,9 @@ void CCharacter::DDRacePostCoreTick()
HandleSkippableTiles(CurrentIndex);
// handle Anti-Skip tiles
std::list<int> Indices = Collision()->GetMapIndices(m_PrevPos, m_Pos);
if(!Indices.empty())
for(int Index : Indices)
std::vector<int> vIndices = Collision()->GetMapIndices(m_PrevPos, m_Pos);
if(!vIndices.empty())
for(int Index : vIndices)
HandleTiles(Index);
else
{

View file

@ -287,10 +287,9 @@ CCharacter *CGameWorld::IntersectCharacter(vec2 Pos0, vec2 Pos1, float Radius, v
return pClosest;
}
std::list<class CCharacter *> CGameWorld::IntersectedCharacters(vec2 Pos0, vec2 Pos1, float Radius, const CEntity *pNotThis)
std::vector<CCharacter *> CGameWorld::IntersectedCharacters(vec2 Pos0, vec2 Pos1, float Radius, const CEntity *pNotThis)
{
std::list<CCharacter *> listOfChars;
std::vector<CCharacter *> vpCharacters;
CCharacter *pChr = (CCharacter *)FindFirst(CGameWorld::ENTTYPE_CHARACTER);
for(; pChr; pChr = (CCharacter *)pChr->TypeNext())
{
@ -303,11 +302,11 @@ std::list<class CCharacter *> CGameWorld::IntersectedCharacters(vec2 Pos0, vec2
float Len = distance(pChr->m_Pos, IntersectPos);
if(Len < pChr->m_ProximityRadius + Radius)
{
listOfChars.push_back(pChr);
vpCharacters.push_back(pChr);
}
}
}
return listOfChars;
return vpCharacters;
}
void CGameWorld::ReleaseHooked(int ClientID)

View file

@ -7,6 +7,7 @@
#include <game/teamscore.h>
#include <list>
#include <vector>
class CCollision;
class CCharacter;
@ -49,7 +50,7 @@ public:
// DDRace
void ReleaseHooked(int ClientID);
std::list<CCharacter *> IntersectedCharacters(vec2 Pos0, vec2 Pos1, float Radius, const CEntity *pNotThis = nullptr);
std::vector<CCharacter *> IntersectedCharacters(vec2 Pos0, vec2 Pos1, float Radius, const CEntity *pNotThis = nullptr);
int m_GameTick;
int m_GameTickSpeed;

View file

@ -76,9 +76,9 @@ bool CRaceHelper::IsStart(CGameClient *pClient, vec2 Prev, vec2 Pos)
}
else
{
std::list<int> Indices = pCollision->GetMapIndices(Prev, Pos);
if(!Indices.empty())
for(int &Indice : Indices)
std::vector<int> vIndices = pCollision->GetMapIndices(Prev, Pos);
if(!vIndices.empty())
for(int &Indice : vIndices)
{
if(pCollision->GetTileIndex(Indice) == TILE_START)
return true;

View file

@ -880,9 +880,9 @@ int CCollision::GetMapIndex(vec2 Pos) const
return -1;
}
std::list<int> CCollision::GetMapIndices(vec2 PrevPos, vec2 Pos, unsigned MaxIndices) const
std::vector<int> CCollision::GetMapIndices(vec2 PrevPos, vec2 Pos, unsigned MaxIndices) const
{
std::list<int> Indices;
std::vector<int> vIndices;
float d = distance(PrevPos, Pos);
int End(d + 1);
if(!d)
@ -893,11 +893,11 @@ std::list<int> CCollision::GetMapIndices(vec2 PrevPos, vec2 Pos, unsigned MaxInd
if(TileExists(Index))
{
Indices.push_back(Index);
return Indices;
vIndices.push_back(Index);
return vIndices;
}
else
return Indices;
return vIndices;
}
else
{
@ -911,14 +911,14 @@ std::list<int> CCollision::GetMapIndices(vec2 PrevPos, vec2 Pos, unsigned MaxInd
int Index = Ny * m_Width + Nx;
if(TileExists(Index) && LastIndex != Index)
{
if(MaxIndices && Indices.size() > MaxIndices)
return Indices;
Indices.push_back(Index);
if(MaxIndices && vIndices.size() > MaxIndices)
return vIndices;
vIndices.push_back(Index);
LastIndex = Index;
}
}
return Indices;
return vIndices;
}
}

View file

@ -6,7 +6,7 @@
#include <base/vmath.h>
#include <engine/shared/protocol.h>
#include <list>
#include <vector>
enum
{
@ -73,7 +73,7 @@ public:
int Entity(int x, int y, int Layer) const;
int GetPureMapIndex(float x, float y) const;
int GetPureMapIndex(vec2 Pos) const { return GetPureMapIndex(Pos.x, Pos.y); }
std::list<int> GetMapIndices(vec2 PrevPos, vec2 Pos, unsigned MaxIndices = 0) const;
std::vector<int> GetMapIndices(vec2 PrevPos, vec2 Pos, unsigned MaxIndices = 0) const;
int GetMapIndex(vec2 Pos) const;
bool TileExists(int Index) const;
bool TileExistsNext(int Index) const;

View file

@ -6459,7 +6459,7 @@ void CEditor::RenderPressedKeys(CUIRect View)
void CEditor::RenderSavingIndicator(CUIRect View)
{
if(m_lpWriterFinishJobs.empty())
if(m_WriterFinishJobs.empty())
return;
UI()->MapScreen();
@ -7065,10 +7065,10 @@ bool CEditor::PerformAutosave()
void CEditor::HandleWriterFinishJobs()
{
if(m_lpWriterFinishJobs.empty())
if(m_WriterFinishJobs.empty())
return;
std::shared_ptr<CDataFileWriterFinishJob> pJob = m_lpWriterFinishJobs.front();
std::shared_ptr<CDataFileWriterFinishJob> pJob = m_WriterFinishJobs.front();
if(pJob->Status() != IJob::STATE_DONE)
return;
@ -7095,7 +7095,7 @@ void CEditor::HandleWriterFinishJobs()
}
}
m_lpWriterFinishJobs.pop_front();
m_WriterFinishJobs.pop_front();
}
void CEditor::OnUpdate()

View file

@ -20,7 +20,7 @@
#include "auto_map.h"
#include <chrono>
#include <list>
#include <deque>
#include <string>
#include <vector>
@ -1154,7 +1154,7 @@ public:
static const void *ms_pUiGotContext;
CEditorMap m_Map;
std::list<std::shared_ptr<CDataFileWriterFinishJob>> m_lpWriterFinishJobs;
std::deque<std::shared_ptr<CDataFileWriterFinishJob>> m_WriterFinishJobs;
int m_ShiftBy;

View file

@ -34,7 +34,7 @@ struct CSoundSource_DEPRECATED
bool CEditor::Save(const char *pFilename)
{
// Check if file with this name is already being saved at the moment
if(std::any_of(std::begin(m_lpWriterFinishJobs), std::end(m_lpWriterFinishJobs), [pFilename](const std::shared_ptr<CDataFileWriterFinishJob> &Job) { return str_comp(pFilename, Job->GetFileName()) == 0; }))
if(std::any_of(std::begin(m_WriterFinishJobs), std::end(m_WriterFinishJobs), [pFilename](const std::shared_ptr<CDataFileWriterFinishJob> &Job) { return str_comp(pFilename, Job->GetFileName()) == 0; }))
return false;
return m_Map.Save(pFilename);
@ -378,7 +378,7 @@ bool CEditorMap::Save(const char *pFileName)
// finish the data file
std::shared_ptr<CDataFileWriterFinishJob> pWriterFinishJob = std::make_shared<CDataFileWriterFinishJob>(pFileName, std::move(df));
m_pEditor->Engine()->AddJob(pWriterFinishJob);
m_pEditor->m_lpWriterFinishJobs.push_back(pWriterFinishJob);
m_pEditor->m_WriterFinishJobs.push_back(pWriterFinishJob);
return true;
}

View file

@ -752,6 +752,11 @@ void CGameContext::ConSwap(IConsole::IResult *pResult, void *pUserData)
pSelf->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "chatresp", "Need to have started the map to swap with a player.");
return;
}
if(pSelf->m_World.m_Core.m_apCharacters[pResult->m_ClientID] == nullptr || pSelf->m_World.m_Core.m_apCharacters[TargetClientId] == nullptr)
{
pSelf->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "chatresp", "You and the other player must not be paused.");
return;
}
bool SwapPending = pSwapPlayer->m_SwapTargetsClientID != pResult->m_ClientID;
if(SwapPending)

View file

@ -2094,10 +2094,10 @@ void CCharacter::DDRacePostCoreTick()
return;
// handle Anti-Skip tiles
std::list<int> Indices = Collision()->GetMapIndices(m_PrevPos, m_Pos);
if(!Indices.empty())
std::vector<int> vIndices = Collision()->GetMapIndices(m_PrevPos, m_Pos);
if(!vIndices.empty())
{
for(int &Index : Indices)
for(int &Index : vIndices)
{
HandleTiles(Index);
if(!m_Alive)

View file

@ -28,11 +28,10 @@ CLight::CLight(CGameWorld *pGameWorld, vec2 Pos, float Rotation, int Length,
bool CLight::HitCharacter()
{
std::list<CCharacter *> HitCharacters =
GameServer()->m_World.IntersectedCharacters(m_Pos, m_To, 0.0f, 0);
if(HitCharacters.empty())
std::vector<CCharacter *> vpHitCharacters = GameServer()->m_World.IntersectedCharacters(m_Pos, m_To, 0.0f, 0);
if(vpHitCharacters.empty())
return false;
for(auto *pChar : HitCharacters)
for(auto *pChar : vpHitCharacters)
{
if(m_Layer == LAYER_SWITCH && m_Number > 0 && !Switchers()[m_Number].m_aStatus[pChar->Team()])
continue;

View file

@ -399,10 +399,9 @@ CCharacter *CGameWorld::ClosestCharacter(vec2 Pos, float Radius, const CEntity *
return pClosest;
}
std::list<class CCharacter *> CGameWorld::IntersectedCharacters(vec2 Pos0, vec2 Pos1, float Radius, const CEntity *pNotThis)
std::vector<CCharacter *> CGameWorld::IntersectedCharacters(vec2 Pos0, vec2 Pos1, float Radius, const CEntity *pNotThis)
{
std::list<CCharacter *> listOfChars;
std::vector<CCharacter *> vpCharacters;
CCharacter *pChr = (CCharacter *)FindFirst(CGameWorld::ENTTYPE_CHARACTER);
for(; pChr; pChr = (CCharacter *)pChr->TypeNext())
{
@ -416,11 +415,11 @@ std::list<class CCharacter *> CGameWorld::IntersectedCharacters(vec2 Pos0, vec2
if(Len < pChr->m_ProximityRadius + Radius)
{
pChr->m_Intersection = IntersectPos;
listOfChars.push_back(pChr);
vpCharacters.push_back(pChr);
}
}
}
return listOfChars;
return vpCharacters;
}
void CGameWorld::ReleaseHooked(int ClientID)

View file

@ -5,7 +5,7 @@
#include <game/gamecore.h>
#include <list>
#include <vector>
class CEntity;
class CCharacter;
@ -165,7 +165,7 @@ public:
Returns:
Returns list with all Characters on line.
*/
std::list<CCharacter *> IntersectedCharacters(vec2 Pos0, vec2 Pos1, float Radius, const CEntity *pNotThis = nullptr);
std::vector<CCharacter *> IntersectedCharacters(vec2 Pos0, vec2 Pos1, float Radius, const CEntity *pNotThis = nullptr);
};
#endif