diff --git a/datasrc/network.py b/datasrc/network.py index 166d3f6ea..008893252 100644 --- a/datasrc/network.py +++ b/datasrc/network.py @@ -377,8 +377,8 @@ Messages = [ NetIntAny("m_Tee14"), NetIntAny("m_Tee15"), ]), - NetMessage("Cl_ShowOthers", [ NetBool("m_Show"), ]), + NetMessage("Cl_IsDDRace64", []), ] diff --git a/src/engine/server.h b/src/engine/server.h index 191a0a085..3d2e797dc 100644 --- a/src/engine/server.h +++ b/src/engine/server.h @@ -4,6 +4,8 @@ #define ENGINE_SERVER_H #include "kernel.h" #include "message.h" +#include +#include 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 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 + 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 + 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 diff --git a/src/engine/server/server.cpp b/src/engine/server/server.cpp index 84bdd4dba..9e3cd46b1 100644 --- a/src/engine/server/server.cpp +++ b/src/engine/server/server.cpp @@ -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; +} diff --git a/src/engine/server/server.h b/src/engine/server/server.h index 95c95059b..75016847e 100644 --- a/src/engine/server/server.h +++ b/src/engine/server/server.h @@ -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 diff --git a/src/engine/shared/config_variables.h b/src/engine/shared/config_variables.h index 15935b641..6a254c556 100644 --- a/src/engine/shared/config_variables.h +++ b/src/engine/shared/config_variables.h @@ -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 diff --git a/src/engine/shared/console.cpp b/src/engine/shared/console.cpp index 76a9605f9..d094b430d 100644 --- a/src/engine/shared/console.cpp +++ b/src/engine/shared/console.cpp @@ -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; } } } diff --git a/src/engine/shared/network.h b/src/engine/shared/network.h index 259d600f2..f7b1ae2ba 100644 --- a/src/engine/shared/network.h +++ b/src/engine/shared/network.h @@ -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, diff --git a/src/engine/shared/protocol.h b/src/engine/shared/protocol.h index ba04da8af..6034edef2 100644 --- a/src/engine/shared/protocol.h +++ b/src/engine/shared/protocol.h @@ -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, diff --git a/src/game/client/components/scoreboard.cpp b/src/game/client/components/scoreboard.cpp index fec096595..01ea14b4c 100644 --- a/src/game/client/components/scoreboard.cpp +++ b/src/game/client/components/scoreboard.cpp @@ -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); diff --git a/src/game/client/gameclient.cpp b/src/game/client/gameclient.cpp index 655f6ded1..80b82c2fb 100644 --- a/src/game/client/gameclient.cpp +++ b/src/game/client/gameclient.cpp @@ -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; } diff --git a/src/game/ddracecommands.h b/src/game/ddracecommands.h index 05b1574c4..883bf3eae 100644 --- a/src/game/ddracecommands.h +++ b/src/game/ddracecommands.h @@ -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, ""); diff --git a/src/game/server/ddracecommands.cpp b/src/game/server/ddracecommands.cpp index 2d668645c..563a4ab9a 100644 --- a/src/game/server/ddracecommands.cpp +++ b/src/game/server/ddracecommands.cpp @@ -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); +} diff --git a/src/game/server/entities/character.cpp b/src/game/server/entities/character.cpp index 28c4ed132..bc29fb960 100644 --- a/src/game/server/entities/character.cpp +++ b/src/game/server/entities/character.cpp @@ -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(Server()->SnapNewItem(NETOBJTYPE_CHARACTER, m_pPlayer->GetCID(), sizeof(CNetObj_Character))); + CNetObj_Character *pCharacter = static_cast(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 || diff --git a/src/game/server/entities/character.h b/src/game/server/entities/character.h index c3bc40a88..1fe475191 100644 --- a/src/game/server/entities/character.h +++ b/src/game/server/entities/character.h @@ -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; diff --git a/src/game/server/entities/projectile.cpp b/src/game/server/entities/projectile.cpp index 82737794c..856cfe57e 100644 --- a/src/game/server/entities/projectile.cpp +++ b/src/game/server/entities/projectile.cpp @@ -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 diff --git a/src/game/server/eventhandler.cpp b/src/game/server/eventhandler.cpp index e3fa90f11..3f307c2f5 100644 --- a/src/game/server/eventhandler.cpp +++ b/src/game/server/eventhandler.cpp @@ -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; diff --git a/src/game/server/eventhandler.h b/src/game/server/eventhandler.h index 721b59afa..e3a62c515 100644 --- a/src/game/server/eventhandler.h +++ b/src/game/server/eventhandler.h @@ -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 +#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); }; diff --git a/src/game/server/gamecontext.cpp b/src/game/server/gamecontext.cpp index b915124af..a4ffe69ef 100644 --- a/src/game/server/gamecontext.cpp +++ b/src/game/server/gamecontext.cpp @@ -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); +} diff --git a/src/game/server/gamecontext.h b/src/game/server/gamecontext.h index 7a404b0da..4be3dd0e0 100644 --- a/src/game/server/gamecontext.h +++ b/src/game/server/gamecontext.h @@ -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 +#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< 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 +#endif /* Class: Game Controller diff --git a/src/game/server/gameworld.cpp b/src/game/server/gameworld.cpp index 260c4d00b..02a73a36e 100644 --- a/src/game/server/gameworld.cpp +++ b/src/game/server/gameworld.cpp @@ -4,6 +4,9 @@ #include "gameworld.h" #include "entity.h" #include "gamecontext.h" +#include +#include +#include ////////////////////////////////////////////////// // game world @@ -147,6 +150,88 @@ void CGameWorld::RemoveEntities() } } +bool distCompare(std::pair a, std::pair b) +{ + return (a.first < b.first); +} + +void CGameWorld::UpdatePlayerMaps() +{ + if (Server()->Tick() % g_Config.m_SvMapUpdateRate != 0) return; + + std::pair 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) diff --git a/src/game/server/gameworld.h b/src/game/server/gameworld.h index 492362610..a433e7640 100644 --- a/src/game/server/gameworld.h +++ b/src/game/server/gameworld.h @@ -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; } diff --git a/src/game/server/player.cpp b/src/game/server/player.cpp index 79d1a13d7..6a27b1f60 100644 --- a/src/game/server/player.cpp +++ b/src/game/server/player.cpp @@ -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(Server()->SnapNewItem(NETOBJTYPE_CLIENTINFO, m_ClientID, sizeof(CNetObj_ClientInfo))); + int id = m_ClientID; + if (!Server()->Translate(id, SnappingClient)) return; + + CNetObj_ClientInfo *pClientInfo = static_cast(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(Server()->SnapNewItem(NETOBJTYPE_PLAYERINFO, m_ClientID, sizeof(CNetObj_PlayerInfo))); + CNetObj_PlayerInfo *pPlayerInfo = static_cast(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(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; + } + } + } +} diff --git a/src/game/server/player.h b/src/game/server/player.h index c1cacc4f0..78821aec4 100644 --- a/src/game/server/player.h +++ b/src/game/server/player.h @@ -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 { diff --git a/src/game/server/teams.cpp b/src/game/server/teams.cpp index 56120fd6a..1ab069a94 100644 --- a/src/game/server/teams.cpp +++ b/src/game/server/teams.cpp @@ -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; } diff --git a/src/game/server/teams.h b/src/game/server/teams.h index bdd2d7f5c..5a02fcd21 100644 --- a/src/game/server/teams.h +++ b/src/game/server/teams.h @@ -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; diff --git a/src/game/variables.h b/src/game/variables.h index a23a38b55..1a2cb66e8 100644 --- a/src/game/variables.h +++ b/src/game/variables.h @@ -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, "") diff --git a/src/mastersrv/mastersrv.h b/src/mastersrv/mastersrv.h index 38e5ab277..ae9a0c2af 100644 --- a/src/mastersrv/mastersrv.h +++ b/src/mastersrv/mastersrv.h @@ -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'};