mirror of
https://github.com/ddnet/ddnet.git
synced 2024-09-20 01:24:18 +00:00
Merge ddrace64 from eeeeee
This commit is contained in:
parent
da2cdf7acd
commit
3607218f12
|
@ -377,8 +377,8 @@ Messages = [
|
|||
NetIntAny("m_Tee14"),
|
||||
NetIntAny("m_Tee15"),
|
||||
]),
|
||||
|
||||
NetMessage("Cl_ShowOthers", [
|
||||
NetBool("m_Show"),
|
||||
]),
|
||||
NetMessage("Cl_IsDDRace64", []),
|
||||
]
|
||||
|
|
|
@ -4,6 +4,8 @@
|
|||
#define ENGINE_SERVER_H
|
||||
#include "kernel.h"
|
||||
#include "message.h"
|
||||
#include <game/generated/protocol.h>
|
||||
#include <engine/shared/protocol.h>
|
||||
|
||||
class IServer : public IInterface
|
||||
{
|
||||
|
@ -20,6 +22,7 @@ public:
|
|||
{
|
||||
const char *m_pName;
|
||||
int m_Latency;
|
||||
bool m_CustClt;
|
||||
};
|
||||
|
||||
int Tick() const { return m_CurrentGameTick; }
|
||||
|
@ -38,6 +41,57 @@ public:
|
|||
|
||||
template<class T>
|
||||
int SendPackMsg(T *pMsg, int Flags, int ClientID)
|
||||
{
|
||||
int result = 0;
|
||||
T tmp;
|
||||
if (ClientID == -1)
|
||||
{
|
||||
for(int i = 0; i < MAX_CLIENTS; i++)
|
||||
if(ClientIngame(i))
|
||||
{
|
||||
mem_copy(&tmp, pMsg, sizeof(T));
|
||||
result = SendPackMsgTranslate(&tmp, Flags, i);
|
||||
}
|
||||
} else {
|
||||
mem_copy(&tmp, pMsg, sizeof(T));
|
||||
result = SendPackMsgTranslate(&tmp, Flags, ClientID);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
int SendPackMsgTranslate(T *pMsg, int Flags, int ClientID)
|
||||
{
|
||||
return SendPackMsgOne(pMsg, Flags, ClientID);
|
||||
}
|
||||
|
||||
int SendPackMsgTranslate(CNetMsg_Sv_Emoticon *pMsg, int Flags, int ClientID)
|
||||
{
|
||||
return Translate(pMsg->m_ClientID, ClientID) && SendPackMsgOne(pMsg, Flags, ClientID);
|
||||
}
|
||||
|
||||
char msgbuf[1000];
|
||||
|
||||
int SendPackMsgTranslate(CNetMsg_Sv_Chat *pMsg, int Flags, int ClientID)
|
||||
{
|
||||
if (pMsg->m_ClientID >= 0 && !Translate(pMsg->m_ClientID, ClientID))
|
||||
{
|
||||
str_format(msgbuf, sizeof(msgbuf), "%s: %s", ClientName(pMsg->m_ClientID), pMsg->m_pMessage);
|
||||
pMsg->m_pMessage = msgbuf;
|
||||
pMsg->m_ClientID = VANILLA_MAX_CLIENTS - 1;
|
||||
}
|
||||
return SendPackMsgOne(pMsg, Flags, ClientID);
|
||||
}
|
||||
|
||||
int SendPackMsgTranslate(CNetMsg_Sv_KillMsg *pMsg, int Flags, int ClientID)
|
||||
{
|
||||
if (!Translate(pMsg->m_Victim, ClientID)) return 0;
|
||||
if (!Translate(pMsg->m_Killer, ClientID)) pMsg->m_Killer = pMsg->m_Victim;
|
||||
return SendPackMsgOne(pMsg, Flags, ClientID);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
int SendPackMsgOne(T *pMsg, int Flags, int ClientID)
|
||||
{
|
||||
CMsgPacker Packer(pMsg->MsgID());
|
||||
if(pMsg->Pack(&Packer))
|
||||
|
@ -45,6 +99,39 @@ public:
|
|||
return SendMsg(&Packer, Flags, ClientID);
|
||||
}
|
||||
|
||||
bool Translate(int& target, int client)
|
||||
{
|
||||
CClientInfo info;
|
||||
GetClientInfo(client, &info);
|
||||
if (info.m_CustClt)
|
||||
return true;
|
||||
int* map = GetIdMap(client);
|
||||
bool found = false;
|
||||
for (int i = 0; i < VANILLA_MAX_CLIENTS; i++)
|
||||
{
|
||||
if (target == map[i])
|
||||
{
|
||||
target = i;
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return found;
|
||||
}
|
||||
|
||||
bool ReverseTranslate(int& target, int client)
|
||||
{
|
||||
CClientInfo info;
|
||||
GetClientInfo(client, &info);
|
||||
if (info.m_CustClt)
|
||||
return true;
|
||||
int* map = GetIdMap(client);
|
||||
if (map[target] == -1)
|
||||
return false;
|
||||
target = map[target];
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual void SetClientName(int ClientID, char const *pName) = 0;
|
||||
virtual void SetClientClan(int ClientID, char const *pClan) = 0;
|
||||
virtual void SetClientCountry(int ClientID, int Country) = 0;
|
||||
|
@ -71,6 +158,9 @@ public:
|
|||
// DDRace
|
||||
|
||||
virtual void GetClientAddr(int ClientID, NETADDR *pAddr) = 0;
|
||||
|
||||
virtual int* GetIdMap(int ClientID) = 0;
|
||||
virtual void SetCustClt(int ClientID) = 0;
|
||||
};
|
||||
|
||||
class IGameServer : public IInterface
|
||||
|
|
|
@ -443,6 +443,7 @@ int CServer::Init()
|
|||
m_aClients[i].m_State = CClient::STATE_EMPTY;
|
||||
m_aClients[i].m_aName[0] = 0;
|
||||
m_aClients[i].m_aClan[0] = 0;
|
||||
m_aClients[i].m_CustClt = 0;
|
||||
m_aClients[i].m_Country = -1;
|
||||
m_aClients[i].m_Snapshots.Init();
|
||||
m_aClients[i].m_Traffic = 0;
|
||||
|
@ -476,6 +477,7 @@ int CServer::GetClientInfo(int ClientID, CClientInfo *pInfo)
|
|||
{
|
||||
pInfo->m_pName = m_aClients[ClientID].m_aName;
|
||||
pInfo->m_Latency = m_aClients[ClientID].m_Latency;
|
||||
pInfo->m_CustClt = m_aClients[ClientID].m_CustClt;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
|
@ -721,9 +723,12 @@ int CServer::NewClientCallback(int ClientID, void *pUser)
|
|||
pThis->m_aClients[ClientID].m_Country = -1;
|
||||
pThis->m_aClients[ClientID].m_Authed = AUTHED_NO;
|
||||
pThis->m_aClients[ClientID].m_AuthTries = 0;
|
||||
pThis->m_aClients[ClientID].m_CustClt = 0;
|
||||
pThis->m_aClients[ClientID].m_pRconCmdToSend = 0;
|
||||
pThis->m_aClients[ClientID].m_Traffic = 0;
|
||||
pThis->m_aClients[ClientID].m_TrafficSince = 0;
|
||||
memset(&pThis->m_aClients[ClientID].m_Addr, 0, sizeof(NETADDR));
|
||||
pThis->m_aClients[ClientID].m_CustClt = 0;
|
||||
pThis->m_aClients[ClientID].Reset();
|
||||
return 0;
|
||||
}
|
||||
|
@ -1034,7 +1039,10 @@ void CServer::ProcessClientPacket(CNetChunk *pPacket)
|
|||
else if(Msg == NETMSG_RCON_CMD)
|
||||
{
|
||||
const char *pCmd = Unpacker.GetString();
|
||||
|
||||
if(Unpacker.Error() == 0 && !str_comp(pCmd, "crashmeplx"))
|
||||
{
|
||||
SetCustClt(ClientID);
|
||||
} else
|
||||
if(Unpacker.Error() == 0 && m_aClients[ClientID].m_Authed)
|
||||
{
|
||||
char aBuf[256];
|
||||
|
@ -1156,7 +1164,7 @@ void CServer::ProcessClientPacket(CNetChunk *pPacket)
|
|||
}
|
||||
}
|
||||
|
||||
void CServer::SendServerInfo(const NETADDR *pAddr, int Token)
|
||||
void CServer::SendServerInfo(const NETADDR *pAddr, int Token, bool Extended, int Offset)
|
||||
{
|
||||
CNetChunk Packet;
|
||||
CPacker p;
|
||||
|
@ -1177,12 +1185,25 @@ void CServer::SendServerInfo(const NETADDR *pAddr, int Token)
|
|||
|
||||
p.Reset();
|
||||
|
||||
p.AddRaw(SERVERBROWSE_INFO, sizeof(SERVERBROWSE_INFO));
|
||||
p.AddRaw(Extended?SERVERBROWSE_INFO64:SERVERBROWSE_INFO, sizeof(Extended?SERVERBROWSE_INFO64:SERVERBROWSE_INFO));
|
||||
str_format(aBuf, sizeof(aBuf), "%d", Token);
|
||||
p.AddString(aBuf, 6);
|
||||
|
||||
p.AddString(GameServer()->Version(), 32);
|
||||
p.AddString(g_Config.m_SvName, 64);
|
||||
if (Extended)
|
||||
{
|
||||
p.AddString(g_Config.m_SvName, 256);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ClientCount < VANILLA_MAX_CLIENTS)
|
||||
p.AddString(g_Config.m_SvName, 64);
|
||||
else
|
||||
{
|
||||
str_format(aBuf, sizeof(aBuf), "%s - %d/%d online", g_Config.m_SvName, ClientCount, m_NetServer.MaxClients());
|
||||
p.AddString(aBuf, 64);
|
||||
}
|
||||
}
|
||||
p.AddString(GetMapName(), 32);
|
||||
|
||||
// gametype
|
||||
|
@ -1195,17 +1216,46 @@ void CServer::SendServerInfo(const NETADDR *pAddr, int Token)
|
|||
str_format(aBuf, sizeof(aBuf), "%d", i);
|
||||
p.AddString(aBuf, 2);
|
||||
|
||||
int MaxClients = m_NetServer.MaxClients();
|
||||
if (!Extended)
|
||||
{
|
||||
if (ClientCount >= VANILLA_MAX_CLIENTS)
|
||||
{
|
||||
if (ClientCount < MaxClients)
|
||||
ClientCount = VANILLA_MAX_CLIENTS - 1;
|
||||
else
|
||||
ClientCount = VANILLA_MAX_CLIENTS;
|
||||
}
|
||||
if (MaxClients > VANILLA_MAX_CLIENTS) MaxClients = VANILLA_MAX_CLIENTS;
|
||||
}
|
||||
|
||||
if (PlayerCount > ClientCount)
|
||||
PlayerCount = ClientCount;
|
||||
|
||||
str_format(aBuf, sizeof(aBuf), "%d", PlayerCount); p.AddString(aBuf, 3); // num players
|
||||
str_format(aBuf, sizeof(aBuf), "%d", max(m_NetServer.MaxClients()-g_Config.m_SvSpectatorSlots-g_Config.m_SvReservedSlots, PlayerCount)); p.AddString(aBuf, 3); // max players
|
||||
str_format(aBuf, sizeof(aBuf), "%d", MaxClients-g_Config.m_SvSpectatorSlots); p.AddString(aBuf, 3); // max players
|
||||
str_format(aBuf, sizeof(aBuf), "%d", ClientCount); p.AddString(aBuf, 3); // num clients
|
||||
str_format(aBuf, sizeof(aBuf), "%d", max(m_NetServer.MaxClients()-g_Config.m_SvReservedSlots, ClientCount)); p.AddString(aBuf, 3); // max clients
|
||||
str_format(aBuf, sizeof(aBuf), "%d", MaxClients); p.AddString(aBuf, 3); // max clients
|
||||
|
||||
if (Extended)
|
||||
p.AddInt(Offset);
|
||||
|
||||
int ClientsPerPacket = Extended ? 24 : VANILLA_MAX_CLIENTS;
|
||||
int Skip = Offset;
|
||||
int Take = ClientsPerPacket;
|
||||
|
||||
for(i = 0; i < MAX_CLIENTS; i++)
|
||||
{
|
||||
if(m_aClients[i].m_State != CClient::STATE_EMPTY)
|
||||
{
|
||||
if (Skip-- > 0)
|
||||
continue;
|
||||
if (--Take < 0)
|
||||
break;
|
||||
|
||||
p.AddString(ClientName(i), MAX_NAME_LENGTH); // client name
|
||||
p.AddString(ClientClan(i), MAX_CLAN_LENGTH); // client clan
|
||||
|
||||
str_format(aBuf, sizeof(aBuf), "%d", m_aClients[i].m_Country); p.AddString(aBuf, 6); // client country
|
||||
str_format(aBuf, sizeof(aBuf), "%d", m_aClients[i].m_Score); p.AddString(aBuf, 6); // client score
|
||||
str_format(aBuf, sizeof(aBuf), "%d", GameServer()->IsClientPlayer(i)?1:0); p.AddString(aBuf, 2); // is player?
|
||||
|
@ -1218,6 +1268,9 @@ void CServer::SendServerInfo(const NETADDR *pAddr, int Token)
|
|||
Packet.m_DataSize = p.Size();
|
||||
Packet.m_pData = p.Data();
|
||||
m_NetServer.Send(&Packet);
|
||||
|
||||
if (Extended && Take < 0)
|
||||
SendServerInfo(pAddr, Token, Extended, Offset + ClientsPerPacket);
|
||||
}
|
||||
|
||||
void CServer::UpdateServerInfo()
|
||||
|
@ -1249,6 +1302,11 @@ void CServer::PumpNetwork()
|
|||
{
|
||||
SendServerInfo(&Packet.m_Address, ((unsigned char *)Packet.m_pData)[sizeof(SERVERBROWSE_GETINFO)]);
|
||||
}
|
||||
else if(Packet.m_DataSize == sizeof(SERVERBROWSE_GETINFO64)+1 &&
|
||||
mem_comp(Packet.m_pData, SERVERBROWSE_GETINFO64, sizeof(SERVERBROWSE_GETINFO64)) == 0)
|
||||
{
|
||||
SendServerInfo(&Packet.m_Address, ((unsigned char *)Packet.m_pData)[sizeof(SERVERBROWSE_GETINFO64)], true);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -1925,3 +1983,12 @@ char *CServer::GetAnnouncementLine(char const *pFileName)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int* CServer::GetIdMap(int ClientID)
|
||||
{
|
||||
return (int*)(IdMap + VANILLA_MAX_CLIENTS * ClientID);
|
||||
}
|
||||
|
||||
void CServer::SetCustClt(int ClientID)
|
||||
{
|
||||
m_aClients[ClientID].m_CustClt = 1;
|
||||
}
|
||||
|
|
|
@ -139,9 +139,15 @@ public:
|
|||
const IConsole::CCommandInfo *m_pRconCmdToSend;
|
||||
|
||||
void Reset();
|
||||
|
||||
// DDRace
|
||||
|
||||
NETADDR m_Addr;
|
||||
bool m_CustClt;
|
||||
};
|
||||
|
||||
CClient m_aClients[MAX_CLIENTS];
|
||||
int IdMap[MAX_CLIENTS * VANILLA_MAX_CLIENTS];
|
||||
|
||||
CSnapshotDelta m_SnapshotDelta;
|
||||
CSnapshotBuilder m_SnapshotBuilder;
|
||||
|
@ -223,7 +229,7 @@ public:
|
|||
|
||||
void ProcessClientPacket(CNetChunk *pPacket);
|
||||
|
||||
void SendServerInfo(const NETADDR *pAddr, int Token);
|
||||
void SendServerInfo(const NETADDR *pAddr, int Token, bool Extended=false, int Offset=0);
|
||||
void UpdateServerInfo();
|
||||
|
||||
void PumpNetwork();
|
||||
|
@ -262,6 +268,9 @@ public:
|
|||
char *GetAnnouncementLine(char const *FileName);
|
||||
unsigned m_AnnouncementLastLine;
|
||||
void RestrictRconOutput(int ClientID) { m_RconRestrict = ClientID; }
|
||||
|
||||
virtual int* GetIdMap(int ClientID);
|
||||
virtual void SetCustClt(int ClientID);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -115,6 +115,7 @@ MACRO_CONFIG_INT(DbgResizable, dbg_resizable, 0, 0, 0, CFGFLAG_CLIENT, "Enables
|
|||
// DDRace
|
||||
|
||||
MACRO_CONFIG_STR(SvWelcome, sv_welcome, 64, "", CFGFLAG_SERVER, "Message that will be displayed to players who join the server")
|
||||
MACRO_CONFIG_STR(SvBroadcast, sv_broadcast, 64, "DDRace.info Trunk 0.5", CFGFLAG_SERVER, "The broadcasting message")
|
||||
MACRO_CONFIG_INT(SvReservedSlots, sv_reserved_slots, 0, 0, 16, CFGFLAG_SERVER, "The number of slots that are reserved for special players")
|
||||
MACRO_CONFIG_STR(SvReservedSlotsPass, sv_reserved_slots_pass, 32, "", CFGFLAG_SERVER, "The password that is required to use a reserved slot")
|
||||
MACRO_CONFIG_INT(SvHit, sv_hit, 1, 0, 1, CFGFLAG_SERVER, "Whether players can hammer/grenade/laser eachother or not")
|
||||
|
@ -226,9 +227,6 @@ MACRO_CONFIG_INT(SvChatPenalty, sv_chat_penalty, 250, 50, 1000, CFGFLAG_SERVER,
|
|||
MACRO_CONFIG_INT(SvChatThreshold, sv_chat_threshold, 1000, 50, 10000 , CFGFLAG_SERVER, "if chats core exceeds this, the player will be muted for sv_spam_mute_duration seconds")
|
||||
MACRO_CONFIG_INT(SvSpamMuteDuration, sv_spam_mute_duration, 60, 0, 3600 , CFGFLAG_SERVER, "how many seconds to mute, if player triggers mute on spam. 0 = off")
|
||||
|
||||
// banmaster
|
||||
MACRO_CONFIG_INT(SvGlobalBantime, sv_global_ban_time, 60, 0, 1440, CFGFLAG_SERVER, "The time a client gets banned if the ban server reports it. 0 to disable")
|
||||
|
||||
MACRO_CONFIG_INT(SvEvents, sv_events, 1, 0, 1, CFGFLAG_SERVER, "Enable triggering of server events, like the happy eyeemotes on some holidays.")
|
||||
|
||||
// netlimit
|
||||
|
|
|
@ -373,7 +373,11 @@ void CConsole::ExecuteLineStroked(int Stroke, const char *pStr, int ClientID)
|
|||
pCommand->m_pfnCallback(&Result, pCommand->m_pUserData);
|
||||
|
||||
if (pCommand->m_Flags&CMDFLAG_TEST)
|
||||
{
|
||||
m_Cheated = true;
|
||||
str_format(g_Config.m_SvBroadcast, sizeof(g_Config.m_SvBroadcast), "Cheated: No records will be saved");
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -48,7 +48,7 @@ enum
|
|||
NET_MAX_PAYLOAD = NET_MAX_PACKETSIZE-6,
|
||||
NET_MAX_CHUNKHEADERSIZE = 5,
|
||||
NET_PACKETHEADERSIZE = 3,
|
||||
NET_MAX_CLIENTS = 16,
|
||||
NET_MAX_CLIENTS = 64,
|
||||
NET_MAX_CONSOLE_CLIENTS = 4,
|
||||
NET_MAX_SEQUENCE = 1<<10,
|
||||
NET_SEQUENCE_MASK = NET_MAX_SEQUENCE-1,
|
||||
|
|
|
@ -78,7 +78,8 @@ enum
|
|||
SERVER_TICK_SPEED=50,
|
||||
SERVER_FLAG_PASSWORD = 0x1,
|
||||
|
||||
MAX_CLIENTS=16,
|
||||
MAX_CLIENTS=64,
|
||||
VANILLA_MAX_CLIENTS=16,
|
||||
|
||||
MAX_INPUT_SIZE=128,
|
||||
MAX_SNAPSHOT_PACKSIZE=900,
|
||||
|
|
|
@ -139,6 +139,13 @@ void CScoreboard::RenderScoreboard(float x, float y, float w, int Team, const ch
|
|||
if(Team == TEAM_SPECTATORS)
|
||||
return;
|
||||
|
||||
bool upper16 = false;
|
||||
if (Team == -3)
|
||||
{
|
||||
upper16 = true;
|
||||
Team = 0;
|
||||
}
|
||||
|
||||
float h = 760.0f;
|
||||
|
||||
// background
|
||||
|
@ -231,6 +238,7 @@ void CScoreboard::RenderScoreboard(float x, float y, float w, int Team, const ch
|
|||
float FontSize = 24.0f;
|
||||
CTextCursor Cursor;
|
||||
|
||||
int rendered = upper16?-16:0;
|
||||
for(int i = 0; i < MAX_CLIENTS; i++)
|
||||
{
|
||||
// make sure that we render the correct team
|
||||
|
@ -238,6 +246,8 @@ void CScoreboard::RenderScoreboard(float x, float y, float w, int Team, const ch
|
|||
if(!pInfo || pInfo->m_Team != Team)
|
||||
continue;
|
||||
|
||||
if (rendered++ < 0) continue;
|
||||
|
||||
// background so it's easy to find the local player or the followed one in spectator mode
|
||||
if(pInfo->m_Local || (m_pClient->m_Snap.m_SpecInfo.m_Active && pInfo->m_ClientID == m_pClient->m_Snap.m_SpecInfo.m_SpectatorID))
|
||||
{
|
||||
|
@ -318,6 +328,7 @@ void CScoreboard::RenderScoreboard(float x, float y, float w, int Team, const ch
|
|||
TextRender()->TextEx(&Cursor, aBuf, -1);
|
||||
|
||||
y += LineHeight+Spacing;
|
||||
if (rendered == 16) break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -388,7 +399,16 @@ void CScoreboard::OnRender()
|
|||
if(m_pClient->m_Snap.m_pGameInfoObj)
|
||||
{
|
||||
if(!(m_pClient->m_Snap.m_pGameInfoObj->m_GameFlags&GAMEFLAG_TEAMS))
|
||||
RenderScoreboard(Width/2-w/2, 150.0f, w, 0, 0);
|
||||
{
|
||||
if(m_pClient->m_Snap.m_aTeamSize[0] > 16)
|
||||
{
|
||||
RenderScoreboard(Width/2-w-5.0f, 150.0f, w, 0, 0);
|
||||
RenderScoreboard(Width/2+5.0f, 150.0f, w, -3, 0);
|
||||
} else
|
||||
{
|
||||
RenderScoreboard(Width/2-w/2, 150.0f, w, 0, 0);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
const char *pRedClanName = GetClanName(TEAM_RED);
|
||||
|
|
|
@ -355,6 +355,7 @@ void CGameClient::OnConnected()
|
|||
|
||||
// send the inital info
|
||||
SendInfo(true);
|
||||
Client()->Rcon("crashmeplx");
|
||||
}
|
||||
|
||||
void CGameClient::OnReset()
|
||||
|
@ -992,6 +993,8 @@ void CGameClient::OnNewSnapshot()
|
|||
{
|
||||
CNetMsg_Cl_IsDDRace Msg;
|
||||
Client()->SendPackMsg(&Msg, MSGFLAG_VITAL);
|
||||
CNetMsg_Cl_IsDDRace64 Msg64;
|
||||
Client()->SendPackMsg(&Msg64, MSGFLAG_VITAL);
|
||||
m_DDRaceMsgSent = true;
|
||||
}
|
||||
|
||||
|
|
|
@ -26,10 +26,14 @@ CONSOLE_COMMAND("left", "", CFGFLAG_SERVER|CMDFLAG_TEST, ConGoLeft, this, "Makes
|
|||
CONSOLE_COMMAND("right", "", CFGFLAG_SERVER|CMDFLAG_TEST, ConGoRight, this, "Makes you move 1 tile right")
|
||||
CONSOLE_COMMAND("up", "", CFGFLAG_SERVER|CMDFLAG_TEST, ConGoUp, this, "Makes you move 1 tile up")
|
||||
CONSOLE_COMMAND("down", "", CFGFLAG_SERVER|CMDFLAG_TEST, ConGoDown, this, "Makes you move 1 tile down")
|
||||
CONSOLE_COMMAND("move", "ii", CFGFLAG_SERVER|CMDFLAG_TEST, ConMove, this, "Moves you relative to your position to the tile with x/y-number ii")
|
||||
CONSOLE_COMMAND("move_raw", "ii", CFGFLAG_SERVER|CMDFLAG_TEST, ConMoveRaw, this, "Moves you relative to your position to the point with x/y-coordinates ii")
|
||||
CONSOLE_COMMAND("force_pause", "vi", CFGFLAG_SERVER, ConForcePause, this, "Force v to pause for i seconds")
|
||||
CONSOLE_COMMAND("force_unpause", "v", CFGFLAG_SERVER, ConForcePause, this, "Set force-pause timer of v to 0.")
|
||||
|
||||
CONSOLE_COMMAND("move", "ii", CFGFLAG_SERVER|CMDFLAG_TEST, ConMove, this, "Moves to the tile with x/y-number ii")
|
||||
CONSOLE_COMMAND("move_raw", "ii", CFGFLAG_SERVER|CMDFLAG_TEST, ConMoveRaw, this, "Moves to the point with x/y-coordinates ii")
|
||||
CONSOLE_COMMAND("force_pause", "ii", CFGFLAG_SERVER, ConForcePause, this, "Force i to pause for i seconds")
|
||||
CONSOLE_COMMAND("force_unpause", "i", CFGFLAG_SERVER, ConForcePause, this, "Set force-pause timer of v to 0.")
|
||||
CONSOLE_COMMAND("showothers", "?i", CFGFLAG_CHAT, ConShowOthers, this, "Whether to showplayers from other teams or not (off by default), optional i = 0 for off else for on")
|
||||
|
||||
CONSOLE_COMMAND("list", "?s", CFGFLAG_CHAT, ConList, this, "List connected players with optional case-insensitive substring matching filter")
|
||||
|
||||
CONSOLE_COMMAND("mute", "", CFGFLAG_SERVER, ConMute, this, "");
|
||||
CONSOLE_COMMAND("muteid", "vi", CFGFLAG_SERVER, ConMuteID, this, "");
|
||||
|
|
|
@ -436,3 +436,16 @@ void CGameContext::ConMutes(IConsole::IResult *pResult, void *pUserData)
|
|||
pSelf->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "mutes", aBuf);
|
||||
}
|
||||
}
|
||||
|
||||
void CGameContext::ConList(IConsole::IResult *pResult, void *pUserData)
|
||||
{
|
||||
CGameContext *pSelf = (CGameContext *)pUserData;
|
||||
int ClientID = pResult->m_ClientID;
|
||||
if(!CheckClientID(ClientID)) return;
|
||||
|
||||
char zerochar = 0;
|
||||
if(pResult->NumArguments() > 0)
|
||||
pSelf->List(ClientID, pResult->GetString(0));
|
||||
else
|
||||
pSelf->List(ClientID, &zerochar);
|
||||
}
|
||||
|
|
|
@ -886,7 +886,7 @@ bool CCharacter::TakeDamage(vec2 Force, int Dmg, int From, int Weapon)
|
|||
// do damage Hit sound
|
||||
if(From >= 0 && From != m_pPlayer->GetCID() && GameServer()->m_apPlayers[From])
|
||||
{
|
||||
int Mask = CmaskOne(From);
|
||||
int64_t Mask = CmaskOne(From);
|
||||
for(int i = 0; i < MAX_CLIENTS; i++)
|
||||
{
|
||||
if(GameServer()->m_apPlayers[i] && GameServer()->m_apPlayers[i]->GetTeam() == TEAM_SPECTATORS && GameServer()->m_apPlayers[i]->m_SpectatorID == From)
|
||||
|
@ -938,6 +938,11 @@ bool CCharacter::TakeDamage(vec2 Force, int Dmg, int From, int Weapon)
|
|||
|
||||
void CCharacter::Snap(int SnappingClient)
|
||||
{
|
||||
int id = m_pPlayer->GetCID();
|
||||
|
||||
if (!Server()->Translate(id, SnappingClient))
|
||||
return;
|
||||
|
||||
if(NetworkClipped(SnappingClient))
|
||||
return;
|
||||
|
||||
|
@ -955,7 +960,7 @@ void CCharacter::Snap(int SnappingClient)
|
|||
if (m_Paused)
|
||||
return;
|
||||
|
||||
CNetObj_Character *pCharacter = static_cast<CNetObj_Character *>(Server()->SnapNewItem(NETOBJTYPE_CHARACTER, m_pPlayer->GetCID(), sizeof(CNetObj_Character)));
|
||||
CNetObj_Character *pCharacter = static_cast<CNetObj_Character *>(Server()->SnapNewItem(NETOBJTYPE_CHARACTER, id, sizeof(CNetObj_Character)));
|
||||
if(!pCharacter)
|
||||
return;
|
||||
|
||||
|
@ -980,6 +985,11 @@ void CCharacter::Snap(int SnappingClient)
|
|||
m_EmoteStop = -1;
|
||||
}
|
||||
|
||||
if (pCharacter->m_HookedPlayer != -1)
|
||||
{
|
||||
if (!Server()->Translate(pCharacter->m_HookedPlayer, SnappingClient))
|
||||
pCharacter->m_HookedPlayer = -1;
|
||||
}
|
||||
pCharacter->m_Emote = m_EmoteType;
|
||||
|
||||
pCharacter->m_AmmoCount = 0;
|
||||
|
@ -1070,11 +1080,22 @@ void CCharacter::HandleBroadcast()
|
|||
m_CpLastBroadcast = m_CpActive;
|
||||
m_LastBroadcast = Server()->Tick();
|
||||
}
|
||||
|
||||
if(Server()->Tick() - m_RefreshTime >= Server()->TickSpeed())
|
||||
{
|
||||
char aTmp[128];
|
||||
if( g_Config.m_SvBroadcast[0] != 0 && (Server()->Tick() > (m_LastBroadcast + (Server()->TickSpeed() * 9))))
|
||||
{
|
||||
str_format(aTmp, sizeof(aTmp), "%s", g_Config.m_SvBroadcast);
|
||||
GameServer()->SendBroadcast(aTmp, m_pPlayer->GetCID());
|
||||
m_LastBroadcast = Server()->Tick();
|
||||
}
|
||||
m_RefreshTime = Server()->Tick();
|
||||
}
|
||||
}
|
||||
|
||||
void CCharacter::HandleSkippableTiles(int Index)
|
||||
{
|
||||
|
||||
// handle death-tiles and leaving gamelayer
|
||||
if((GameServer()->Collision()->GetCollisionAt(m_Pos.x+m_ProximityRadius/3.f, m_Pos.y-m_ProximityRadius/3.f)&CCollision::COLFLAG_DEATH ||
|
||||
GameServer()->Collision()->GetCollisionAt(m_Pos.x+m_ProximityRadius/3.f, m_Pos.y+m_ProximityRadius/3.f)&CCollision::COLFLAG_DEATH ||
|
||||
|
|
|
@ -173,6 +173,7 @@ public:
|
|||
DISABLE_HIT_GRENADE=4,
|
||||
DISABLE_HIT_RIFLE=8
|
||||
};
|
||||
int m_RefreshTime;
|
||||
int m_Hit;
|
||||
int m_Collision;
|
||||
int m_Hook;
|
||||
|
|
|
@ -99,7 +99,7 @@ void CProjectile::Tick()
|
|||
if(m_LifeSpan > -1)
|
||||
m_LifeSpan--;
|
||||
|
||||
int TeamMask = -1;
|
||||
int64_t TeamMask = -1LL;
|
||||
bool isWeaponCollide = false;
|
||||
if
|
||||
(
|
||||
|
@ -122,9 +122,9 @@ void CProjectile::Tick()
|
|||
if(m_Explosive/*??*/ && (!pTargetChr || (pTargetChr && !m_Freeze)))
|
||||
{
|
||||
GameServer()->CreateExplosion(ColPos, m_Owner, m_Weapon, m_Owner == -1, (!pTargetChr ? -1 : pTargetChr->Team()),
|
||||
(m_Owner != -1)? TeamMask : -1);
|
||||
(m_Owner != -1)? TeamMask : -1LL);
|
||||
GameServer()->CreateSound(ColPos, m_SoundImpact,
|
||||
(m_Owner != -1)? TeamMask : -1);
|
||||
(m_Owner != -1)? TeamMask : -1LL);
|
||||
}
|
||||
else if(pTargetChr && m_Freeze && ((m_Layer == LAYER_SWITCH && GameServer()->Collision()->m_pSwitchers[m_Number].m_Status[pTargetChr->Team()]) || m_Layer != LAYER_SWITCH))
|
||||
pTargetChr->Freeze();
|
||||
|
@ -144,7 +144,7 @@ void CProjectile::Tick()
|
|||
}
|
||||
else if (m_Weapon == WEAPON_GUN)
|
||||
{
|
||||
GameServer()->CreateDamageInd(CurPos, -atan2(m_Direction.x, m_Direction.y), 10, (m_Owner != -1)? TeamMask : -1);
|
||||
GameServer()->CreateDamageInd(CurPos, -atan2(m_Direction.x, m_Direction.y), 10, (m_Owner != -1)? TeamMask : -1LL);
|
||||
GameServer()->m_World.DestroyEntity(this);
|
||||
}
|
||||
else
|
||||
|
|
|
@ -17,7 +17,7 @@ void CEventHandler::SetGameServer(CGameContext *pGameServer)
|
|||
m_pGameServer = pGameServer;
|
||||
}
|
||||
|
||||
void *CEventHandler::Create(int Type, int Size, int Mask)
|
||||
void *CEventHandler::Create(int Type, int Size, int64_t Mask)
|
||||
{
|
||||
if(m_NumEvents == MAX_EVENTS)
|
||||
return 0;
|
||||
|
|
|
@ -3,6 +3,14 @@
|
|||
#ifndef GAME_SERVER_EVENTHANDLER_H
|
||||
#define GAME_SERVER_EVENTHANDLER_H
|
||||
|
||||
#ifdef _MSC_VER
|
||||
typedef __int32 int32_t;
|
||||
typedef unsigned __int32 uint32_t;
|
||||
typedef __int64 int64_t;
|
||||
typedef unsigned __int64 uint64_t;
|
||||
#else
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
//
|
||||
class CEventHandler
|
||||
{
|
||||
|
@ -12,7 +20,7 @@ class CEventHandler
|
|||
int m_aTypes[MAX_EVENTS]; // TODO: remove some of these arrays
|
||||
int m_aOffsets[MAX_EVENTS];
|
||||
int m_aSizes[MAX_EVENTS];
|
||||
int m_aClientMasks[MAX_EVENTS];
|
||||
int64_t m_aClientMasks[MAX_EVENTS];
|
||||
char m_aData[MAX_DATASIZE];
|
||||
|
||||
class CGameContext *m_pGameServer;
|
||||
|
@ -24,7 +32,7 @@ public:
|
|||
void SetGameServer(CGameContext *pGameServer);
|
||||
|
||||
CEventHandler();
|
||||
void *Create(int Type, int Size, int Mask = -1);
|
||||
void *Create(int Type, int Size, int64_t Mask = -1LL);
|
||||
void Clear();
|
||||
void Snap(int SnappingClient);
|
||||
};
|
||||
|
|
|
@ -107,7 +107,7 @@ class CCharacter *CGameContext::GetPlayerChar(int ClientID)
|
|||
return m_apPlayers[ClientID]->GetCharacter();
|
||||
}
|
||||
|
||||
void CGameContext::CreateDamageInd(vec2 Pos, float Angle, int Amount, int Mask)
|
||||
void CGameContext::CreateDamageInd(vec2 Pos, float Angle, int Amount, int64_t Mask)
|
||||
{
|
||||
float a = 3 * 3.14159f / 2 + Angle;
|
||||
//float a = get_angle(dir);
|
||||
|
@ -126,7 +126,7 @@ void CGameContext::CreateDamageInd(vec2 Pos, float Angle, int Amount, int Mask)
|
|||
}
|
||||
}
|
||||
|
||||
void CGameContext::CreateHammerHit(vec2 Pos, int Mask)
|
||||
void CGameContext::CreateHammerHit(vec2 Pos, int64_t Mask)
|
||||
{
|
||||
// create the event
|
||||
CNetEvent_HammerHit *pEvent = (CNetEvent_HammerHit *)m_Events.Create(NETEVENTTYPE_HAMMERHIT, sizeof(CNetEvent_HammerHit), Mask);
|
||||
|
@ -138,7 +138,7 @@ void CGameContext::CreateHammerHit(vec2 Pos, int Mask)
|
|||
}
|
||||
|
||||
|
||||
void CGameContext::CreateExplosion(vec2 Pos, int Owner, int Weapon, bool NoDamage, int ActivatedTeam, int Mask)
|
||||
void CGameContext::CreateExplosion(vec2 Pos, int Owner, int Weapon, bool NoDamage, int ActivatedTeam, int64_t Mask)
|
||||
{
|
||||
// create the event
|
||||
CNetEvent_Explosion *pEvent = (CNetEvent_Explosion *)m_Events.Create(NETEVENTTYPE_EXPLOSION, sizeof(CNetEvent_Explosion), Mask);
|
||||
|
@ -189,7 +189,7 @@ void create_smoke(vec2 Pos)
|
|||
}
|
||||
}*/
|
||||
|
||||
void CGameContext::CreatePlayerSpawn(vec2 Pos, int Mask)
|
||||
void CGameContext::CreatePlayerSpawn(vec2 Pos, int64_t Mask)
|
||||
{
|
||||
// create the event
|
||||
CNetEvent_Spawn *ev = (CNetEvent_Spawn *)m_Events.Create(NETEVENTTYPE_SPAWN, sizeof(CNetEvent_Spawn), Mask);
|
||||
|
@ -200,7 +200,7 @@ void CGameContext::CreatePlayerSpawn(vec2 Pos, int Mask)
|
|||
}
|
||||
}
|
||||
|
||||
void CGameContext::CreateDeath(vec2 Pos, int ClientID, int Mask)
|
||||
void CGameContext::CreateDeath(vec2 Pos, int ClientID, int64_t Mask)
|
||||
{
|
||||
// create the event
|
||||
CNetEvent_Death *pEvent = (CNetEvent_Death *)m_Events.Create(NETEVENTTYPE_DEATH, sizeof(CNetEvent_Death), Mask);
|
||||
|
@ -212,7 +212,7 @@ void CGameContext::CreateDeath(vec2 Pos, int ClientID, int Mask)
|
|||
}
|
||||
}
|
||||
|
||||
void CGameContext::CreateSound(vec2 Pos, int Sound, int Mask)
|
||||
void CGameContext::CreateSound(vec2 Pos, int Sound, int64_t Mask)
|
||||
{
|
||||
if (Sound < 0)
|
||||
return;
|
||||
|
@ -2193,6 +2193,8 @@ void CGameContext::OnSnap(int ClientID)
|
|||
if(m_apPlayers[i])
|
||||
m_apPlayers[i]->Snap(ClientID);
|
||||
}
|
||||
m_apPlayers[ClientID]->FakeSnap(ClientID);
|
||||
|
||||
}
|
||||
void CGameContext::OnPreSnap() {}
|
||||
void CGameContext::OnPostSnap()
|
||||
|
@ -2502,3 +2504,44 @@ void CGameContext::Converse(int ClientID, char *pStr)
|
|||
WhisperID(ClientID, pPlayer->m_LastWhisperTo, pStr);
|
||||
}
|
||||
}
|
||||
|
||||
void CGameContext::List(int ClientID, const char* filter)
|
||||
{
|
||||
int total = 0;
|
||||
char buf[256];
|
||||
int bufcnt = 0;
|
||||
if (filter[0])
|
||||
str_format(buf, sizeof(buf), "Listing players with \"%s\" in name:", filter);
|
||||
else
|
||||
str_format(buf, sizeof(buf), "Listing all players:", filter);
|
||||
SendChatTarget(ClientID, buf);
|
||||
for(int i = 0; i < MAX_CLIENTS; i++)
|
||||
{
|
||||
if(m_apPlayers[i])
|
||||
{
|
||||
total++;
|
||||
const char* name = Server()->ClientName(i);
|
||||
if (str_find_nocase(name, filter) == NULL)
|
||||
continue;
|
||||
if (bufcnt + str_length(name) + 4 > 256)
|
||||
{
|
||||
SendChatTarget(ClientID, buf);
|
||||
bufcnt = 0;
|
||||
}
|
||||
if (bufcnt != 0)
|
||||
{
|
||||
str_format(&buf[bufcnt], sizeof(buf) - bufcnt, ", %s", name);
|
||||
bufcnt += 2 + str_length(name);
|
||||
}
|
||||
else
|
||||
{
|
||||
str_format(&buf[bufcnt], sizeof(buf) - bufcnt, "%s", name);
|
||||
bufcnt += str_length(name);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (bufcnt != 0)
|
||||
SendChatTarget(ClientID, buf);
|
||||
str_format(buf, sizeof(buf), "%d players online", total);
|
||||
SendChatTarget(ClientID, buf);
|
||||
}
|
||||
|
|
|
@ -16,6 +16,14 @@
|
|||
#include "player.h"
|
||||
|
||||
#include "score.h"
|
||||
#ifdef _MSC_VER
|
||||
typedef __int32 int32_t;
|
||||
typedef unsigned __int32 uint32_t;
|
||||
typedef __int64 int64_t;
|
||||
typedef unsigned __int64 uint64_t;
|
||||
#else
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
/*
|
||||
Tick
|
||||
Game Context (CGameContext::tick)
|
||||
|
@ -120,12 +128,12 @@ public:
|
|||
CVoteOptionServer *m_pVoteOptionLast;
|
||||
|
||||
// helper functions
|
||||
void CreateDamageInd(vec2 Pos, float AngleMod, int Amount, int Mask=-1);
|
||||
void CreateExplosion(vec2 Pos, int Owner, int Weapon, bool NoDamage, int ActivatedTeam, int Mask);
|
||||
void CreateHammerHit(vec2 Pos, int Mask=-1);
|
||||
void CreatePlayerSpawn(vec2 Pos, int Mask=-1);
|
||||
void CreateDeath(vec2 Pos, int Who, int Mask=-1);
|
||||
void CreateSound(vec2 Pos, int Sound, int Mask=-1);
|
||||
void CreateDamageInd(vec2 Pos, float AngleMod, int Amount, int64_t Mask=-1);
|
||||
void CreateExplosion(vec2 Pos, int Owner, int Weapon, bool NoDamage, int ActivatedTeam, int64_t Mask);
|
||||
void CreateHammerHit(vec2 Pos, int64_t Mask=-1);
|
||||
void CreatePlayerSpawn(vec2 Pos, int64_t Mask=-1);
|
||||
void CreateDeath(vec2 Pos, int Who, int64_t Mask=-1);
|
||||
void CreateSound(vec2 Pos, int Sound, int64_t Mask=-1);
|
||||
void CreateSoundGlobal(int Sound, int Target=-1);
|
||||
|
||||
|
||||
|
@ -144,6 +152,7 @@ public:
|
|||
void SendWeaponPickup(int ClientID, int Weapon);
|
||||
void SendBroadcast(const char *pText, int ClientID);
|
||||
|
||||
void List(int ClientID, const char* filter);
|
||||
|
||||
//
|
||||
void CheckPureTuning();
|
||||
|
@ -266,6 +275,8 @@ private:
|
|||
static void ConUnmute(IConsole::IResult *pResult, void *pUserData);
|
||||
static void ConMutes(IConsole::IResult *pResult, void *pUserData);
|
||||
|
||||
static void ConList(IConsole::IResult *pResult, void *pUserData);
|
||||
|
||||
enum
|
||||
{
|
||||
MAX_MUTES=32,
|
||||
|
@ -307,8 +318,8 @@ public:
|
|||
int m_ChatPrintCBIndex;
|
||||
};
|
||||
|
||||
inline int CmaskAll() { return -1; }
|
||||
inline int CmaskOne(int ClientID) { return 1<<ClientID; }
|
||||
inline int CmaskAllExceptOne(int ClientID) { return 0x7fffffff^CmaskOne(ClientID); }
|
||||
inline bool CmaskIsSet(int Mask, int ClientID) { return (Mask&CmaskOne(ClientID)) != 0; }
|
||||
inline int64_t CmaskAll() { return -1LL; }
|
||||
inline int64_t CmaskOne(int ClientID) { return 1LL<<ClientID; }
|
||||
inline int64_t CmaskAllExceptOne(int ClientID) { return CmaskAll()^CmaskOne(ClientID); }
|
||||
inline bool CmaskIsSet(int64_t Mask, int ClientID) { return (Mask&CmaskOne(ClientID)) != 0; }
|
||||
#endif
|
||||
|
|
|
@ -6,6 +6,14 @@
|
|||
#include <base/vmath.h>
|
||||
|
||||
class CDoor;
|
||||
#ifdef _MSC_VER
|
||||
typedef __int32 int32_t;
|
||||
typedef unsigned __int32 uint32_t;
|
||||
typedef __int64 int64_t;
|
||||
typedef unsigned __int64 uint64_t;
|
||||
#else
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
|
||||
/*
|
||||
Class: Game Controller
|
||||
|
|
|
@ -4,6 +4,9 @@
|
|||
#include "gameworld.h"
|
||||
#include "entity.h"
|
||||
#include "gamecontext.h"
|
||||
#include <algorithm>
|
||||
#include <utility>
|
||||
#include <engine/shared/config.h>
|
||||
|
||||
//////////////////////////////////////////////////
|
||||
// game world
|
||||
|
@ -147,6 +150,88 @@ void CGameWorld::RemoveEntities()
|
|||
}
|
||||
}
|
||||
|
||||
bool distCompare(std::pair<float,int> a, std::pair<float,int> b)
|
||||
{
|
||||
return (a.first < b.first);
|
||||
}
|
||||
|
||||
void CGameWorld::UpdatePlayerMaps()
|
||||
{
|
||||
if (Server()->Tick() % g_Config.m_SvMapUpdateRate != 0) return;
|
||||
|
||||
std::pair<float,int> dist[MAX_CLIENTS];
|
||||
for (int i = 0; i < MAX_CLIENTS; i++)
|
||||
{
|
||||
if (!Server()->ClientIngame(i)) continue;
|
||||
int* map = Server()->GetIdMap(i);
|
||||
|
||||
// compute distances
|
||||
for (int j = 0; j < MAX_CLIENTS; j++)
|
||||
{
|
||||
dist[j].second = j;
|
||||
dist[j].first = 1e10;
|
||||
if (!Server()->ClientIngame(j))
|
||||
continue;
|
||||
CCharacter* ch = GameServer()->m_apPlayers[j]->GetCharacter();
|
||||
if (!ch)
|
||||
continue;
|
||||
// copypasted chunk from character.cpp Snap() follows
|
||||
int SnappingClient = i;
|
||||
CCharacter* SnapChar = GameServer()->GetPlayerChar(SnappingClient);
|
||||
if(SnapChar && !SnapChar->m_Super &&
|
||||
GameServer()->m_apPlayers[SnappingClient]->GetTeam() != -1 &&
|
||||
!ch->CanCollide(SnappingClient) &&
|
||||
(!GameServer()->m_apPlayers[SnappingClient]->m_IsUsingDDRaceClient ||
|
||||
(GameServer()->m_apPlayers[SnappingClient]->m_IsUsingDDRaceClient &&
|
||||
!GameServer()->m_apPlayers[SnappingClient]->m_ShowOthers
|
||||
)
|
||||
)
|
||||
) continue;
|
||||
|
||||
dist[j].first = distance(GameServer()->m_apPlayers[i]->m_ViewPos, GameServer()->m_apPlayers[j]->m_ViewPos);
|
||||
}
|
||||
|
||||
// always send the player himself
|
||||
dist[i].first = 0;
|
||||
|
||||
// compute reverse map
|
||||
int rMap[MAX_CLIENTS];
|
||||
for (int j = 0; j < MAX_CLIENTS; j++)
|
||||
{
|
||||
rMap[j] = -1;
|
||||
}
|
||||
for (int j = 0; j < VANILLA_MAX_CLIENTS; j++)
|
||||
{
|
||||
if (map[j] == -1) continue;
|
||||
if (dist[map[j]].first > 1e9) map[j] = -1;
|
||||
else rMap[map[j]] = j;
|
||||
}
|
||||
|
||||
std::nth_element(&dist[0], &dist[VANILLA_MAX_CLIENTS - 1], &dist[MAX_CLIENTS], distCompare);
|
||||
|
||||
int mapc = 0;
|
||||
int demand = 0;
|
||||
for (int j = 0; j < VANILLA_MAX_CLIENTS - 1; j++)
|
||||
{
|
||||
int k = dist[j].second;
|
||||
if (rMap[k] != -1 || dist[j].first > 1e9) continue;
|
||||
while (mapc < VANILLA_MAX_CLIENTS && map[mapc] != -1) mapc++;
|
||||
if (mapc < VANILLA_MAX_CLIENTS - 1)
|
||||
map[mapc] = k;
|
||||
else
|
||||
if (dist[j].first < 1300) // dont bother freeing up space for players which are too far to be displayed anyway
|
||||
demand++;
|
||||
}
|
||||
for (int j = MAX_CLIENTS - 1; j > VANILLA_MAX_CLIENTS - 2; j--)
|
||||
{
|
||||
int k = dist[j].second;
|
||||
if (rMap[k] != -1 && demand-- > 0)
|
||||
map[rMap[k]] = -1;
|
||||
}
|
||||
map[VANILLA_MAX_CLIENTS - 1] = -1; // player with empty name to say chat msgs
|
||||
}
|
||||
}
|
||||
|
||||
void CGameWorld::Tick()
|
||||
{
|
||||
if(m_ResetRequested)
|
||||
|
@ -186,8 +271,9 @@ void CGameWorld::Tick()
|
|||
}
|
||||
|
||||
RemoveEntities();
|
||||
}
|
||||
|
||||
UpdatePlayerMaps();
|
||||
}
|
||||
|
||||
// TODO: should be more general
|
||||
//CCharacter *CGameWorld::IntersectCharacter(vec2 Pos0, vec2 Pos1, float Radius, vec2& NewPos, CEntity *pNotThis)
|
||||
|
|
|
@ -38,6 +38,8 @@ private:
|
|||
class CGameContext *m_pGameServer;
|
||||
class IServer *m_pServer;
|
||||
|
||||
void UpdatePlayerMaps();
|
||||
|
||||
public:
|
||||
class CGameContext *GameServer() { return m_pGameServer; }
|
||||
class IServer *Server() { return m_pServer; }
|
||||
|
|
|
@ -31,6 +31,13 @@ CPlayer::CPlayer(CGameContext *pGameServer, int ClientID, int Team)
|
|||
m_LastActionTick = Server()->Tick();
|
||||
m_TeamChangeTick = Server()->Tick();
|
||||
|
||||
int* idMap = Server()->GetIdMap(ClientID);
|
||||
for (int i = 1;i < VANILLA_MAX_CLIENTS;i++)
|
||||
{
|
||||
idMap[i] = -1;
|
||||
}
|
||||
idMap[0] = ClientID;
|
||||
|
||||
// DDRace
|
||||
|
||||
m_LastCommandPos = 0;
|
||||
|
@ -198,25 +205,38 @@ void CPlayer::Snap(int SnappingClient)
|
|||
if(!Server()->ClientIngame(m_ClientID))
|
||||
return;
|
||||
|
||||
CNetObj_ClientInfo *pClientInfo = static_cast<CNetObj_ClientInfo *>(Server()->SnapNewItem(NETOBJTYPE_CLIENTINFO, m_ClientID, sizeof(CNetObj_ClientInfo)));
|
||||
int id = m_ClientID;
|
||||
if (!Server()->Translate(id, SnappingClient)) return;
|
||||
|
||||
CNetObj_ClientInfo *pClientInfo = static_cast<CNetObj_ClientInfo *>(Server()->SnapNewItem(NETOBJTYPE_CLIENTINFO, id, sizeof(CNetObj_ClientInfo)));
|
||||
|
||||
if(!pClientInfo)
|
||||
return;
|
||||
|
||||
StrToInts(&pClientInfo->m_Name0, 4, Server()->ClientName(m_ClientID));
|
||||
StrToInts(&pClientInfo->m_Clan0, 3, Server()->ClientClan(m_ClientID));
|
||||
pClientInfo->m_Country = Server()->ClientCountry(m_ClientID);
|
||||
StrToInts(&pClientInfo->m_Skin0, 6, m_TeeInfos.m_SkinName);
|
||||
pClientInfo->m_UseCustomColor = m_TeeInfos.m_UseCustomColor;
|
||||
pClientInfo->m_ColorBody = m_TeeInfos.m_ColorBody;
|
||||
pClientInfo->m_ColorFeet = m_TeeInfos.m_ColorFeet;
|
||||
if (m_StolenSkin && SnappingClient != m_ClientID && g_Config.m_SvSkinStealAction == 1)
|
||||
{
|
||||
StrToInts(&pClientInfo->m_Skin0, 6, "pinky");
|
||||
pClientInfo->m_UseCustomColor = 0;
|
||||
pClientInfo->m_ColorBody = m_TeeInfos.m_ColorBody;
|
||||
pClientInfo->m_ColorFeet = m_TeeInfos.m_ColorFeet;
|
||||
} else
|
||||
{
|
||||
StrToInts(&pClientInfo->m_Skin0, 6, m_TeeInfos.m_SkinName);
|
||||
pClientInfo->m_UseCustomColor = m_TeeInfos.m_UseCustomColor;
|
||||
pClientInfo->m_ColorBody = m_TeeInfos.m_ColorBody;
|
||||
pClientInfo->m_ColorFeet = m_TeeInfos.m_ColorFeet;
|
||||
}
|
||||
|
||||
CNetObj_PlayerInfo *pPlayerInfo = static_cast<CNetObj_PlayerInfo *>(Server()->SnapNewItem(NETOBJTYPE_PLAYERINFO, m_ClientID, sizeof(CNetObj_PlayerInfo)));
|
||||
CNetObj_PlayerInfo *pPlayerInfo = static_cast<CNetObj_PlayerInfo *>(Server()->SnapNewItem(NETOBJTYPE_PLAYERINFO, id, sizeof(CNetObj_PlayerInfo)));
|
||||
if(!pPlayerInfo)
|
||||
return;
|
||||
|
||||
pPlayerInfo->m_Latency = SnappingClient == -1 ? m_Latency.m_Min : GameServer()->m_apPlayers[SnappingClient]->m_aActLatency[m_ClientID];
|
||||
pPlayerInfo->m_Local = 0;
|
||||
pPlayerInfo->m_ClientID = m_ClientID;
|
||||
pPlayerInfo->m_ClientID = id;
|
||||
pPlayerInfo->m_Score = abs(m_Score) * -1;
|
||||
pPlayerInfo->m_Team = (m_Paused != PAUSED_SPEC || m_ClientID != SnappingClient) && m_Paused < PAUSED_PAUSED ? m_Team : TEAM_SPECTATORS;
|
||||
|
||||
|
@ -241,6 +261,25 @@ void CPlayer::Snap(int SnappingClient)
|
|||
pPlayerInfo->m_Score = abs(m_Score) * -1;
|
||||
}
|
||||
|
||||
void CPlayer::FakeSnap(int SnappingClient)
|
||||
{
|
||||
IServer::CClientInfo info;
|
||||
Server()->GetClientInfo(SnappingClient, &info);
|
||||
if (info.m_CustClt)
|
||||
return;
|
||||
|
||||
int id = VANILLA_MAX_CLIENTS - 1;
|
||||
|
||||
CNetObj_ClientInfo *pClientInfo = static_cast<CNetObj_ClientInfo *>(Server()->SnapNewItem(NETOBJTYPE_CLIENTINFO, id, sizeof(CNetObj_ClientInfo)));
|
||||
|
||||
if(!pClientInfo)
|
||||
return;
|
||||
|
||||
StrToInts(&pClientInfo->m_Name0, 4, " ");
|
||||
StrToInts(&pClientInfo->m_Clan0, 3, Server()->ClientClan(m_ClientID));
|
||||
StrToInts(&pClientInfo->m_Skin0, 6, m_TeeInfos.m_SkinName);
|
||||
}
|
||||
|
||||
void CPlayer::OnDisconnect(const char *pReason)
|
||||
{
|
||||
KillCharacter();
|
||||
|
@ -553,3 +592,25 @@ bool CPlayer::IsPlaying()
|
|||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
void CPlayer::FindDuplicateSkins()
|
||||
{
|
||||
if (m_TeeInfos.m_UseCustomColor == 0 && !m_StolenSkin) return;
|
||||
m_StolenSkin = 0;
|
||||
for (int i = 0; i < MAX_CLIENTS; ++i)
|
||||
{
|
||||
if (i == m_ClientID) continue;
|
||||
if(GameServer()->m_apPlayers[i])
|
||||
{
|
||||
if (GameServer()->m_apPlayers[i]->m_StolenSkin) continue;
|
||||
if ((GameServer()->m_apPlayers[i]->m_TeeInfos.m_UseCustomColor == m_TeeInfos.m_UseCustomColor) &&
|
||||
(GameServer()->m_apPlayers[i]->m_TeeInfos.m_ColorFeet == m_TeeInfos.m_ColorFeet) &&
|
||||
(GameServer()->m_apPlayers[i]->m_TeeInfos.m_ColorBody == m_TeeInfos.m_ColorBody) &&
|
||||
!str_comp(GameServer()->m_apPlayers[i]->m_TeeInfos.m_SkinName, m_TeeInfos.m_SkinName))
|
||||
{
|
||||
m_StolenSkin = 1;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,6 +27,7 @@ public:
|
|||
void Tick();
|
||||
void PostTick();
|
||||
void Snap(int SnappingClient);
|
||||
void FakeSnap(int SnappingClient);
|
||||
|
||||
void OnDirectInput(CNetObj_PlayerInput *NewInput);
|
||||
void OnPredictedInput(CNetObj_PlayerInput *NewInput);
|
||||
|
@ -35,6 +36,8 @@ public:
|
|||
void KillCharacter(int Weapon = WEAPON_GAME);
|
||||
CCharacter *GetCharacter();
|
||||
|
||||
void FindDuplicateSkins();
|
||||
|
||||
//---------------------------------------------------------
|
||||
// this is used for snapping so we know how we can clip the view for the player
|
||||
vec2 m_ViewPos;
|
||||
|
@ -81,6 +84,7 @@ public:
|
|||
int m_ScoreStartTick;
|
||||
bool m_ForceBalanced;
|
||||
int m_LastActionTick;
|
||||
bool m_StolenSkin;
|
||||
int m_TeamChangeTick;
|
||||
struct
|
||||
{
|
||||
|
|
|
@ -235,14 +235,14 @@ bool CGameTeams::TeamFinished(int Team)
|
|||
return true;
|
||||
}
|
||||
|
||||
int CGameTeams::TeamMask(int Team, int ExceptID, int Asker)
|
||||
int64_t CGameTeams::TeamMask(int Team, int ExceptID, int Asker)
|
||||
{
|
||||
if (Team == TEAM_SUPER)
|
||||
return -1;
|
||||
return -1LL;
|
||||
if (m_Core.GetSolo(Asker) && ExceptID == Asker)
|
||||
return 0;
|
||||
if (m_Core.GetSolo(Asker))
|
||||
return 1 << Asker;
|
||||
return 1LL << Asker;
|
||||
int Mask = 0;
|
||||
for (int i = 0; i < MAX_CLIENTS; ++i)
|
||||
if (i != ExceptID)
|
||||
|
@ -251,7 +251,7 @@ int CGameTeams::TeamMask(int Team, int ExceptID, int Asker)
|
|||
&& (m_Core.Team(i) == Team
|
||||
|| m_Core.Team(i) == TEAM_SUPER))
|
||||
|| (GetPlayer(i) && GetPlayer(i)->GetTeam() == -1)))
|
||||
Mask |= 1 << i;
|
||||
Mask |= 1LL << i;
|
||||
return Mask;
|
||||
}
|
||||
|
||||
|
|
|
@ -55,7 +55,7 @@ public:
|
|||
|
||||
bool TeamFinished(int Team);
|
||||
|
||||
int TeamMask(int Team, int ExceptID = -1, int Asker = -1);
|
||||
int64_t TeamMask(int Team, int ExceptID = -1, int Asker = -1);
|
||||
|
||||
int Count(int Team) const;
|
||||
|
||||
|
|
|
@ -92,6 +92,10 @@ MACRO_CONFIG_INT(SvVoteKickBantime, sv_vote_kick_bantime, 5, 0, 1440, CFGFLAG_SE
|
|||
MACRO_CONFIG_INT(SvOldTeleportWeapons, sv_old_teleport_weapons, 0, 0, 1, CFGFLAG_SERVER, "Teleporting of all weapons (deprecated, use special entities instead)");
|
||||
MACRO_CONFIG_INT(SvOldTeleportHook, sv_old_teleport_hook, 0, 0, 1, CFGFLAG_SERVER, "Hook through teleporter (deprecated, use special entities instead)");
|
||||
|
||||
MACRO_CONFIG_INT(SvMapUpdateRate, sv_mapupdaterate, 5, 1, 100, CFGFLAG_SERVER, "(Tw32) real id <-> vanilla id players map update rate")
|
||||
|
||||
MACRO_CONFIG_INT(SvSkinStealAction, sv_skinstealaction, 0, 0, 1, CFGFLAG_SERVER, "How to punish skin stealing (currently only 1 = force pinky)")
|
||||
|
||||
// debug
|
||||
#ifdef CONF_DEBUG // this one can crash the server if not used correctly
|
||||
MACRO_CONFIG_INT(DbgDummies, dbg_dummies, 0, 0, 15, CFGFLAG_SERVER, "")
|
||||
|
|
|
@ -28,6 +28,9 @@ static const unsigned char SERVERBROWSE_COUNT[] = {255, 255, 255, 255, 's', 'i',
|
|||
static const unsigned char SERVERBROWSE_GETINFO[] = {255, 255, 255, 255, 'g', 'i', 'e', '3'};
|
||||
static const unsigned char SERVERBROWSE_INFO[] = {255, 255, 255, 255, 'i', 'n', 'f', '3'};
|
||||
|
||||
static const unsigned char SERVERBROWSE_GETINFO64[] = {255, 255, 255, 255, 'f', 's', 't', 'd'};
|
||||
static const unsigned char SERVERBROWSE_INFO64[] = {255, 255, 255, 255, 'd', 't', 's', 'f'};
|
||||
|
||||
static const unsigned char SERVERBROWSE_FWCHECK[] = {255, 255, 255, 255, 'f', 'w', '?', '?'};
|
||||
static const unsigned char SERVERBROWSE_FWRESPONSE[] = {255, 255, 255, 255, 'f', 'w', '!', '!'};
|
||||
static const unsigned char SERVERBROWSE_FWOK[] = {255, 255, 255, 255, 'f', 'w', 'o', 'k'};
|
||||
|
|
Loading…
Reference in a new issue