Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make the engine oblivious of the data passed between map reloads #2066 #21

Open
wants to merge 1 commit into
base: community
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 18 additions & 2 deletions src/engine/server.h
Original file line number Diff line number Diff line change
Expand Up @@ -85,15 +85,31 @@ class IGameServer : public IInterface

virtual void OnMessage(int MsgID, CUnpacker *pUnpacker, int ClientID) = 0;

virtual void OnClientConnected(int ClientID, bool AsSpec) = 0;
// Called before map reload, for any data that the game wants to
// persist to the next map.
//
// Has the size of the return value of `PersistentClientDataSize()`.
//
// Returns whether the game should be supplied with the data when the
// client connects for the next map.
virtual bool OnClientDataPersist(int ClientID, void *pData) = 0;

// Called when a client connects.
//
// If it is reconnecting to the game after a map change, the
// `pPersistentData` point is nonnull and contains the data the game
// previously stored.
virtual void OnClientConnected(int ClientID, void *pPersistentData) = 0;

virtual void OnClientEnter(int ClientID) = 0;
virtual void OnClientDrop(int ClientID, const char *pReason) = 0;
virtual void OnClientDirectInput(int ClientID, void *pInput) = 0;
virtual void OnClientPredictedInput(int ClientID, void *pInput) = 0;

virtual bool IsClientReady(int ClientID) const = 0;
virtual bool IsClientPlayer(int ClientID) const = 0;
virtual bool IsClientSpectator(int ClientID) const = 0;

virtual int PersistentClientDataSize() const = 0;

virtual const char *GameType() const = 0;
virtual const char *Version() const = 0;
Expand Down
38 changes: 30 additions & 8 deletions src/engine/server/server.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,7 @@ void CServer::CClient::Reset()
m_SnapRate = CClient::SNAPRATE_INIT;
m_Score = 0;
m_MapChunk = 0;
m_HasPersistentData = false;
}

CServer::CServer() : m_DemoRecorder(&m_SnapshotDelta)
Expand Down Expand Up @@ -858,7 +859,7 @@ void CServer::ProcessClientPacket(CNetChunk *pPacket)
}
else if(Msg == NETMSG_REQUEST_MAP_DATA)
{
if((pPacket->m_Flags&NET_CHUNKFLAG_VITAL) == 0 || m_aClients[ClientID].m_State == CClient::STATE_CONNECTING || m_aClients[ClientID].m_State == CClient::STATE_CONNECTING_AS_SPEC)
if((pPacket->m_Flags&NET_CHUNKFLAG_VITAL) == 0 || m_aClients[ClientID].m_State == CClient::STATE_CONNECTING)
{
int ChunkSize = MAP_CHUNK_SIZE;

Expand Down Expand Up @@ -892,7 +893,7 @@ void CServer::ProcessClientPacket(CNetChunk *pPacket)
}
else if(Msg == NETMSG_READY)
{
if((pPacket->m_Flags&NET_CHUNKFLAG_VITAL) != 0 && (m_aClients[ClientID].m_State == CClient::STATE_CONNECTING || m_aClients[ClientID].m_State == CClient::STATE_CONNECTING_AS_SPEC))
if((pPacket->m_Flags&NET_CHUNKFLAG_VITAL) != 0 && (m_aClients[ClientID].m_State == CClient::STATE_CONNECTING))
{
char aAddrStr[NETADDR_MAXSTRSIZE];
net_addr_str(m_NetServer.ClientAddr(ClientID), aAddrStr, sizeof(aAddrStr), true);
Expand All @@ -901,9 +902,14 @@ void CServer::ProcessClientPacket(CNetChunk *pPacket)
str_format(aBuf, sizeof(aBuf), "player is ready. ClientID=%x addr=%s", ClientID, aAddrStr);
Console()->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "server", aBuf);

bool ConnectAsSpec = m_aClients[ClientID].m_State == CClient::STATE_CONNECTING_AS_SPEC;
void *pPersistentData = 0;
if(m_aClients[ClientID].m_HasPersistentData)
{
pPersistentData = m_aClients[ClientID].m_pPersistentData;
m_aClients[ClientID].m_HasPersistentData = false;
}
m_aClients[ClientID].m_State = CClient::STATE_READY;
GameServer()->OnClientConnected(ClientID, ConnectAsSpec);
GameServer()->OnClientConnected(ClientID, pPersistentData);
SendConnectionReady(ClientID);
}
}
Expand Down Expand Up @@ -1281,6 +1287,14 @@ int CServer::Run()
//
m_PrintCBIndex = Console()->RegisterPrintCallback(g_Config.m_ConsoleOutputLevel, SendRconLineAuthed, this);

