From f796309cc82e8d762d383070eadfb3e2ef945c7f Mon Sep 17 00:00:00 2001 From: Dennis Felsing Date: Wed, 21 Aug 2024 15:36:05 +0200 Subject: [PATCH] Fix save/swap with draggers --- src/game/server/ddracecommands.cpp | 2 +- src/game/server/entities/dragger_beam.cpp | 6 ++++ src/game/server/entities/dragger_beam.h | 1 + src/game/server/entity.h | 10 ++++++ src/game/server/gameworld.cpp | 15 +++++++++ src/game/server/gameworld.h | 8 +++++ src/game/server/save.cpp | 37 ++++++++++++----------- src/game/server/save.h | 15 +++++++-- src/game/server/score.cpp | 2 +- 9 files changed, 75 insertions(+), 21 deletions(-) diff --git a/src/game/server/ddracecommands.cpp b/src/game/server/ddracecommands.cpp index d595eac82..83ce130c8 100644 --- a/src/game/server/ddracecommands.cpp +++ b/src/game/server/ddracecommands.cpp @@ -870,7 +870,7 @@ void CGameContext::ConDrySave(IConsole::IResult *pResult, void *pUserData) CSaveTeam SavedTeam; 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)) return; diff --git a/src/game/server/entities/dragger_beam.cpp b/src/game/server/entities/dragger_beam.cpp index f4d198068..5dace37f6 100644 --- a/src/game/server/entities/dragger_beam.cpp +++ b/src/game/server/entities/dragger_beam.cpp @@ -10,6 +10,7 @@ #include #include +#include CDraggerBeam::CDraggerBeam(CGameWorld *pGameWorld, CDragger *pDragger, vec2 Pos, float Strength, bool IgnoreWalls, 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; } + +ESaveResult CDraggerBeam::BlocksSave(int ClientId) +{ + return m_ForClientId == ClientId ? ESaveResult::DRAGGER_ACTIVE : ESaveResult::SUCCESS; +} diff --git a/src/game/server/entities/dragger_beam.h b/src/game/server/entities/dragger_beam.h index cff7db57f..70249d1e8 100644 --- a/src/game/server/entities/dragger_beam.h +++ b/src/game/server/entities/dragger_beam.h @@ -39,6 +39,7 @@ public: void Tick() override; void Snap(int SnappingClient) override; void SwapClients(int Client1, int Client2) override; + ESaveResult BlocksSave(int ClientId) override; }; #endif // GAME_SERVER_ENTITIES_DRAGGER_BEAM_H diff --git a/src/game/server/entity.h b/src/game/server/entity.h index 03930b252..b3cf409bc 100644 --- a/src/game/server/entity.h +++ b/src/game/server/entity.h @@ -8,6 +8,7 @@ #include #include "gameworld.h" +#include "save.h" class CCollision; class CGameContext; @@ -138,6 +139,15 @@ public: // TODO: Maybe make protected */ 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 Returns: diff --git a/src/game/server/gameworld.cpp b/src/game/server/gameworld.cpp index 4e9d90aa4..5f4229081 100644 --- a/src/game/server/gameworld.cpp +++ b/src/game/server/gameworld.cpp @@ -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) { // update all objects diff --git a/src/game/server/gameworld.h b/src/game/server/gameworld.h index 15f338a2e..758f23203 100644 --- a/src/game/server/gameworld.h +++ b/src/game/server/gameworld.h @@ -5,6 +5,8 @@ #include +#include "save.h" + #include class CEntity; @@ -153,6 +155,12 @@ public: */ void SwapClients(int Client1, int Client2); + /* + Function: BlocksSave + Checks if any entity would block /save + */ + ESaveResult BlocksSave(int ClientId); + // DDRace void ReleaseHooked(int ClientId); diff --git a/src/game/server/save.cpp b/src/game/server/save.cpp index f4f07a407..cec79c946 100644 --- a/src/game/server/save.cpp +++ b/src/game/server/save.cpp @@ -490,30 +490,30 @@ CSaveTeam::~CSaveTeam() 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)) - return 1; + return ESaveResult::TEAM_FLOCK; IGameController *pController = pGameServer->m_pController; CGameTeams *pTeams = &pController->Teams(); if(pTeams->TeamFlock(Team)) { - return 5; + return ESaveResult::TEAM_0_MODE; } m_MembersCount = pTeams->Count(Team); if(m_MembersCount <= 0) { - return 2; + return ESaveResult::TEAM_NOT_FOUND; } m_TeamState = pTeams->GetTeamState(Team); if(m_TeamState != CGameTeams::TEAMSTATE_STARTED) { - return 4; + return ESaveResult::NOT_STARTED; } 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) continue; 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); aPlayerCids[j] = p->GetPlayer()->GetCid(); j++; } if(m_MembersCount != j) - return 3; + return ESaveResult::CHAR_NOT_FOUND; 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); } - 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) { - case 0: + case ESaveResult::SUCCESS: return false; - case 1: + case ESaveResult::TEAM_FLOCK: pGameContext->SendChatTarget(ClientId, "You have to be in a team (from 1-63)"); break; - case 2: + case ESaveResult::TEAM_NOT_FOUND: pGameContext->SendChatTarget(ClientId, "Could not find your Team"); 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'"); break; - case 4: + case ESaveResult::NOT_STARTED: pGameContext->SendChatTarget(ClientId, "Your team has not started yet"); break; - case 5: + case ESaveResult::TEAM_0_MODE: pGameContext->SendChatTarget(ClientId, "Team can't be saved while in team 0 mode"); break; - default: // this state should never be reached - pGameContext->SendChatTarget(ClientId, "Unknown error while saving"); + case ESaveResult::DRAGGER_ACTIVE: + pGameContext->SendChatTarget(ClientId, "Team can't be saved while a dragger is active"); break; } return true; diff --git a/src/game/server/save.h b/src/game/server/save.h index 145dbf25c..c60a78072 100644 --- a/src/game/server/save.h +++ b/src/game/server/save.h @@ -19,6 +19,17 @@ enum NUM_RESCUEMODES }; +enum class ESaveResult +{ + SUCCESS, + TEAM_FLOCK, + TEAM_NOT_FOUND, + CHAR_NOT_FOUND, + NOT_STARTED, + TEAM_0_MODE, + DRAGGER_ACTIVE +}; + class CSaveTee { public: @@ -148,13 +159,13 @@ public: int FromString(const char *pString); // 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; - 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); CSaveTee *m_pSavedTees = nullptr; // 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: CCharacter *MatchCharacter(CGameContext *pGameServer, int ClientId, int SaveId, bool KeepCurrentCharacter) const; diff --git a/src/game/server/score.cpp b/src/game/server/score.cpp index 60d0efc8c..80e5c6c27 100644 --- a/src/game/server/score.cpp +++ b/src/game/server/score.cpp @@ -303,7 +303,7 @@ void CScore::SaveTeam(int ClientId, const char *pCode, const char *pServer) auto SaveResult = std::make_shared(ClientId); 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())) return; pController->Teams().SetSaving(Team, SaveResult);