4623: Refactor: Distinguish between two concepts previously called "Dummy" r=def- a=heinrich5991

On the one hand variables called "Dummy" would tell us whether the
current action refers to the currently inactive tee ("dummy"). On the
other hand, these variables could tell us whether the current action
refers to the main connection to the server, or the secondary one. The
latter use case is now renamed to "Client", with the choices
`CLIENT_MAIN`, `CLIENT_DUMMY` (and `CLIENT_CONTACT`).

Perhaps better names could be found, especially since `Client` also
refers to the engine client class in the game code.

Also fix a few bugs in dummy handling.

## Checklist

- [x] Tested the change ingame
- [ ] Provided screenshots if it is a visual change
- [ ] Tested in combination with possibly related configuration options
- [ ] Written a unit test if it works standalone, system.c especially
- [ ] 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: heinrich5991 <heinrich5991@gmail.com>
This commit is contained in:
bors[bot] 2022-01-21 21:26:21 +00:00 committed by GitHub
commit 623d8af04c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 209 additions and 458 deletions

View file

@ -62,6 +62,14 @@ public:
int m_DataSize;
};
enum
{
CONN_MAIN = 0,
CONN_DUMMY,
CONN_CONTACT,
NUM_CONNS,
};
/* Constants: Client States
STATE_OFFLINE - The client is offline.
STATE_CONNECTING - The client is trying to connect to a server.
@ -86,13 +94,13 @@ public:
inline int State() const { return m_State; }
// tick time access
inline int PrevGameTick(int Dummy) const { return m_PrevGameTick[Dummy]; }
inline int GameTick(int Dummy) const { return m_CurGameTick[Dummy]; }
inline int PredGameTick(int Dummy) const { return m_PredTick[Dummy]; }
inline float IntraGameTick(int Dummy) const { return m_GameIntraTick[Dummy]; }
inline float PredIntraGameTick(int Dummy) const { return m_PredIntraTick[Dummy]; }
inline float IntraGameTickSincePrev(int Dummy) const { return m_GameIntraTickSincePrev[Dummy]; }
inline float GameTickTime(int Dummy) const { return m_GameTickTime[Dummy]; }
inline int PrevGameTick(int Conn) const { return m_PrevGameTick[Conn]; }
inline int GameTick(int Conn) const { return m_CurGameTick[Conn]; }
inline int PredGameTick(int Conn) const { return m_PredTick[Conn]; }
inline float IntraGameTick(int Conn) const { return m_GameIntraTick[Conn]; }
inline float PredIntraGameTick(int Conn) const { return m_PredIntraTick[Conn]; }
inline float IntraGameTickSincePrev(int Conn) const { return m_GameIntraTickSincePrev[Conn]; }
inline float GameTickTime(int Conn) const { return m_GameTickTime[Conn]; }
inline int GameTickSpeed() const { return m_GameTickSpeed; }
// other time access
@ -134,7 +142,7 @@ public:
virtual void Notify(const char *pTitle, const char *pMessage) = 0;
// networking
virtual void EnterGame(bool Dummy) = 0;
virtual void EnterGame(int Conn) = 0;
//
virtual const char *MapDownloadName() const = 0;
@ -173,16 +181,16 @@ public:
virtual void SnapSetStaticsize(int ItemType, int Size) = 0;
virtual int SendMsg(CMsgPacker *pMsg, int Flags) = 0;
virtual int SendMsgY(CMsgPacker *pMsg, int Flags, int NetClient = 1) = 0;
virtual int SendMsg(int Conn, CMsgPacker *pMsg, int Flags) = 0;
virtual int SendMsgActive(CMsgPacker *pMsg, int Flags) = 0;
template<class T>
int SendPackMsg(T *pMsg, int Flags)
int SendPackMsgActive(T *pMsg, int Flags)
{
CMsgPacker Packer(pMsg->MsgID(), false);
if(pMsg->Pack(&Packer))
return -1;
return SendMsg(&Packer, Flags);
return SendMsgActive(&Packer, Flags);
}
//
@ -243,7 +251,7 @@ public:
virtual void OnUpdate() = 0;
virtual void OnStateChange(int NewState, int OldState) = 0;
virtual void OnConnected() = 0;
virtual void OnMessage(int MsgID, CUnpacker *pUnpacker, bool Dummy = 0) = 0;
virtual void OnMessage(int MsgID, CUnpacker *pUnpacker, int Conn, bool Dummy) = 0;
virtual void OnPredict() = 0;
virtual void OnActivateEditor() = 0;

View file

@ -422,7 +422,7 @@ static inline bool RepackMsg(const CMsgPacker *pMsg, CPacker &Packer)
return false;
}
int CClient::SendMsg(CMsgPacker *pMsg, int Flags)
int CClient::SendMsg(int Conn, CMsgPacker *pMsg, int Flags)
{
CNetChunk Packet;
@ -444,7 +444,7 @@ int CClient::SendMsg(CMsgPacker *pMsg, int Flags)
if(Flags & MSGFLAG_FLUSH)
Packet.m_Flags |= NETSENDFLAG_FLUSH;
if(Flags & MSGFLAG_RECORD)
if((Flags & MSGFLAG_RECORD) && Conn == g_Config.m_ClDummy)
{
for(auto &i : m_DemoRecorder)
if(i.IsRecording())
@ -453,36 +453,41 @@ int CClient::SendMsg(CMsgPacker *pMsg, int Flags)
if(!(Flags & MSGFLAG_NOSEND))
{
m_NetClient[g_Config.m_ClDummy].Send(&Packet);
m_NetClient[Conn].Send(&Packet);
}
return 0;
}
int CClient::SendMsgActive(CMsgPacker *pMsg, int Flags)
{
return SendMsg(g_Config.m_ClDummy, pMsg, Flags);
}
void CClient::SendInfo()
{
CMsgPacker MsgVer(NETMSG_CLIENTVER, true);
MsgVer.AddRaw(&m_ConnectionID, sizeof(m_ConnectionID));
MsgVer.AddInt(GameClient()->DDNetVersion());
MsgVer.AddString(GameClient()->DDNetVersionStr(), 0);
SendMsg(&MsgVer, MSGFLAG_VITAL);
SendMsg(CONN_MAIN, &MsgVer, MSGFLAG_VITAL);
CMsgPacker Msg(NETMSG_INFO, true);
Msg.AddString(GameClient()->NetVersion(), 128);
Msg.AddString(m_Password, 128);
SendMsg(&Msg, MSGFLAG_VITAL | MSGFLAG_FLUSH);
SendMsg(CONN_MAIN, &Msg, MSGFLAG_VITAL | MSGFLAG_FLUSH);
}
void CClient::SendEnterGame(bool Dummy)
void CClient::SendEnterGame(int Conn)
{
CMsgPacker Msg(NETMSG_ENTERGAME, true);
SendMsgY(&Msg, MSGFLAG_VITAL | MSGFLAG_FLUSH, Dummy);
SendMsg(Conn, &Msg, MSGFLAG_VITAL | MSGFLAG_FLUSH);
}
void CClient::SendReady()
{
CMsgPacker Msg(NETMSG_READY, true);
SendMsg(&Msg, MSGFLAG_VITAL | MSGFLAG_FLUSH);
SendMsg(CONN_MAIN, &Msg, MSGFLAG_VITAL | MSGFLAG_FLUSH);
}
void CClient::SendMapRequest()
@ -495,7 +500,7 @@ void CClient::SendMapRequest()
m_MapdownloadFileTemp = Storage()->OpenFile(m_aMapdownloadFilenameTemp, IOFLAG_WRITE, IStorage::TYPE_SAVE);
CMsgPacker Msg(NETMSG_REQUEST_MAP_DATA, true);
Msg.AddInt(m_MapdownloadChunk);
SendMsg(&Msg, MSGFLAG_VITAL | MSGFLAG_FLUSH);
SendMsg(CONN_MAIN, &Msg, MSGFLAG_VITAL | MSGFLAG_FLUSH);
}
void CClient::RconAuth(const char *pName, const char *pPassword)
@ -510,14 +515,14 @@ void CClient::RconAuth(const char *pName, const char *pPassword)
Msg.AddString(pName, 32);
Msg.AddString(pPassword, 32);
Msg.AddInt(1);
SendMsg(&Msg, MSGFLAG_VITAL);
SendMsgActive(&Msg, MSGFLAG_VITAL);
}
void CClient::Rcon(const char *pCmd)
{
CMsgPacker Msg(NETMSG_RCON_CMD, true);
Msg.AddString(pCmd, 256);
SendMsg(&Msg, MSGFLAG_VITAL);
SendMsgActive(&Msg, MSGFLAG_VITAL);
}
bool CClient::ConnectionProblems() const
@ -535,7 +540,7 @@ void CClient::DirectInput(int *pInput, int Size)
for(int i = 0; i < Size / 4; i++)
Msg.AddInt(pInput[i]);
SendMsg(&Msg, 0);
SendMsgActive(&Msg, 0);
}
void CClient::SendInput()
@ -576,7 +581,7 @@ void CClient::SendInput()
m_CurrentInput[i]++;
m_CurrentInput[i] %= 200;
SendMsgY(&Msg, MSGFLAG_FLUSH, i);
SendMsg(i, &Msg, MSGFLAG_FLUSH);
// ugly workaround for dummy. we need to send input with dummy to prevent
// prediction time resets. but if we do it too often, then it's
// impossible to use grenade with frozen dummy that gets hammered...
@ -685,17 +690,17 @@ void CClient::OnEnterGame(bool Dummy)
GameClient()->OnEnterGame();
}
void CClient::EnterGame(bool Dummy)
void CClient::EnterGame(int Conn)
{
if(State() == IClient::STATE_DEMOPLAYBACK)
return;
m_CodeRunAfterJoin[Dummy] = false;
m_CodeRunAfterJoin[Conn] = false;
// now we will wait for two snapshots
// to finish the connection
SendEnterGame(Dummy);
OnEnterGame(Dummy);
SendEnterGame(Conn);
OnEnterGame(Conn);
ServerInfoRequest(); // fresh one for timeout protection
m_CurrentServerNextPingTime = time_get() + time_freq() / 2;
@ -762,12 +767,12 @@ void CClient::Connect(const char *pAddress, const char *pPassword)
}
ServerInfoRequest();
if(net_host_lookup(m_aServerAddressStr, &m_ServerAddress, m_NetClient[CLIENT_MAIN].NetType()) != 0)
if(net_host_lookup(m_aServerAddressStr, &m_ServerAddress, m_NetClient[CONN_MAIN].NetType()) != 0)
{
char aBufMsg[256];
str_format(aBufMsg, sizeof(aBufMsg), "could not find the address of %s, connecting to localhost", aBuf);
m_pConsole->Print(IConsole::OUTPUT_LEVEL_STANDARD, "client", aBufMsg);
net_host_lookup("localhost", &m_ServerAddress, m_NetClient[CLIENT_MAIN].NetType());
net_host_lookup("localhost", &m_ServerAddress, m_NetClient[CONN_MAIN].NetType());
}
if(m_SendPassword)
@ -792,7 +797,7 @@ void CClient::Connect(const char *pAddress, const char *pPassword)
{
m_ServerAddress.type = NETTYPE_WEBSOCKET_IPV4;
}
m_NetClient[CLIENT_MAIN].Connect(&m_ServerAddress);
m_NetClient[CONN_MAIN].Connect(&m_ServerAddress);
SetState(IClient::STATE_CONNECTING);
for(int i = 0; i < RECORDER_MAX; i++)
@ -821,7 +826,7 @@ void CClient::DisconnectWithReason(const char *pReason)
m_ServerSentCapabilities = false;
m_UseTempRconCommands = 0;
m_pConsole->DeregisterTempAll();
m_NetClient[CLIENT_MAIN].Disconnect(pReason);
m_NetClient[CONN_MAIN].Disconnect(pReason);
SetState(IClient::STATE_OFFLINE);
m_pMap->Unload();
m_CurrentServerPingInfoType = -1;
@ -888,7 +893,7 @@ void CClient::DummyConnect()
if(m_LastDummyConnectTime > 0 && m_LastDummyConnectTime + GameTickSpeed() * 5 > GameTick(g_Config.m_ClDummy))
return;
if(m_NetClient[CLIENT_MAIN].State() != NET_CONNSTATE_ONLINE && m_NetClient[CLIENT_MAIN].State() != NET_CONNSTATE_PENDING)
if(m_NetClient[CONN_MAIN].State() != NET_CONNSTATE_ONLINE && m_NetClient[CONN_MAIN].State() != NET_CONNSTATE_PENDING)
return;
if(m_DummyConnected || !DummyAllowed())
@ -904,7 +909,7 @@ void CClient::DummyConnect()
g_Config.m_ClDummyHammer = 0;
//connecting to the server
m_NetClient[CLIENT_DUMMY].Connect(&m_ServerAddress);
m_NetClient[CONN_DUMMY].Connect(&m_ServerAddress);
}
void CClient::DummyDisconnect(const char *pReason)
@ -912,7 +917,7 @@ void CClient::DummyDisconnect(const char *pReason)
if(!m_DummyConnected)
return;
m_NetClient[CLIENT_DUMMY].Disconnect(pReason);
m_NetClient[CONN_DUMMY].Disconnect(pReason);
g_Config.m_ClDummy = 0;
m_RconAuthed[1] = 0;
m_aSnapshots[1][SNAP_CURRENT] = 0;
@ -934,29 +939,6 @@ int CClient::GetCurrentRaceTime()
return (GameTick(g_Config.m_ClDummy) - GameClient()->GetLastRaceTick()) / 50;
}
int CClient::SendMsgY(CMsgPacker *pMsg, int Flags, int NetClient)
{
CNetChunk Packet;
// repack message (inefficient)
CPacker Pack;
if(RepackMsg(pMsg, Pack))
return 0;
mem_zero(&Packet, sizeof(CNetChunk));
Packet.m_ClientID = 0;
Packet.m_pData = Pack.Data();
Packet.m_DataSize = Pack.Size();
if(Flags & MSGFLAG_VITAL)
Packet.m_Flags |= NETSENDFLAG_VITAL;
if(Flags & MSGFLAG_FLUSH)
Packet.m_Flags |= NETSENDFLAG_FLUSH;
m_NetClient[NetClient].Send(&Packet);
return 0;
}
void CClient::GetServerInfo(CServerInfo *pServerInfo) const
{
mem_copy(pServerInfo, &m_CurrentServerInfo, sizeof(m_CurrentServerInfo));
@ -1175,7 +1157,7 @@ const char *CClient::DummyName() const
const char *CClient::ErrorString() const
{
return m_NetClient[CLIENT_MAIN].ErrorString();
return m_NetClient[CONN_MAIN].ErrorString();
}
void CClient::Render()
@ -1597,7 +1579,7 @@ static CServerCapabilities GetServerCapabilities(int Version, int Flags)
return Result;
}
void CClient::ProcessServerPacket(CNetChunk *pPacket)
void CClient::ProcessServerPacket(CNetChunk *pPacket, int Conn, bool Dummy)
{
CUnpacker Unpacker;
Unpacker.Reset(pPacket->m_pData, pPacket->m_DataSize);
@ -1615,13 +1597,13 @@ void CClient::ProcessServerPacket(CNetChunk *pPacket)
}
else if(Result == UNPACKMESSAGE_ANSWER)
{
SendMsg(&Packer, MSGFLAG_VITAL);
SendMsg(Conn, &Packer, MSGFLAG_VITAL);
}
if(Sys)
{
// system message
if((pPacket->m_Flags & NET_CHUNKFLAG_VITAL) != 0 && Msg == NETMSG_MAP_DETAILS)
if(!Dummy && (pPacket->m_Flags & NET_CHUNKFLAG_VITAL) != 0 && Msg == NETMSG_MAP_DETAILS)
{
const char *pMap = Unpacker.GetString(CUnpacker::SANITIZE_CC | CUnpacker::SKIP_START_WHITESPACES);
SHA256_DIGEST *pMapSha256 = (SHA256_DIGEST *)Unpacker.GetRaw(sizeof(*pMapSha256));
@ -1637,7 +1619,7 @@ void CClient::ProcessServerPacket(CNetChunk *pPacket)
m_MapDetailsSha256 = *pMapSha256;
m_MapDetailsCrc = MapCrc;
}
else if((pPacket->m_Flags & NET_CHUNKFLAG_VITAL) != 0 && Msg == NETMSG_CAPABILITIES)
else if(!Dummy && (pPacket->m_Flags & NET_CHUNKFLAG_VITAL) != 0 && Msg == NETMSG_CAPABILITIES)
{
if(!m_CanReceiveServerCapabilities)
{
@ -1653,7 +1635,7 @@ void CClient::ProcessServerPacket(CNetChunk *pPacket)
m_CanReceiveServerCapabilities = false;
m_ServerSentCapabilities = true;
}
else if((pPacket->m_Flags & NET_CHUNKFLAG_VITAL) != 0 && Msg == NETMSG_MAP_CHANGE)
else if(!Dummy && (pPacket->m_Flags & NET_CHUNKFLAG_VITAL) != 0 && Msg == NETMSG_MAP_CHANGE)
{
if(m_CanReceiveServerCapabilities)
{
@ -1742,7 +1724,7 @@ void CClient::ProcessServerPacket(CNetChunk *pPacket)
}
}
}
else if(Msg == NETMSG_MAP_DATA)
else if(!Dummy && Msg == NETMSG_MAP_DATA)
{
int Last = Unpacker.GetInt();
int MapCRC = Unpacker.GetInt();
@ -1774,7 +1756,7 @@ void CClient::ProcessServerPacket(CNetChunk *pPacket)
CMsgPacker Msg(NETMSG_REQUEST_MAP_DATA, true);
Msg.AddInt(m_MapdownloadChunk);
SendMsg(&Msg, MSGFLAG_VITAL | MSGFLAG_FLUSH);
SendMsg(CONN_MAIN, &Msg, MSGFLAG_VITAL | MSGFLAG_FLUSH);
if(g_Config.m_Debug)
{
@ -1784,14 +1766,22 @@ void CClient::ProcessServerPacket(CNetChunk *pPacket)
}
}
}
else if((pPacket->m_Flags & NET_CHUNKFLAG_VITAL) != 0 && Msg == NETMSG_CON_READY)
else if(!Dummy && (pPacket->m_Flags & NET_CHUNKFLAG_VITAL) != 0 && Msg == NETMSG_CON_READY)
{
GameClient()->OnConnected();
}
else if(Dummy && Msg == NETMSG_CON_READY)
{
m_DummyConnected = true;
g_Config.m_ClDummy = 1;
Rcon("crashmeplx");
if(m_RconAuthed[0])
RconAuth("", m_RconPassword);
}
else if(Msg == NETMSG_PING)
{
CMsgPacker Msg(NETMSG_PING_REPLY, true);
SendMsg(&Msg, 0);
SendMsg(Conn, &Msg, 0);
}
else if(Msg == NETMSG_PINGEX)
{
@ -1802,9 +1792,9 @@ void CClient::ProcessServerPacket(CNetChunk *pPacket)
}
CMsgPacker Msg(NETMSG_PONGEX, true);
Msg.AddRaw(pID, sizeof(*pID));
SendMsg(&Msg, MSGFLAG_FLUSH);
SendMsg(Conn, &Msg, MSGFLAG_FLUSH);
}
else if(Msg == NETMSG_PONGEX)
else if(Conn == CONN_MAIN && Msg == NETMSG_PONGEX)
{
CUuid *pID = (CUuid *)Unpacker.GetRaw(sizeof(*pID));
if(Unpacker.Error())
@ -1822,31 +1812,25 @@ void CClient::ProcessServerPacket(CNetChunk *pPacket)
m_pConsole->Print(IConsole::OUTPUT_LEVEL_STANDARD, "client", aBuf);
}
}
else if((pPacket->m_Flags & NET_CHUNKFLAG_VITAL) != 0 && Msg == NETMSG_RCON_CMD_ADD)
else if(!Dummy && (pPacket->m_Flags & NET_CHUNKFLAG_VITAL) != 0 && Msg == NETMSG_RCON_CMD_ADD)
{
if(!g_Config.m_ClDummy)
{
const char *pName = Unpacker.GetString(CUnpacker::SANITIZE_CC);
const char *pHelp = Unpacker.GetString(CUnpacker::SANITIZE_CC);
const char *pParams = Unpacker.GetString(CUnpacker::SANITIZE_CC);
if(Unpacker.Error() == 0)
m_pConsole->RegisterTemp(pName, pParams, CFGFLAG_SERVER, pHelp);
}
const char *pName = Unpacker.GetString(CUnpacker::SANITIZE_CC);
const char *pHelp = Unpacker.GetString(CUnpacker::SANITIZE_CC);
const char *pParams = Unpacker.GetString(CUnpacker::SANITIZE_CC);
if(Unpacker.Error() == 0)
m_pConsole->RegisterTemp(pName, pParams, CFGFLAG_SERVER, pHelp);
}
else if((pPacket->m_Flags & NET_CHUNKFLAG_VITAL) != 0 && Msg == NETMSG_RCON_CMD_REM)
else if(!Dummy && (pPacket->m_Flags & NET_CHUNKFLAG_VITAL) != 0 && Msg == NETMSG_RCON_CMD_REM)
{
if(!g_Config.m_ClDummy)
{
const char *pName = Unpacker.GetString(CUnpacker::SANITIZE_CC);
if(Unpacker.Error() == 0)
m_pConsole->DeregisterTemp(pName);
}
const char *pName = Unpacker.GetString(CUnpacker::SANITIZE_CC);
if(Unpacker.Error() == 0)
m_pConsole->DeregisterTemp(pName);
}
else if((pPacket->m_Flags & NET_CHUNKFLAG_VITAL) != 0 && Msg == NETMSG_RCON_AUTH_STATUS)
else if(!Dummy && (pPacket->m_Flags & NET_CHUNKFLAG_VITAL) != 0 && Msg == NETMSG_RCON_AUTH_STATUS)
{
int Result = Unpacker.GetInt();
if(Unpacker.Error() == 0)
m_RconAuthed[g_Config.m_ClDummy] = Result;
m_RconAuthed[Dummy] = Result;
int Old = m_UseTempRconCommands;
m_UseTempRconCommands = Unpacker.GetInt();
if(Unpacker.Error() != 0)
@ -1854,13 +1838,13 @@ void CClient::ProcessServerPacket(CNetChunk *pPacket)
if(Old != 0 && m_UseTempRconCommands == 0)
m_pConsole->DeregisterTempAll();
}
else if((pPacket->m_Flags & NET_CHUNKFLAG_VITAL) != 0 && Msg == NETMSG_RCON_LINE)
else if(!Dummy && (pPacket->m_Flags & NET_CHUNKFLAG_VITAL) != 0 && Msg == NETMSG_RCON_LINE)
{
const char *pLine = Unpacker.GetString();
if(Unpacker.Error() == 0)
GameClient()->OnRconLine(pLine);
}
else if(Msg == NETMSG_PING_REPLY)
else if(Conn == CONN_MAIN && Msg == NETMSG_PING_REPLY)
{
char aBuf[256];
str_format(aBuf, sizeof(aBuf), "latency %.2f", (time_get() - m_PingStartTime) * 1000 / (float)time_freq());
@ -1876,10 +1860,10 @@ void CClient::ProcessServerPacket(CNetChunk *pPacket)
int64_t Target = 0;
for(int k = 0; k < 200; k++)
{
if(m_aInputs[g_Config.m_ClDummy][k].m_Tick == InputPredTick)
if(m_aInputs[Conn][k].m_Tick == InputPredTick)
{
Target = m_aInputs[g_Config.m_ClDummy][k].m_PredictedTime + (Now - m_aInputs[g_Config.m_ClDummy][k].m_Time);
Target = Target - (int64_t)((TimeLeft / 1000.0f) * time_freq()) + m_aInputs[g_Config.m_ClDummy][k].m_PredictionMargin;
Target = m_aInputs[Conn][k].m_PredictedTime + (Now - m_aInputs[Conn][k].m_Time);
Target = Target - (int64_t)((TimeLeft / 1000.0f) * time_freq()) + m_aInputs[Conn][k].m_PredictionMargin;
break;
}
}
@ -1922,18 +1906,18 @@ void CClient::ProcessServerPacket(CNetChunk *pPacket)
if(Unpacker.Error() || NumParts < 1 || NumParts > CSnapshot::MAX_PARTS || Part < 0 || Part >= NumParts || PartSize < 0 || PartSize > MAX_SNAPSHOT_PACKSIZE)
return;
if(GameTick >= m_CurrentRecvTick[g_Config.m_ClDummy])
if(GameTick >= m_CurrentRecvTick[Conn])
{
if(GameTick != m_CurrentRecvTick[g_Config.m_ClDummy])
if(GameTick != m_CurrentRecvTick[Conn])
{
m_SnapshotParts[g_Config.m_ClDummy] = 0;
m_CurrentRecvTick[g_Config.m_ClDummy] = GameTick;
m_SnapshotParts[Conn] = 0;
m_CurrentRecvTick[Conn] = GameTick;
}
mem_copy((char *)m_aSnapshotIncomingData + Part * MAX_SNAPSHOT_PACKSIZE, pData, clamp(PartSize, 0, (int)sizeof(m_aSnapshotIncomingData) - Part * MAX_SNAPSHOT_PACKSIZE));
m_SnapshotParts[g_Config.m_ClDummy] |= 1 << Part;
m_SnapshotParts[Conn] |= 1 << Part;
if(m_SnapshotParts[g_Config.m_ClDummy] == (unsigned)((1 << NumParts) - 1))
if(m_SnapshotParts[Conn] == (unsigned)((1 << NumParts) - 1))
{
static CSnapshot Emptysnap;
CSnapshot *pDeltaShot = &Emptysnap;
@ -1943,7 +1927,7 @@ void CClient::ProcessServerPacket(CNetChunk *pPacket)
const int CompleteSize = (NumParts - 1) * MAX_SNAPSHOT_PACKSIZE + PartSize;
// reset snapshoting
m_SnapshotParts[g_Config.m_ClDummy] = 0;
m_SnapshotParts[Conn] = 0;
// find snapshot that we should use as delta
Emptysnap.Clear();
@ -1951,7 +1935,7 @@ void CClient::ProcessServerPacket(CNetChunk *pPacket)
// find delta
if(DeltaTick >= 0)
{
int DeltashotSize = m_SnapshotStorage[g_Config.m_ClDummy].Get(DeltaTick, 0, &pDeltaShot, 0);
int DeltashotSize = m_SnapshotStorage[Conn].Get(DeltaTick, 0, &pDeltaShot, 0);
if(DeltashotSize < 0)
{
@ -1966,7 +1950,7 @@ void CClient::ProcessServerPacket(CNetChunk *pPacket)
// ack snapshot
// TODO: combine this with the input message
m_AckGameTick[g_Config.m_ClDummy] = -1;
m_AckGameTick[Conn] = -1;
return;
}
}
@ -2008,7 +1992,7 @@ void CClient::ProcessServerPacket(CNetChunk *pPacket)
if(m_SnapCrcErrors > 10)
{
// to many errors, send reset
m_AckGameTick[g_Config.m_ClDummy] = -1;
m_AckGameTick[Conn] = -1;
SendInput();
m_SnapCrcErrors = 0;
}
@ -2022,14 +2006,14 @@ void CClient::ProcessServerPacket(CNetChunk *pPacket)
// purge old snapshots
int PurgeTick = DeltaTick;
if(m_aSnapshots[g_Config.m_ClDummy][SNAP_PREV] && m_aSnapshots[g_Config.m_ClDummy][SNAP_PREV]->m_Tick < PurgeTick)
PurgeTick = m_aSnapshots[g_Config.m_ClDummy][SNAP_PREV]->m_Tick;
if(m_aSnapshots[g_Config.m_ClDummy][SNAP_CURRENT] && m_aSnapshots[g_Config.m_ClDummy][SNAP_CURRENT]->m_Tick < PurgeTick)
PurgeTick = m_aSnapshots[g_Config.m_ClDummy][SNAP_CURRENT]->m_Tick;
m_SnapshotStorage[g_Config.m_ClDummy].PurgeUntil(PurgeTick);
if(m_aSnapshots[Conn][SNAP_PREV] && m_aSnapshots[Conn][SNAP_PREV]->m_Tick < PurgeTick)
PurgeTick = m_aSnapshots[Conn][SNAP_PREV]->m_Tick;
if(m_aSnapshots[Conn][SNAP_CURRENT] && m_aSnapshots[Conn][SNAP_CURRENT]->m_Tick < PurgeTick)
PurgeTick = m_aSnapshots[Conn][SNAP_CURRENT]->m_Tick;
m_SnapshotStorage[Conn].PurgeUntil(PurgeTick);
// add new
m_SnapshotStorage[g_Config.m_ClDummy].Add(GameTick, time_get(), SnapSize, pTmpBuffer3, 1);
m_SnapshotStorage[Conn].Add(GameTick, time_get(), SnapSize, pTmpBuffer3, 1);
// for antiping: if the projectile netobjects from the server contains extra data, this is removed and the original content restored before recording demo
unsigned char aExtraInfoRemoved[CSnapshot::MAX_SIZE];
@ -2047,39 +2031,48 @@ void CClient::ProcessServerPacket(CNetChunk *pPacket)
}
// apply snapshot, cycle pointers
m_ReceivedSnapshots[g_Config.m_ClDummy]++;
m_ReceivedSnapshots[Conn]++;
m_CurrentRecvTick[g_Config.m_ClDummy] = GameTick;
m_CurrentRecvTick[Conn] = GameTick;
// we got two snapshots until we see us self as connected
if(m_ReceivedSnapshots[g_Config.m_ClDummy] == 2)
if(m_ReceivedSnapshots[Conn] == 2)
{
// start at 200ms and work from there
m_PredictedTime.Init(GameTick * time_freq() / 50);
m_PredictedTime.SetAdjustSpeed(1, 1000.0f);
m_PredictedTime.UpdateMargin(PredictionMargin() * time_freq() / 1000);
m_GameTime[g_Config.m_ClDummy].Init((GameTick - 1) * time_freq() / 50);
m_aSnapshots[g_Config.m_ClDummy][SNAP_PREV] = m_SnapshotStorage[g_Config.m_ClDummy].m_pFirst;
m_aSnapshots[g_Config.m_ClDummy][SNAP_CURRENT] = m_SnapshotStorage[g_Config.m_ClDummy].m_pLast;
m_LocalStartTime = time_get();
if(!Dummy)
{
m_PredictedTime.Init(GameTick * time_freq() / 50);
m_PredictedTime.SetAdjustSpeed(1, 1000.0f);
m_PredictedTime.UpdateMargin(PredictionMargin() * time_freq() / 1000);
}
m_GameTime[Conn].Init((GameTick - 1) * time_freq() / 50);
m_aSnapshots[Conn][SNAP_PREV] = m_SnapshotStorage[Conn].m_pFirst;
m_aSnapshots[Conn][SNAP_CURRENT] = m_SnapshotStorage[Conn].m_pLast;
if(!Dummy)
{
m_LocalStartTime = time_get();
#if defined(CONF_VIDEORECORDER)
IVideo::SetLocalStartTime(m_LocalStartTime);
IVideo::SetLocalStartTime(m_LocalStartTime);
#endif
GameClient()->OnNewSnapshot();
GameClient()->OnNewSnapshot();
}
SetState(IClient::STATE_ONLINE);
DemoRecorder_HandleAutoStart();
if(!Dummy)
{
DemoRecorder_HandleAutoStart();
}
}
// adjust game time
if(m_ReceivedSnapshots[g_Config.m_ClDummy] > 2)
if(m_ReceivedSnapshots[Conn] > 2)
{
int64_t Now = m_GameTime[g_Config.m_ClDummy].Get(time_get());
int64_t Now = m_GameTime[Conn].Get(time_get());
int64_t TickStart = GameTick * time_freq() / 50;
int64_t TimeLeft = (TickStart - Now) * 1000 / time_freq();
m_GameTime[g_Config.m_ClDummy].Update(&m_GametimeMarginGraph, (GameTick - 1) * time_freq() / 50, TimeLeft, 0);
m_GameTime[Conn].Update(&m_GametimeMarginGraph, (GameTick - 1) * time_freq() / 50, TimeLeft, 0);
}
if(m_ReceivedSnapshots[g_Config.m_ClDummy] > 50 && !m_CodeRunAfterJoin[g_Config.m_ClDummy])
if(m_ReceivedSnapshots[Conn] > 50 && !m_CodeRunAfterJoin[Conn])
{
if(m_ServerCapabilities.m_ChatTimeoutCode || ShouldSendChatTimeoutCodeHeuristic())
{
@ -2088,26 +2081,26 @@ void CClient::ProcessServerPacket(CNetChunk *pPacket)
char aBuf[256];
if(g_Config.m_ClRunOnJoin[0])
{
str_format(aBuf, sizeof(aBuf), "/mc;timeout %s;%s", m_aTimeoutCodes[g_Config.m_ClDummy], g_Config.m_ClRunOnJoin);
str_format(aBuf, sizeof(aBuf), "/mc;timeout %s;%s", m_aTimeoutCodes[Conn], g_Config.m_ClRunOnJoin);
}
else
{
str_format(aBuf, sizeof(aBuf), "/timeout %s", m_aTimeoutCodes[g_Config.m_ClDummy]);
str_format(aBuf, sizeof(aBuf), "/timeout %s", m_aTimeoutCodes[Conn]);
}
Msg.m_pMessage = aBuf;
CMsgPacker Packer(Msg.MsgID(), false);
Msg.Pack(&Packer);
SendMsgY(&Packer, MSGFLAG_VITAL, g_Config.m_ClDummy);
SendMsg(Conn, &Packer, MSGFLAG_VITAL);
}
m_CodeRunAfterJoin[g_Config.m_ClDummy] = true;
m_CodeRunAfterJoin[Conn] = true;
}
// ack snapshot
m_AckGameTick[g_Config.m_ClDummy] = GameTick;
m_AckGameTick[Conn] = GameTick;
}
}
}
else if(Msg == NETMSG_RCONTYPE)
else if(Conn == CONN_MAIN && Msg == NETMSG_RCONTYPE)
{
bool UsernameReq = Unpacker.GetInt() & 1;
GameClient()->OnRconType(UsernameReq);
@ -2118,250 +2111,16 @@ void CClient::ProcessServerPacket(CNetChunk *pPacket)
if((pPacket->m_Flags & NET_CHUNKFLAG_VITAL) != 0)
{
// game message
for(auto &DemoRecorder : m_DemoRecorder)
if(DemoRecorder.IsRecording())
DemoRecorder.RecordMessage(pPacket->m_pData, pPacket->m_DataSize);
GameClient()->OnMessage(Msg, &Unpacker);
}
}
}
void CClient::ProcessServerPacketDummy(CNetChunk *pPacket)
{
CUnpacker Unpacker;
Unpacker.Reset(pPacket->m_pData, pPacket->m_DataSize);
CMsgPacker Packer(NETMSG_EX, true);
// unpack msgid and system flag
int Msg;
bool Sys;
CUuid Uuid;
int Result = UnpackMessageID(&Msg, &Sys, &Uuid, &Unpacker, &Packer);
if(Result == UNPACKMESSAGE_ERROR)
{
return;
}
else if(Result == UNPACKMESSAGE_ANSWER)
{
SendMsgY(&Packer, MSGFLAG_VITAL, !g_Config.m_ClDummy);
}
if(Sys)
{
if(Msg == NETMSG_CON_READY)
{
m_DummyConnected = true;
g_Config.m_ClDummy = 1;
Rcon("crashmeplx");
if(m_RconAuthed[0])
RconAuth("", m_RconPassword);
}
else if(Msg == NETMSG_RCON_CMD_ADD)
{
if(g_Config.m_ClDummy)
if(!Dummy)
{
const char *pName = Unpacker.GetString(CUnpacker::SANITIZE_CC);
const char *pHelp = Unpacker.GetString(CUnpacker::SANITIZE_CC);
const char *pParams = Unpacker.GetString(CUnpacker::SANITIZE_CC);
if(Unpacker.Error() == 0)
m_pConsole->RegisterTemp(pName, pParams, CFGFLAG_SERVER, pHelp);
}
}
else if(Msg == NETMSG_RCON_CMD_REM)
{
if(g_Config.m_ClDummy)
{
const char *pName = Unpacker.GetString(CUnpacker::SANITIZE_CC);
if(Unpacker.Error() == 0)
m_pConsole->DeregisterTemp(pName);
}
}
else if(Msg == NETMSG_SNAP || Msg == NETMSG_SNAPSINGLE || Msg == NETMSG_SNAPEMPTY)
{
int GameTick = Unpacker.GetInt();
int DeltaTick = GameTick - Unpacker.GetInt();
// only allow packets from the server we actually want
if(net_addr_comp(&pPacket->m_Address, &m_ServerAddress))
return;
// we are not allowed to process snapshot yet
if(State() < IClient::STATE_LOADING)
return;
int NumParts = 1;
int Part = 0;
if(Msg == NETMSG_SNAP)
{
NumParts = Unpacker.GetInt();
Part = Unpacker.GetInt();
for(auto &DemoRecorder : m_DemoRecorder)
if(DemoRecorder.IsRecording())
DemoRecorder.RecordMessage(pPacket->m_pData, pPacket->m_DataSize);
}
unsigned int Crc = 0;
int PartSize = 0;
if(Msg != NETMSG_SNAPEMPTY)
{
Crc = Unpacker.GetInt();
PartSize = Unpacker.GetInt();
}
const char *pData = (const char *)Unpacker.GetRaw(PartSize);
if(Unpacker.Error() || NumParts < 1 || NumParts > CSnapshot::MAX_PARTS || Part < 0 || Part >= NumParts || PartSize < 0 || PartSize > MAX_SNAPSHOT_PACKSIZE)
return;
if(GameTick >= m_CurrentRecvTick[!g_Config.m_ClDummy])
{
if(GameTick != m_CurrentRecvTick[!g_Config.m_ClDummy])
{
m_SnapshotParts[!g_Config.m_ClDummy] = 0;
m_CurrentRecvTick[!g_Config.m_ClDummy] = GameTick;
}
mem_copy((char *)m_aSnapshotIncomingData + Part * MAX_SNAPSHOT_PACKSIZE, pData, clamp(PartSize, 0, (int)sizeof(m_aSnapshotIncomingData) - Part * MAX_SNAPSHOT_PACKSIZE));
m_SnapshotParts[!g_Config.m_ClDummy] |= 1 << Part;
if(m_SnapshotParts[!g_Config.m_ClDummy] == (unsigned)((1 << NumParts) - 1))
{
static CSnapshot Emptysnap;
CSnapshot *pDeltaShot = &Emptysnap;
unsigned char aTmpBuffer2[CSnapshot::MAX_SIZE];
unsigned char aTmpBuffer3[CSnapshot::MAX_SIZE];
CSnapshot *pTmpBuffer3 = (CSnapshot *)aTmpBuffer3; // Fix compiler warning for strict-aliasing
const int CompleteSize = (NumParts - 1) * MAX_SNAPSHOT_PACKSIZE + PartSize;
// reset snapshoting
m_SnapshotParts[!g_Config.m_ClDummy] = 0;
// find snapshot that we should use as delta
Emptysnap.Clear();
// find delta
if(DeltaTick >= 0)
{
int DeltashotSize = m_SnapshotStorage[!g_Config.m_ClDummy].Get(DeltaTick, 0, &pDeltaShot, 0);
if(DeltashotSize < 0)
{
// couldn't find the delta snapshots that the server used
// to compress this snapshot. force the server to resync
if(g_Config.m_Debug)
{
char aBuf[256];
str_format(aBuf, sizeof(aBuf), "error, couldn't find the delta snapshot");
m_pConsole->Print(IConsole::OUTPUT_LEVEL_DEBUG, "client", aBuf);
}
// ack snapshot
// TODO: combine this with the input message
m_AckGameTick[!g_Config.m_ClDummy] = -1;
return;
}
}
// decompress snapshot
const void *pDeltaData = m_SnapshotDelta.EmptyDelta();
int DeltaSize = sizeof(int) * 3;
if(CompleteSize)
{
int IntSize = CVariableInt::Decompress(m_aSnapshotIncomingData, CompleteSize, aTmpBuffer2, sizeof(aTmpBuffer2));
if(IntSize < 0) // failure during decompression, bail
return;
pDeltaData = aTmpBuffer2;
DeltaSize = IntSize;
}
// unpack delta
const int SnapSize = m_SnapshotDelta.UnpackDelta(pDeltaShot, pTmpBuffer3, pDeltaData, DeltaSize);
if(SnapSize < 0)
{
m_pConsole->Print(IConsole::OUTPUT_LEVEL_DEBUG, "client", "delta unpack failed!");
return;
}
if(Msg != NETMSG_SNAPEMPTY && pTmpBuffer3->Crc() != Crc)
{
if(g_Config.m_Debug)
{
char aBuf[256];
str_format(aBuf, sizeof(aBuf), "snapshot crc error #%d - tick=%d wantedcrc=%d gotcrc=%d compressed_size=%d delta_tick=%d",
m_SnapCrcErrors, GameTick, Crc, pTmpBuffer3->Crc(), CompleteSize, DeltaTick);
m_pConsole->Print(IConsole::OUTPUT_LEVEL_DEBUG, "client", aBuf);
}
m_SnapCrcErrors++;
if(m_SnapCrcErrors > 10)
{
// to many errors, send reset
m_AckGameTick[!g_Config.m_ClDummy] = -1;
SendInput();
m_SnapCrcErrors = 0;
}
return;
}
else
{
if(m_SnapCrcErrors)
m_SnapCrcErrors--;
}
// purge old snapshots
int PurgeTick = DeltaTick;
if(m_aSnapshots[!g_Config.m_ClDummy][SNAP_PREV] && m_aSnapshots[!g_Config.m_ClDummy][SNAP_PREV]->m_Tick < PurgeTick)
PurgeTick = m_aSnapshots[!g_Config.m_ClDummy][SNAP_PREV]->m_Tick;
if(m_aSnapshots[!g_Config.m_ClDummy][SNAP_CURRENT] && m_aSnapshots[!g_Config.m_ClDummy][SNAP_CURRENT]->m_Tick < PurgeTick)
PurgeTick = m_aSnapshots[!g_Config.m_ClDummy][SNAP_CURRENT]->m_Tick;
m_SnapshotStorage[!g_Config.m_ClDummy].PurgeUntil(PurgeTick);
// add new
m_SnapshotStorage[!g_Config.m_ClDummy].Add(GameTick, time_get(), SnapSize, pTmpBuffer3, 1);
// apply snapshot, cycle pointers
m_ReceivedSnapshots[!g_Config.m_ClDummy]++;
m_CurrentRecvTick[!g_Config.m_ClDummy] = GameTick;
// we got two snapshots until we see us self as connected
if(m_ReceivedSnapshots[!g_Config.m_ClDummy] == 2)
{
// start at 200ms and work from there
//m_PredictedTime[!g_Config.m_ClDummy].Init(GameTick*time_freq()/50);
//m_PredictedTime[!g_Config.m_ClDummy].SetAdjustSpeed(1, 1000.0f);
m_GameTime[!g_Config.m_ClDummy].Init((GameTick - 1) * time_freq() / 50);
m_aSnapshots[!g_Config.m_ClDummy][SNAP_PREV] = m_SnapshotStorage[!g_Config.m_ClDummy].m_pFirst;
m_aSnapshots[!g_Config.m_ClDummy][SNAP_CURRENT] = m_SnapshotStorage[!g_Config.m_ClDummy].m_pLast;
m_LocalStartTime = time_get();
#if defined(CONF_VIDEORECORDER)
IVideo::SetLocalStartTime(m_LocalStartTime);
#endif
SetState(IClient::STATE_ONLINE);
}
// adjust game time
if(m_ReceivedSnapshots[!g_Config.m_ClDummy] > 2)
{
int64_t Now = m_GameTime[!g_Config.m_ClDummy].Get(time_get());
int64_t TickStart = GameTick * time_freq() / 50;
int64_t TimeLeft = (TickStart - Now) * 1000 / time_freq();
m_GameTime[!g_Config.m_ClDummy].Update(&m_GametimeMarginGraph, (GameTick - 1) * time_freq() / 50, TimeLeft, 0);
}
// ack snapshot
m_AckGameTick[!g_Config.m_ClDummy] = GameTick;
}
}
GameClient()->OnMessage(Msg, &Unpacker, Conn, Dummy);
}
}
else
{
GameClient()->OnMessage(Msg, &Unpacker, 1);
}
}
void CClient::ResetMapDownload()
@ -2560,26 +2319,26 @@ void CClient::PumpNetwork()
if(State() != IClient::STATE_DEMOPLAYBACK)
{
// check for errors
if(State() != IClient::STATE_OFFLINE && State() < IClient::STATE_QUITTING && m_NetClient[CLIENT_MAIN].State() == NETSTATE_OFFLINE)
if(State() != IClient::STATE_OFFLINE && State() < IClient::STATE_QUITTING && m_NetClient[CONN_MAIN].State() == NETSTATE_OFFLINE)
{
SetState(IClient::STATE_OFFLINE);
Disconnect();
char aBuf[256];
str_format(aBuf, sizeof(aBuf), "offline error='%s'", m_NetClient[CLIENT_MAIN].ErrorString());
str_format(aBuf, sizeof(aBuf), "offline error='%s'", m_NetClient[CONN_MAIN].ErrorString());
m_pConsole->Print(IConsole::OUTPUT_LEVEL_STANDARD, "client", aBuf, ClientNetworkErrPrintColor);
}
if(State() != IClient::STATE_OFFLINE && State() < IClient::STATE_QUITTING && m_DummyConnected &&
m_NetClient[CLIENT_DUMMY].State() == NETSTATE_OFFLINE)
m_NetClient[CONN_DUMMY].State() == NETSTATE_OFFLINE)
{
DummyDisconnect(0);
char aBuf[256];
str_format(aBuf, sizeof(aBuf), "offline dummy error='%s'", m_NetClient[CLIENT_DUMMY].ErrorString());
str_format(aBuf, sizeof(aBuf), "offline dummy error='%s'", m_NetClient[CONN_DUMMY].ErrorString());
m_pConsole->Print(IConsole::OUTPUT_LEVEL_STANDARD, "client", aBuf, ClientNetworkErrPrintColor);
}
//
if(State() == IClient::STATE_CONNECTING && m_NetClient[CLIENT_MAIN].State() == NETSTATE_ONLINE)
if(State() == IClient::STATE_CONNECTING && m_NetClient[CONN_MAIN].State() == NETSTATE_ONLINE)
{
// we switched to online
m_pConsole->Print(IConsole::OUTPUT_LEVEL_STANDARD, "client", "connected, sending info", ClientNetworkPrintColor);
@ -2590,28 +2349,20 @@ void CClient::PumpNetwork()
// process packets
CNetChunk Packet;
for(int i = 0; i < NUM_CLIENTS; i++)
for(int i = 0; i < NUM_CONNS; i++)
{
while(m_NetClient[i].Recv(&Packet))
{
if(Packet.m_ClientID == -1 || i > 1)
if(Packet.m_ClientID == -1)
{
ProcessConnlessPacket(&Packet);
continue;
}
else if(i > 0 && i < 2)
if(i > 1)
{
if(g_Config.m_ClDummy)
ProcessServerPacket(&Packet); //self
else
ProcessServerPacketDummy(&Packet); //multiclient
}
else
{
if(g_Config.m_ClDummy)
ProcessServerPacketDummy(&Packet); //multiclient
else
ProcessServerPacket(&Packet); //self
continue;
}
ProcessServerPacket(&Packet, i, g_Config.m_ClDummy ^ i);
}
}
}
@ -2653,7 +2404,7 @@ void CClient::OnDemoPlayerMessage(void *pData, int Size)
}
if(!Sys)
GameClient()->OnMessage(Msg, &Unpacker);
GameClient()->OnMessage(Msg, &Unpacker, CONN_MAIN, false);
}
/*
const IDemoPlayer::CInfo *client_demoplayer_getinfo()
@ -2881,7 +2632,7 @@ void CClient::Update()
{
CMsgPacker Msg(NETMSG_PINGEX, true);
Msg.AddRaw(&m_CurrentServerPingUuid, sizeof(m_CurrentServerPingUuid));
SendMsg(&Msg, MSGFLAG_FLUSH);
SendMsg(CONN_MAIN, &Msg, MSGFLAG_FLUSH);
}
m_CurrentServerCurrentPingTime = Now;
m_CurrentServerNextPingTime = Now + 600 * Freq; // ping every 10 minutes
@ -3032,7 +2783,7 @@ void CClient::InitInterfaces()
m_DemoEditor.Init(m_pGameClient->NetVersion(), &m_SnapshotDelta, m_pConsole, m_pStorage);
m_ServerBrowser.SetBaseInfo(&m_NetClient[CLIENT_CONTACT], m_pGameClient->NetVersion());
m_ServerBrowser.SetBaseInfo(&m_NetClient[CONN_CONTACT], m_pGameClient->NetVersion());
HttpInit(m_pStorage);
@ -3125,7 +2876,7 @@ void CClient::Run()
}
for(unsigned int i = 0; i < sizeof(m_NetClient) / sizeof(m_NetClient[0]); i++)
{
BindAddr.port = i == CLIENT_MAIN ? g_Config.m_ClPort : i == CLIENT_DUMMY ? g_Config.m_ClDummyPort : g_Config.m_ClContactPort;
BindAddr.port = i == CONN_MAIN ? g_Config.m_ClPort : i == CONN_DUMMY ? g_Config.m_ClDummyPort : g_Config.m_ClContactPort;
while(BindAddr.port == 0 || !m_NetClient[i].Open(BindAddr, 0))
{
BindAddr.port = (secure_rand() % 64511) + 1024;
@ -3235,7 +2986,7 @@ void CClient::Run()
}
// progress on dummy connect if security token handshake skipped/passed
if(m_DummySendConnInfo && !m_NetClient[CLIENT_DUMMY].SecurityTokenUnknown())
if(m_DummySendConnInfo && !m_NetClient[CONN_DUMMY].SecurityTokenUnknown())
{
m_DummySendConnInfo = false;
@ -3244,26 +2995,26 @@ void CClient::Run()
MsgVer.AddRaw(&m_ConnectionID, sizeof(m_ConnectionID));
MsgVer.AddInt(GameClient()->DDNetVersion());
MsgVer.AddString(GameClient()->DDNetVersionStr(), 0);
SendMsgY(&MsgVer, MSGFLAG_VITAL, 1);
SendMsg(CONN_DUMMY, &MsgVer, MSGFLAG_VITAL);
CMsgPacker MsgInfo(NETMSG_INFO, true);
MsgInfo.AddString(GameClient()->NetVersion(), 128);
MsgInfo.AddString(m_Password, 128);
SendMsgY(&MsgInfo, MSGFLAG_VITAL | MSGFLAG_FLUSH, 1);
SendMsg(CONN_DUMMY, &MsgInfo, MSGFLAG_VITAL | MSGFLAG_FLUSH);
// update netclient
m_NetClient[CLIENT_DUMMY].Update();
m_NetClient[CONN_DUMMY].Update();
// send ready
CMsgPacker MsgReady(NETMSG_READY, true);
SendMsgY(&MsgReady, MSGFLAG_VITAL | MSGFLAG_FLUSH, 1);
SendMsg(CONN_DUMMY, &MsgReady, MSGFLAG_VITAL | MSGFLAG_FLUSH);
// startinfo
GameClient()->SendDummyInfo(true);
// send enter game an finish the connection
CMsgPacker MsgEnter(NETMSG_ENTERGAME, true);
SendMsgY(&MsgEnter, MSGFLAG_VITAL | MSGFLAG_FLUSH, 1);
SendMsg(CONN_DUMMY, &MsgEnter, MSGFLAG_VITAL | MSGFLAG_FLUSH);
}
// update input
@ -3445,7 +3196,7 @@ void CClient::Run()
{
SleepTimeInMicroSeconds = ((int64_t)1000000 / (int64_t)g_Config.m_ClRefreshRate) - (Now - LastTime);
if(SleepTimeInMicroSeconds > (int64_t)0)
net_socket_read_wait(m_NetClient[CLIENT_MAIN].m_Socket, SleepTimeInMicroSeconds);
net_socket_read_wait(m_NetClient[CONN_MAIN].m_Socket, SleepTimeInMicroSeconds);
Slept = true;
}
if(Slept)
@ -3550,7 +3301,7 @@ void CClient::Con_Ping(IConsole::IResult *pResult, void *pUserData)
CClient *pSelf = (CClient *)pUserData;
CMsgPacker Msg(NETMSG_PING, true);
pSelf->SendMsg(&Msg, 0);
pSelf->SendMsg(CONN_MAIN, &Msg, 0);
pSelf->m_PingStartTime = time_get();
}
@ -3822,7 +3573,7 @@ const char *CClient::DemoPlayer_Play(const char *pFilename, int StorageType)
io_close(File);
Disconnect();
m_NetClient[CLIENT_MAIN].ResetErrorString();
m_NetClient[CONN_MAIN].ResetErrorString();
// try to start playback
m_DemoPlayer.SetListener(this);

View file

@ -116,15 +116,7 @@ class CClient : public IClient, public CDemoPlayer::IListener
NUM_SNAPSHOT_TYPES = 2,
};
enum
{
CLIENT_MAIN = 0,
CLIENT_DUMMY,
CLIENT_CONTACT,
NUM_CLIENTS,
};
class CNetClient m_NetClient[NUM_CLIENTS];
class CNetClient m_NetClient[NUM_CONNS];
class CDemoPlayer m_DemoPlayer;
class CDemoRecorder m_DemoRecorder[RECORDER_MAX];
class CDemoEditor m_DemoEditor;
@ -307,11 +299,12 @@ public:
CClient();
// ----- send functions -----
virtual int SendMsg(CMsgPacker *pMsg, int Flags);
virtual int SendMsgY(CMsgPacker *pMsg, int Flags, int NetClient = 1);
virtual int SendMsg(int Conn, CMsgPacker *pMsg, int Flags);
// Send via the currently active client (main/dummy)
virtual int SendMsgActive(CMsgPacker *pMsg, int Flags);
void SendInfo();
void SendEnterGame(bool Dummy);
void SendEnterGame(int Conn);
void SendReady();
void SendMapRequest();
@ -340,7 +333,7 @@ public:
// called when the map is loaded and we should init for a new round
void OnEnterGame(bool Dummy);
virtual void EnterGame(bool Dummy);
virtual void EnterGame(int Conn);
virtual void Connect(const char *pAddress, const char *pPassword = NULL);
void DisconnectWithReason(const char *pReason);
@ -384,8 +377,7 @@ public:
void ProcessConnlessPacket(CNetChunk *pPacket);
void ProcessServerInfo(int Type, NETADDR *pFrom, const void *pData, int DataSize);
void ProcessServerPacket(CNetChunk *pPacket);
void ProcessServerPacketDummy(CNetChunk *pPacket);
void ProcessServerPacket(CNetChunk *pPacket, int Conn, bool Dummy);
void ResetMapDownload();
void FinishMapDownload();

View file

@ -1357,7 +1357,7 @@ void CChat::Say(int Team, const char *pLine)
CNetMsg_Cl_Say Msg;
Msg.m_Team = Team;
Msg.m_pMessage = pLine;
Client()->SendPackMsg(&Msg, MSGFLAG_VITAL);
Client()->SendPackMsgActive(&Msg, MSGFLAG_VITAL);
}
void CChat::SayChat(const char *pLine)

View file

@ -185,13 +185,13 @@ void CEmoticon::Emote(int Emoticon)
{
CNetMsg_Cl_Emoticon Msg;
Msg.m_Emoticon = Emoticon;
Client()->SendPackMsg(&Msg, MSGFLAG_VITAL);
Client()->SendPackMsgActive(&Msg, MSGFLAG_VITAL);
if(g_Config.m_ClDummyCopyMoves)
{
CMsgPacker Msg(NETMSGTYPE_CL_EMOTICON, false);
Msg.AddInt(Emoticon);
Client()->SendMsgY(&Msg, MSGFLAG_VITAL, !g_Config.m_ClDummy);
Client()->SendMsg(!g_Config.m_ClDummy, &Msg, MSGFLAG_VITAL);
}
}

View file

@ -184,7 +184,7 @@ void CSounds::PlayAndRecord(int Chn, int SetId, float Vol, vec2 Pos)
{
CNetMsg_Sv_SoundGlobal Msg;
Msg.m_SoundID = SetId;
Client()->SendPackMsg(&Msg, MSGFLAG_NOSEND | MSGFLAG_RECORD);
Client()->SendPackMsgActive(&Msg, MSGFLAG_NOSEND | MSGFLAG_RECORD);
Play(Chn, SetId, Vol);
}

View file

@ -466,5 +466,5 @@ void CSpectator::Spectate(int SpectatorID)
CNetMsg_Cl_SetSpectatorMode Msg;
Msg.m_SpectatorID = SpectatorID;
Client()->SendPackMsg(&Msg, MSGFLAG_VITAL);
Client()->SendPackMsgActive(&Msg, MSGFLAG_VITAL);
}

View file

@ -31,7 +31,7 @@ void CVoting::Callvote(const char *pType, const char *pValue, const char *pReaso
Msg.m_Type = pType;
Msg.m_Value = pValue;
Msg.m_Reason = pReason;
Client()->SendPackMsg(&Msg, MSGFLAG_VITAL);
Client()->SendPackMsgActive(&Msg, MSGFLAG_VITAL);
}
void CVoting::CallvoteSpectate(int ClientID, const char *pReason, bool ForceVote)
@ -133,7 +133,7 @@ void CVoting::Vote(int v)
{
m_Voted = v;
CNetMsg_Cl_Vote Msg = {v};
Client()->SendPackMsg(&Msg, MSGFLAG_VITAL);
Client()->SendPackMsgActive(&Msg, MSGFLAG_VITAL);
}
CVoting::CVoting()

View file

@ -657,7 +657,7 @@ void CGameClient::OnRelease()
m_All.m_paComponents[i]->OnRelease();
}
void CGameClient::OnMessage(int MsgId, CUnpacker *pUnpacker, bool IsDummy)
void CGameClient::OnMessage(int MsgId, CUnpacker *pUnpacker, int Conn, bool Dummy)
{
// special messages
if(MsgId == NETMSGTYPE_SV_TUNEPARAMS)
@ -680,9 +680,9 @@ void CGameClient::OnMessage(int MsgId, CUnpacker *pUnpacker, bool IsDummy)
m_ServerMode = SERVERMODE_PURE;
m_ReceivedTuning[IsDummy ? !g_Config.m_ClDummy : g_Config.m_ClDummy] = true;
m_ReceivedTuning[Conn] = true;
// apply new tuning
m_Tuning[IsDummy ? !g_Config.m_ClDummy : g_Config.m_ClDummy] = NewTuning;
m_Tuning[Conn] = NewTuning;
return;
}
@ -695,7 +695,7 @@ void CGameClient::OnMessage(int MsgId, CUnpacker *pUnpacker, bool IsDummy)
return;
}
if(IsDummy)
if(Dummy)
{
if(MsgId == NETMSGTYPE_SV_CHAT && m_LocalIDs[0] >= 0 && m_LocalIDs[1] >= 0)
{
@ -715,7 +715,7 @@ void CGameClient::OnMessage(int MsgId, CUnpacker *pUnpacker, bool IsDummy)
if(MsgId == NETMSGTYPE_SV_READYTOENTER)
{
Client()->EnterGame(IsDummy ? !g_Config.m_ClDummy : g_Config.m_ClDummy);
Client()->EnterGame(Conn);
}
else if(MsgId == NETMSGTYPE_SV_EMOTICON)
{
@ -723,8 +723,8 @@ void CGameClient::OnMessage(int MsgId, CUnpacker *pUnpacker, bool IsDummy)
// apply
m_aClients[pMsg->m_ClientID].m_Emoticon = pMsg->m_Emoticon;
m_aClients[pMsg->m_ClientID].m_EmoticonStartTick = Client()->GameTick(g_Config.m_ClDummy);
m_aClients[pMsg->m_ClientID].m_EmoticonStartFraction = Client()->IntraGameTickSincePrev(g_Config.m_ClDummy);
m_aClients[pMsg->m_ClientID].m_EmoticonStartTick = Client()->GameTick(Conn);
m_aClients[pMsg->m_ClientID].m_EmoticonStartFraction = Client()->IntraGameTickSincePrev(Conn);
}
else if(MsgId == NETMSGTYPE_SV_SOUNDGLOBAL)
{
@ -1121,7 +1121,7 @@ void CGameClient::OnNewSnapshot()
CNetMsg_Cl_Say Msg;
Msg.m_Team = rand() & 1;
Msg.m_pMessage = aMessage;
Client()->SendPackMsg(&Msg, MSGFLAG_VITAL);
Client()->SendPackMsgActive(&Msg, MSGFLAG_VITAL);
}
}
#endif
@ -1568,23 +1568,23 @@ void CGameClient::OnNewSnapshot()
int *pParams = (int *)&m_Tuning[g_Config.m_ClDummy];
for(unsigned i = 0; i < sizeof(m_Tuning[0]) / sizeof(int); i++)
Msg.AddInt(pParams[i]);
Client()->SendMsg(&Msg, MSGFLAG_RECORD | MSGFLAG_NOSEND);
Client()->SendMsgActive(&Msg, MSGFLAG_RECORD | MSGFLAG_NOSEND);
}
if(!m_DDRaceMsgSent[0] && m_Snap.m_pLocalInfo)
for(int i = 0; i < 2; i++)
{
if(!m_DDRaceMsgSent[i] && m_Snap.m_pLocalInfo)
{
continue;
}
if(i == IClient::CONN_DUMMY && !Client()->DummyConnected())
{
continue;
}
CMsgPacker Msg(NETMSGTYPE_CL_ISDDNETLEGACY, false);
Msg.AddInt(CLIENT_VERSIONNR);
Client()->SendMsgY(&Msg, MSGFLAG_VITAL, 0);
m_DDRaceMsgSent[0] = true;
}
if(!m_DDRaceMsgSent[1] && m_Snap.m_pLocalInfo && Client()->DummyConnected())
{
CMsgPacker Msg(NETMSGTYPE_CL_ISDDNETLEGACY, false);
Msg.AddInt(CLIENT_VERSIONNR);
Client()->SendMsgY(&Msg, MSGFLAG_VITAL, 1);
m_DDRaceMsgSent[1] = true;
Client()->SendMsg(i, &Msg, MSGFLAG_VITAL);
m_DDRaceMsgSent[i] = true;
}
if(m_ShowOthers[g_Config.m_ClDummy] == -1 || (m_ShowOthers[g_Config.m_ClDummy] != -1 && m_ShowOthers[g_Config.m_ClDummy] != g_Config.m_ClShowOthers))
@ -1592,7 +1592,7 @@ void CGameClient::OnNewSnapshot()
{
CNetMsg_Cl_ShowOthers Msg;
Msg.m_Show = g_Config.m_ClShowOthers;
Client()->SendPackMsg(&Msg, MSGFLAG_VITAL);
Client()->SendPackMsgActive(&Msg, MSGFLAG_VITAL);
}
// update state
@ -1618,9 +1618,9 @@ void CGameClient::OnNewSnapshot()
CMsgPacker Packer(Msg.MsgID(), false);
Msg.Pack(&Packer);
if(ZoomToSend != m_LastZoom)
Client()->SendMsgY(&Packer, MSGFLAG_VITAL, 0);
Client()->SendMsg(IClient::CONN_MAIN, &Packer, MSGFLAG_VITAL);
if(Client()->DummyConnected())
Client()->SendMsgY(&Packer, MSGFLAG_VITAL, 1);
Client()->SendMsg(IClient::CONN_DUMMY, &Packer, MSGFLAG_VITAL);
m_LastZoom = ZoomToSend;
m_LastScreenAspect = Graphics()->ScreenAspect();
}
@ -2000,7 +2000,7 @@ void CGameClient::SendSwitchTeam(int Team)
{
CNetMsg_Cl_SetTeam Msg;
Msg.m_Team = Team;
Client()->SendPackMsg(&Msg, MSGFLAG_VITAL);
Client()->SendPackMsgActive(&Msg, MSGFLAG_VITAL);
if(Team != TEAM_SPECTATORS)
m_Camera.OnReset();
@ -2020,7 +2020,7 @@ void CGameClient::SendInfo(bool Start)
Msg.m_ColorFeet = g_Config.m_ClPlayerColorFeet;
CMsgPacker Packer(Msg.MsgID(), false);
Msg.Pack(&Packer);
Client()->SendMsgY(&Packer, MSGFLAG_VITAL, 0);
Client()->SendMsg(IClient::CONN_MAIN, &Packer, MSGFLAG_VITAL);
m_CheckInfo[0] = -1;
}
else
@ -2035,7 +2035,7 @@ void CGameClient::SendInfo(bool Start)
Msg.m_ColorFeet = g_Config.m_ClPlayerColorFeet;
CMsgPacker Packer(Msg.MsgID(), false);
Msg.Pack(&Packer);
Client()->SendMsgY(&Packer, MSGFLAG_VITAL, 0);
Client()->SendMsg(IClient::CONN_MAIN, &Packer, MSGFLAG_VITAL);
m_CheckInfo[0] = Client()->GameTickSpeed();
}
}
@ -2054,7 +2054,7 @@ void CGameClient::SendDummyInfo(bool Start)
Msg.m_ColorFeet = g_Config.m_ClDummyColorFeet;
CMsgPacker Packer(Msg.MsgID(), false);
Msg.Pack(&Packer);
Client()->SendMsgY(&Packer, MSGFLAG_VITAL, 1);
Client()->SendMsg(IClient::CONN_DUMMY, &Packer, MSGFLAG_VITAL);
m_CheckInfo[1] = -1;
}
else
@ -2069,7 +2069,7 @@ void CGameClient::SendDummyInfo(bool Start)
Msg.m_ColorFeet = g_Config.m_ClDummyColorFeet;
CMsgPacker Packer(Msg.MsgID(), false);
Msg.Pack(&Packer);
Client()->SendMsgY(&Packer, MSGFLAG_VITAL, 1);
Client()->SendMsg(IClient::CONN_DUMMY, &Packer, MSGFLAG_VITAL);
m_CheckInfo[1] = Client()->GameTickSpeed();
}
}
@ -2077,12 +2077,12 @@ void CGameClient::SendDummyInfo(bool Start)
void CGameClient::SendKill(int ClientID)
{
CNetMsg_Cl_Kill Msg;
Client()->SendPackMsg(&Msg, MSGFLAG_VITAL);
Client()->SendPackMsgActive(&Msg, MSGFLAG_VITAL);
if(g_Config.m_ClDummyCopyMoves)
{
CMsgPacker Msg(NETMSGTYPE_CL_KILL, false);
Client()->SendMsgY(&Msg, MSGFLAG_VITAL, !g_Config.m_ClDummy);
Client()->SendMsg(!g_Config.m_ClDummy, &Msg, MSGFLAG_VITAL);
}
}

View file

@ -457,7 +457,7 @@ public:
virtual void OnInit();
virtual void OnConsoleInit();
virtual void OnStateChange(int NewState, int OldState);
virtual void OnMessage(int MsgId, CUnpacker *pUnpacker, bool IsDummy = 0);
virtual void OnMessage(int MsgId, CUnpacker *pUnpacker, int Conn, bool Dummy);
virtual void InvalidateSnapshot();
virtual void OnNewSnapshot();
virtual void OnPredict();