Merge pull request #8781 from def-/pr-fix

Disallow save with draggers
This commit is contained in:
Dennis Felsing 2024-08-22 09:38:46 +00:00 committed by GitHub
commit 5210d77f92
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 75 additions and 21 deletions

View file

@ -870,7 +870,7 @@ void CGameContext::ConDrySave(IConsole::IResult *pResult, void *pUserData)
CSaveTeam SavedTeam; CSaveTeam SavedTeam;
int Team = pSelf->GetDDRaceTeam(pResult->m_ClientId); int Team = pSelf->GetDDRaceTeam(pResult->m_ClientId);
int Result = SavedTeam.Save(pSelf, Team, true); ESaveResult Result = SavedTeam.Save(pSelf, Team, true);
if(CSaveTeam::HandleSaveError(Result, pResult->m_ClientId, pSelf)) if(CSaveTeam::HandleSaveError(Result, pResult->m_ClientId, pSelf))
return; return;

View file

@ -10,6 +10,7 @@
#include <game/mapitems.h> #include <game/mapitems.h>
#include <game/server/gamecontext.h> #include <game/server/gamecontext.h>
#include <game/server/save.h>
CDraggerBeam::CDraggerBeam(CGameWorld *pGameWorld, CDragger *pDragger, vec2 Pos, float Strength, bool IgnoreWalls, CDraggerBeam::CDraggerBeam(CGameWorld *pGameWorld, CDragger *pDragger, vec2 Pos, float Strength, bool IgnoreWalls,
int ForClientId, int Layer, int Number) : int ForClientId, int Layer, int Number) :
@ -140,3 +141,8 @@ void CDraggerBeam::SwapClients(int Client1, int Client2)
{ {
m_ForClientId = m_ForClientId == Client1 ? Client2 : m_ForClientId == Client2 ? Client1 : m_ForClientId; m_ForClientId = m_ForClientId == Client1 ? Client2 : m_ForClientId == Client2 ? Client1 : m_ForClientId;
} }
ESaveResult CDraggerBeam::BlocksSave(int ClientId)
{
return m_ForClientId == ClientId ? ESaveResult::DRAGGER_ACTIVE : ESaveResult::SUCCESS;
}

View file

@ -39,6 +39,7 @@ public:
void Tick() override; void Tick() override;
void Snap(int SnappingClient) override; void Snap(int SnappingClient) override;
void SwapClients(int Client1, int Client2) override; void SwapClients(int Client1, int Client2) override;
ESaveResult BlocksSave(int ClientId) override;
}; };
#endif // GAME_SERVER_ENTITIES_DRAGGER_BEAM_H #endif // GAME_SERVER_ENTITIES_DRAGGER_BEAM_H

View file

@ -8,6 +8,7 @@
#include <game/alloc.h> #include <game/alloc.h>
#include "gameworld.h" #include "gameworld.h"
#include "save.h"
class CCollision; class CCollision;
class CGameContext; class CGameContext;
@ -138,6 +139,15 @@ public: // TODO: Maybe make protected
*/ */
virtual void SwapClients(int Client1, int Client2) {} virtual void SwapClients(int Client1, int Client2) {}
/*
Function: BlocksSave
Called to check if a team can be saved
Arguments:
ClientId - Client ID
*/
virtual ESaveResult BlocksSave(int ClientId) { return ESaveResult::SUCCESS; }
/* /*
Function GetOwnerId Function GetOwnerId
Returns: Returns:

View file

@ -270,6 +270,21 @@ void CGameWorld::Tick()
} }
} }
ESaveResult CGameWorld::BlocksSave(int ClientId)
{
// check all objects
for(auto *pEnt : m_apFirstEntityTypes)
for(; pEnt;)
{
m_pNextTraverseEntity = pEnt->m_pNextTypeEntity;
ESaveResult Result = pEnt->BlocksSave(ClientId);
if(Result != ESaveResult::SUCCESS)
return Result;
pEnt = m_pNextTraverseEntity;
}
return ESaveResult::SUCCESS;
}
void CGameWorld::SwapClients(int Client1, int Client2) void CGameWorld::SwapClients(int Client1, int Client2)
{ {
// update all objects // update all objects

View file

@ -5,6 +5,8 @@
#include <game/gamecore.h> #include <game/gamecore.h>
#include "save.h"
#include <vector> #include <vector>
class CEntity; class CEntity;
@ -153,6 +155,12 @@ public:
*/ */
void SwapClients(int Client1, int Client2); void SwapClients(int Client1, int Client2);
/*
Function: BlocksSave
Checks if any entity would block /save
*/
ESaveResult BlocksSave(int ClientId);
// DDRace // DDRace
void ReleaseHooked(int ClientId); void ReleaseHooked(int ClientId);

