Fix save/swap with draggers

This commit is contained in:
Dennis Felsing 2024-08-21 15:36:05 +02:00
parent 54271aef2a
commit f796309cc8
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;
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;

View file

@ -10,6 +10,7 @@
#include <game/mapitems.h>
#include <game/server/gamecontext.h>
#include <game/server/save.h>
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;
}

View file

@ -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

View file

@ -8,6 +8,7 @@
#include <game/alloc.h>
#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:

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)
{
// update all objects

View file

@ -5,6 +5,8 @@
#include <game/gamecore.h>
#include "save.h"
#include <vector>
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);

View file

@ -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;

View file

@ -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;

View file

@ -303,7 +303,7 @@ void CScore::SaveTeam(int ClientId, const char *pCode, const char *pServer)
auto SaveResult = std::make_shared<CScoreSaveResult>(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);