{
int Size = GameServer()->PersistentClientDataSize();
for(int i = 0; i < MAX_CLIENTS; i++)
{
m_aClients[i].m_pPersistentData = mem_alloc(Size, 1);
}
}

// list maps
m_pMapListHeap = new CHeap();
CSubdirCallbackUserdata Userdata;
Expand Down Expand Up @@ -1361,9 +1375,15 @@ int CServer::Run()
if(LoadMap(g_Config.m_SvMap))
{
// new map loaded
bool aSpecs[MAX_CLIENTS];
for(int c = 0; c < MAX_CLIENTS; c++)
aSpecs[c] = GameServer()->IsClientSpectator(c);

// ask the game to for the data it wants to persist past a map change
for(int i = 0; i < MAX_CLIENTS; i++)
{
if(m_aClients[i].m_State == CClient::STATE_INGAME)
{
m_aClients[i].m_HasPersistentData = GameServer()->OnClientDataPersist(i, m_aClients[i].m_pPersistentData);
}
}

GameServer()->OnShutdown();

Expand All @@ -1373,8 +1393,10 @@ int CServer::Run()
continue;

SendMap(c);
bool HasPersistentData = m_aClients[c].m_HasPersistentData;
m_aClients[c].Reset();
m_aClients[c].m_State = aSpecs[c] ? CClient::STATE_CONNECTING_AS_SPEC : CClient::STATE_CONNECTING;
m_aClients[c].m_HasPersistentData = HasPersistentData;
m_aClients[c].m_State = CClient::STATE_CONNECTING;
}

m_GameStartTime = time_get();
Expand Down
4 changes: 3 additions & 1 deletion src/engine/server/server.h
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,6 @@ class CServer : public IServer
STATE_EMPTY = 0,
STATE_AUTH,
STATE_CONNECTING,
STATE_CONNECTING_AS_SPEC,
STATE_READY,
STATE_INGAME,

Expand Down Expand Up @@ -135,6 +134,9 @@ class CServer : public IServer
const IConsole::CCommandInfo *m_pRconCmdToSend;
const CMapListEntry *m_pMapListEntryToSend;

bool m_HasPersistentData;
void *m_pPersistentData;

void Reset();
};

Expand Down
27 changes: 19 additions & 8 deletions src/game/server/gamecontext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -656,9 +656,25 @@ void CGameContext::OnClientEnter(int ClientID)
}
}

void CGameContext::OnClientConnected(int ClientID, bool Dummy, bool AsSpec)
bool CGameContext::OnClientDataPersist(int ClientID, void *pData)
{
m_apPlayers[ClientID] = new(ClientID) CPlayer(this, ClientID, Dummy, AsSpec);
CPersistentClientData *pPersistent = (CPersistentClientData *)pData;
if(!m_apPlayers[ClientID])
{
return false;
}
pPersistent->m_IsSpectator = m_apPlayers[ClientID]->GetTeam() == TEAM_SPECTATORS;
return true;
}

void CGameContext::OnClientConnected(int ClientID, bool Dummy, CPersistentClientData *pPersistent)
{
bool Spec = false;
if(pPersistent)
{
Spec = pPersistent->m_IsSpectator;
}
m_apPlayers[ClientID] = new(ClientID) CPlayer(this, ClientID, Dummy, Spec);

if(Dummy)
return;
Expand Down Expand Up @@ -1482,7 +1498,7 @@ void CGameContext::OnInit()
if(g_Config.m_DbgDummies)
{
for(int i = 0; i < g_Config.m_DbgDummies ; i++)
OnClientConnected(Server()->MaxClients() -i-1, true);
OnClientConnected(Server()->MaxClients() -i-1, true, 0);
}
#endif
}
Expand Down Expand Up @@ -1534,11 +1550,6 @@ bool CGameContext::IsClientPlayer(int ClientID) const
return m_apPlayers[ClientID] && m_apPlayers[ClientID]->GetTeam() != TEAM_SPECTATORS;
}