View file

@ -490,30 +490,30 @@ CSaveTeam::~CSaveTeam()
delete[] m_pSavedTees; delete[] m_pSavedTees;
} }
int CSaveTeam::Save(CGameContext *pGameServer, int Team, bool Dry) ESaveResult CSaveTeam::Save(CGameContext *pGameServer, int Team, bool Dry)
{ {
if(g_Config.m_SvTeam != SV_TEAM_FORCED_SOLO && (Team <= 0 || MAX_CLIENTS <= Team)) if(g_Config.m_SvTeam != SV_TEAM_FORCED_SOLO && (Team <= 0 || MAX_CLIENTS <= Team))
return 1; return ESaveResult::TEAM_FLOCK;
IGameController *pController = pGameServer->m_pController; IGameController *pController = pGameServer->m_pController;
CGameTeams *pTeams = &pController->Teams(); CGameTeams *pTeams = &pController->Teams();
if(pTeams->TeamFlock(Team)) if(pTeams->TeamFlock(Team))
{ {
return 5; return ESaveResult::TEAM_0_MODE;
} }
m_MembersCount = pTeams->Count(Team); m_MembersCount = pTeams->Count(Team);
if(m_MembersCount <= 0) if(m_MembersCount <= 0)
{ {
return 2; return ESaveResult::TEAM_NOT_FOUND;
} }
m_TeamState = pTeams->GetTeamState(Team); m_TeamState = pTeams->GetTeamState(Team);
if(m_TeamState != CGameTeams::TEAMSTATE_STARTED) if(m_TeamState != CGameTeams::TEAMSTATE_STARTED)
{ {
return 4; return ESaveResult::NOT_STARTED;
} }
m_HighestSwitchNumber = pGameServer->Collision()->m_HighestSwitchNumber; m_HighestSwitchNumber = pGameServer->Collision()->m_HighestSwitchNumber;
@ -529,13 +529,16 @@ int CSaveTeam::Save(CGameContext *pGameServer, int Team, bool Dry)
if(pTeams->m_Core.Team(p->GetPlayer()->GetCid()) != Team) if(pTeams->m_Core.Team(p->GetPlayer()->GetCid()) != Team)
continue; continue;
if(m_MembersCount == j) if(m_MembersCount == j)
return 3; return ESaveResult::CHAR_NOT_FOUND;
ESaveResult Result = pGameServer->m_World.BlocksSave(p->GetPlayer()->GetCid());
if(Result != ESaveResult::SUCCESS)
return Result;
m_pSavedTees[j].Save(p); m_pSavedTees[j].Save(p);
aPlayerCids[j] = p->GetPlayer()->GetCid(); aPlayerCids[j] = p->GetPlayer()->GetCid();
j++; j++;
} }
if(m_MembersCount != j) if(m_MembersCount != j)
return 3; return ESaveResult::CHAR_NOT_FOUND;
if(pGameServer->Collision()->m_HighestSwitchNumber) if(pGameServer->Collision()->m_HighestSwitchNumber)
{ {
@ -555,32 +558,32 @@ int CSaveTeam::Save(CGameContext *pGameServer, int Team, bool Dry)
{ {
pGameServer->m_World.RemoveEntitiesFromPlayers(aPlayerCids, m_MembersCount); pGameServer->m_World.RemoveEntitiesFromPlayers(aPlayerCids, m_MembersCount);
} }
return 0; return ESaveResult::SUCCESS;
} }
bool CSaveTeam::HandleSaveError(int Result, int ClientId, CGameContext *pGameContext) bool CSaveTeam::HandleSaveError(ESaveResult Result, int ClientId, CGameContext *pGameContext)
{ {
switch(Result) switch(Result)
{ {
case 0: case ESaveResult::SUCCESS:
return false; return false;
case 1: case ESaveResult::TEAM_FLOCK:
pGameContext->SendChatTarget(ClientId, "You have to be in a team (from 1-63)"); pGameContext->SendChatTarget(ClientId, "You have to be in a team (from 1-63)");
break; break;
case 2: case ESaveResult::TEAM_NOT_FOUND:
pGameContext->SendChatTarget(ClientId, "Could not find your Team"); pGameContext->SendChatTarget(ClientId, "Could not find your Team");
break; break;
case 3: case ESaveResult::CHAR_NOT_FOUND:
pGameContext->SendChatTarget(ClientId, "To save all players in your team have to be alive and not in '/spec'"); pGameContext->SendChatTarget(ClientId, "To save all players in your team have to be alive and not in '/spec'");
break; break;
case 4: case ESaveResult::NOT_STARTED:
pGameContext->SendChatTarget(ClientId, "Your team has not started yet"); pGameContext->SendChatTarget(ClientId, "Your team has not started yet");
break; break;
case 5: case ESaveResult::TEAM_0_MODE:
pGameContext->SendChatTarget(ClientId, "Team can't be saved while in team 0 mode"); pGameContext->SendChatTarget(ClientId, "Team can't be saved while in team 0 mode");
break; break;
default: // this state should never be reached case ESaveResult::DRAGGER_ACTIVE:
pGameContext->SendChatTarget(ClientId, "Unknown error while saving"); pGameContext->SendChatTarget(ClientId, "Team can't be saved while a dragger is active");
break; break;
} }
return true; return true;

View file

@ -19,6 +19,17 @@ enum
NUM_RESCUEMODES NUM_RESCUEMODES
}; };
enum class ESaveResult
{
SUCCESS,
TEAM_FLOCK,
TEAM_NOT_FOUND,
CHAR_NOT_FOUND,
NOT_STARTED,
TEAM_0_MODE,
DRAGGER_ACTIVE
};
class CSaveTee class CSaveTee
{ {
public: public:
@ -148,13 +159,13 @@ public:
int FromString(const char *pString); int FromString(const char *pString);
// returns true if a team can load, otherwise writes a nice error Message in pMessage // returns true if a team can load, otherwise writes a nice error Message in pMessage
bool MatchPlayers(const char (*paNames)[MAX_NAME_LENGTH], const int *pClientId, int NumPlayer, char *pMessage, int MessageLen) const; bool MatchPlayers(const char (*paNames)[MAX_NAME_LENGTH], const int *pClientId, int NumPlayer, char *pMessage, int MessageLen) const;
int Save(CGameContext *pGameServer, int Team, bool Dry = false); ESaveResult Save(CGameContext *pGameServer, int Team, bool Dry = false);
bool Load(CGameContext *pGameServer, int Team, bool KeepCurrentWeakStrong); bool Load(CGameContext *pGameServer, int Team, bool KeepCurrentWeakStrong);
CSaveTee *m_pSavedTees = nullptr; CSaveTee *m_pSavedTees = nullptr;
// returns true if an error occurred // returns true if an error occurred
static bool HandleSaveError(int Result, int ClientId, CGameContext *pGameContext); static bool HandleSaveError(ESaveResult Result, int ClientId, CGameContext *pGameContext);
private: private:
CCharacter *MatchCharacter(CGameContext *pGameServer, int ClientId, int SaveId, bool KeepCurrentCharacter) const; CCharacter *MatchCharacter(CGameContext *pGameServer, int ClientId, int SaveId, bool KeepCurrentCharacter) const;

View file

@ -303,7 +303,7 @@ void CScore::SaveTeam(int ClientId, const char *pCode, const char *pServer)
auto SaveResult = std::make_shared<CScoreSaveResult>(ClientId); auto SaveResult = std::make_shared<CScoreSaveResult>(ClientId);
SaveResult->m_SaveId = RandomUuid(); SaveResult->m_SaveId = RandomUuid();
int Result = SaveResult->m_SavedTeam.Save(GameServer(), Team); ESaveResult Result = SaveResult->m_SavedTeam.Save(GameServer(), Team);
if(CSaveTeam::HandleSaveError(Result, ClientId, GameServer())) if(CSaveTeam::HandleSaveError(Result, ClientId, GameServer()))
return; return;
pController->Teams().SetSaving(Team, SaveResult); pController->Teams().SetSaving(Team, SaveResult);