Merge ddrace64 from eeeeee

This commit is contained in:
def 2013-12-31 06:13:57 +01:00
parent da2cdf7acd
commit 3607218f12
28 changed files with 518 additions and 57 deletions

View file

@ -377,8 +377,8 @@ Messages = [
NetIntAny("m_Tee14"),
NetIntAny("m_Tee15"),
]),
NetMessage("Cl_ShowOthers", [
NetBool("m_Show"),
]),
NetMessage("Cl_IsDDRace64", []),
]

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -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, "");

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -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, "")

View file

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