bool CGameContext::IsClientSpectator(int ClientID) const
{
return m_apPlayers[ClientID] && m_apPlayers[ClientID]->GetTeam() == TEAM_SPECTATORS;
}

const char *CGameContext::GameType() const { return m_pController && m_pController->GetGameType() ? m_pController->GetGameType() : ""; }
const char *CGameContext::Version() const { return GAME_VERSION; }
const char *CGameContext::NetVersion() const { return GAME_NETVERSION; }
Expand Down
13 changes: 10 additions & 3 deletions src/game/server/gamecontext.h
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,12 @@ class CGameContext : public IGameServer
void Construct(int Resetting);

bool m_Resetting;

struct CPersistentClientData
{
bool m_IsSpectator;
};

public:
IServer *Server() const { return m_pServer; }
class IConsole *Console() { return m_pConsole; }
Expand Down Expand Up @@ -163,8 +169,9 @@ class CGameContext : public IGameServer

virtual void OnMessage(int MsgID, CUnpacker *pUnpacker, int ClientID);

virtual void OnClientConnected(int ClientID, bool AsSpec) { OnClientConnected(ClientID, false, AsSpec); }
void OnClientConnected(int ClientID, bool Dummy, bool AsSpec);
virtual bool OnClientDataPersist(int ClientID, void *pData);
virtual void OnClientConnected(int ClientID, void *pPersistentData) { OnClientConnected(ClientID, false, (CPersistentClientData *)pPersistentData); }
void OnClientConnected(int ClientID, bool Dummy, CPersistentClientData *pPersistent);
void OnClientTeamChange(int ClientID);
virtual void OnClientEnter(int ClientID);
virtual void OnClientDrop(int ClientID, const char *pReason);
Expand All @@ -173,7 +180,7 @@ class CGameContext : public IGameServer

virtual bool IsClientReady(int ClientID) const;
virtual bool IsClientPlayer(int ClientID) const;
virtual bool IsClientSpectator(int ClientID) const;
virtual int PersistentClientDataSize() const { return sizeof(CPersistentClientData); }

virtual const char *GameType() const;
virtual const char *Version() const;
Expand Down
4 changes: 2 additions & 2 deletions src/game/server/player.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,15 @@ MACRO_ALLOC_POOL_ID_IMPL(CPlayer, MAX_CLIENTS)

IServer *CPlayer::Server() const { return m_pGameServer->Server(); }

CPlayer::CPlayer(CGameContext *pGameServer, int ClientID, bool Dummy, bool AsSpec)
CPlayer::CPlayer(CGameContext *pGameServer, int ClientID, bool Dummy, bool Spec)
{
m_pGameServer = pGameServer;
m_RespawnTick = Server()->Tick();
m_DieTick = Server()->Tick();
m_ScoreStartTick = Server()->Tick();
m_pCharacter = 0;
m_ClientID = ClientID;
m_Team = AsSpec ? TEAM_SPECTATORS : GameServer()->m_pController->GetStartTeam();
m_Team = Spec ? TEAM_SPECTATORS : GameServer()->m_pController->GetStartTeam();
m_SpecMode = SPEC_FREEVIEW;
m_SpectatorID = -1;
m_pSpecFlag = 0;
Expand Down
2 changes: 1 addition & 1 deletion src/game/server/player.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ class CPlayer
MACRO_ALLOC_POOL_ID()

public:
CPlayer(CGameContext *pGameServer, int ClientID, bool Dummy, bool AsSpec = false);
CPlayer(CGameContext *pGameServer, int ClientID, bool Dummy, bool Spec);
~CPlayer();

void Init(int CID);
Expand Down