Make most user input teehistoric

Exclude private stuff like chat messages and votes.
This commit is contained in:
heinrich5991 2017-09-13 22:35:09 +02:00
parent 6ef9c8dbcd
commit 9761e9606a
19 changed files with 276 additions and 70 deletions

View file

@ -150,6 +150,7 @@ public:
const char *GetMsgName(int Type);
void *SecureUnpackMsg(int Type, CUnpacker *pUnpacker);
bool TeeHistorianRecordMsg(int Type);
const char *FailedMsgOn();
};
@ -323,6 +324,22 @@ if gen_network_source:
lines += ['};']
lines += ['']
lines += ['bool CNetObjHandler::TeeHistorianRecordMsg(int Type)']
lines += ['{']
lines += ['\tswitch(Type)']
lines += ['\t{']
empty = True
for msg in network.Messages:
if not msg.teehistorian:
lines += ['\tcase %s:' % msg.enum_name]
empty = False
if not empty:
lines += ['\t\treturn false;']
lines += ['\tdefault:']
lines += ['\t\treturn true;']
lines += ['\t}']
lines += ['}']
lines += ['']
lines += ['void RegisterGameUuids(CUuidManager *pManager)']
lines += ['{']

View file

@ -237,11 +237,12 @@ class NetEvent(NetObject):
self.enum_name = "NETEVENTTYPE_%s" % self.name.upper()
class NetMessage(NetObject):
def __init__(self, name, variables, ex=None):
def __init__(self, name, variables, ex=None, teehistorian=True):
NetObject.__init__(self, name, variables, ex=ex)
self.base_struct_name = "CNetMsg_%s" % self.base
self.struct_name = "CNetMsg_%s" % self.name
self.enum_name = "NETMSGTYPE_%s" % self.name.upper()
self.teehistorian = teehistorian
def emit_unpack(self):
lines = []
lines += ["case %s:" % self.enum_name]
@ -280,7 +281,7 @@ class NetEventEx(NetEvent):
NetEvent.__init__(self, name, variables, ex=ex)
class NetMessageEx(NetMessage):
def __init__(self, name, ex, variables):
def __init__(self, name, ex, variables, teehistorian=True):
NetMessage.__init__(self, name, variables, ex=ex)

View file

@ -305,7 +305,7 @@ Messages = [
NetMessage("Cl_Say", [
NetBool("m_Team"),
NetStringHalfStrict("m_pMessage"),
]),
], teehistorian=False),
NetMessage("Cl_SetTeam", [
NetIntRange("m_Team", 'TEAM_SPECTATORS', 'TEAM_BLUE'),
@ -343,13 +343,13 @@ Messages = [
NetMessage("Cl_Vote", [
NetIntRange("m_Vote", -1, 1),
]),
], teehistorian=False),
NetMessage("Cl_CallVote", [
NetStringStrict("m_Type"),
NetStringStrict("m_Value"),
NetStringStrict("m_Reason"),
]),
], teehistorian=False),
NetMessage("Cl_IsDDNet", []),

View file

@ -70,6 +70,7 @@ public:
int GetAccessLevel() const { return m_AccessLevel; }
};
typedef void (*FTeeHistorianCommandCallback)(int ClientID, int FlagMask, const char *pCmd, IResult *pResult, void *pUser);
typedef void (*FPrintCallback)(const char *pStr, void *pUser, bool Highlighted);
typedef void (*FPossibleCallback)(const char *pCmd, void *pUser);
typedef void (*FCommandCallback)(IResult *pResult, void *pUserData);
@ -96,6 +97,7 @@ public:
virtual int RegisterPrintCallback(int OutputLevel, FPrintCallback pfnPrintCallback, void *pUserData) = 0;
virtual void SetPrintOutputLevel(int Index, int OutputLevel) = 0;
virtual void Print(int Level, const char *pFrom, const char *pStr, bool Highlighted = false) = 0;
virtual void SetTeeHistorianCommandCallback(FTeeHistorianCommandCallback pfnCallback, void *pUser) = 0;
virtual void SetAccessLevel(int AccessLevel) = 0;

View file

@ -220,6 +220,9 @@ public:
virtual int GetClientVersion(int ClientID) = 0;
virtual void SetClientVersion(int ClientID, int Version) = 0;
virtual bool PlayerExists(int ClientID) = 0;
virtual void OnClientEngineJoin(int ClientID) = 0;
virtual void OnClientEngineDrop(int ClientID, const char *pReason) = 0;
};
extern IGameServer *CreateGameServer();

View file

@ -809,6 +809,7 @@ int CServer::NewClientCallback(int ClientID, void *pUser)
pThis->m_aClients[ClientID].m_TrafficSince = 0;
memset(&pThis->m_aClients[ClientID].m_Addr, 0, sizeof(NETADDR));
pThis->m_aClients[ClientID].Reset();
pThis->GameServer()->OnClientEngineJoin(ClientID);
return 0;
}
@ -860,6 +861,9 @@ int CServer::DelClientCallback(int ClientID, const char *pReason, void *pUser)
pThis->m_aClients[ClientID].m_TrafficSince = 0;
pThis->m_aPrevStates[ClientID] = CClient::STATE_EMPTY;
pThis->m_aClients[ClientID].m_Snapshots.PurgeAll();
pThis->GameServer()->OnClientEngineDrop(ClientID, pReason);
return 0;
}
@ -1058,7 +1062,7 @@ void CServer::ProcessClientPacket(CNetChunk *pPacket)
}
// reserved slot
if(ClientID >= (g_Config.m_SvMaxClients - g_Config.m_SvReservedSlots) && g_Config.m_SvReservedSlotsPass[0] != 0 && strcmp(g_Config.m_SvReservedSlotsPass, pPassword) != 0)
if(ClientID >= (g_Config.m_SvMaxClients - g_Config.m_SvReservedSlots) && g_Config.m_SvReservedSlotsPass[0] != 0 && str_comp(g_Config.m_SvReservedSlotsPass, pPassword) != 0)
{
m_NetServer.Drop(ClientID, "This server is full");
return;
@ -1610,7 +1614,9 @@ void CServer::PumpNetwork()
}
}
else
{
ProcessClientPacket(&Packet);
}
}
m_ServerBan.Update();
@ -2603,18 +2609,18 @@ void CServer::RegisterCommands()
#if defined (CONF_SQL)
Console()->Register("add_sqlserver", "s['r'|'w'] s[Database] s[Prefix] s[User] s[Password] s[IP] i[Port] ?i[SetUpDatabase ?]", CFGFLAG_SERVER, ConAddSqlServer, this, "add a sqlserver");
Console()->Register("add_sqlserver", "s['r'|'w'] s[Database] s[Prefix] s[User] s[Password] s[IP] i[Port] ?i[SetUpDatabase ?]", CFGFLAG_SERVER|CFGFLAG_NONTEEHISTORIC, ConAddSqlServer, this, "add a sqlserver");
Console()->Register("dump_sqlservers", "s['r'|'w']", CFGFLAG_SERVER, ConDumpSqlServers, this, "dumps all sqlservers readservers = r, writeservers = w");
#endif
Console()->Register("dnsbl_status", "", CFGFLAG_SERVER, ConDnsblStatus, this, "List blacklisted players");
Console()->Register("auth_add", "s[ident] s[level] s[pw]", CFGFLAG_SERVER, ConAuthAdd, this, "Add a rcon key");
Console()->Register("auth_add_p", "s[ident] s[level] s[hash] s[salt]", CFGFLAG_SERVER, ConAuthAddHashed, this, "Add a prehashed rcon key");
Console()->Register("auth_change", "s[ident] s[level] s[pw]", CFGFLAG_SERVER, ConAuthUpdate, this, "Update a rcon key");
Console()->Register("auth_change_p", "s[ident] s[level] s[hash] s[salt]", CFGFLAG_SERVER, ConAuthUpdateHashed, this, "Update a rcon key with prehashed data");
Console()->Register("auth_remove", "s[ident]", CFGFLAG_SERVER, ConAuthRemove, this, "Remove a rcon key");
Console()->Register("auth_add", "s[ident] s[level] s[pw]", CFGFLAG_SERVER|CFGFLAG_NONTEEHISTORIC, ConAuthAdd, this, "Add a rcon key");
Console()->Register("auth_add_p", "s[ident] s[level] s[hash] s[salt]", CFGFLAG_SERVER|CFGFLAG_NONTEEHISTORIC, ConAuthAddHashed, this, "Add a prehashed rcon key");
Console()->Register("auth_change", "s[ident] s[level] s[pw]", CFGFLAG_SERVER|CFGFLAG_NONTEEHISTORIC, ConAuthUpdate, this, "Update a rcon key");
Console()->Register("auth_change_p", "s[ident] s[level] s[hash] s[salt]", CFGFLAG_SERVER|CFGFLAG_NONTEEHISTORIC, ConAuthUpdateHashed, this, "Update a rcon key with prehashed data");
Console()->Register("auth_remove", "s[ident]", CFGFLAG_SERVER|CFGFLAG_NONTEEHISTORIC, ConAuthRemove, this, "Remove a rcon key");
Console()->Register("auth_list", "", CFGFLAG_SERVER, ConAuthList, this, "List all rcon keys");
Console()->Chain("sv_name", ConchainSpecialInfoupdate, this);

View file

@ -32,6 +32,7 @@ enum
CMDFLAG_TEST=64,
CFGFLAG_CHAT=128,
CFGFLAG_GAME=256,
CFGFLAG_NONTEEHISTORIC=512,
};
#endif

View file

@ -10,7 +10,7 @@
MACRO_CONFIG_STR(PlayerName, player_name, 16, "nameless tee", CFGFLAG_SAVE|CFGFLAG_CLIENT, "Name of the player")
MACRO_CONFIG_STR(PlayerClan, player_clan, 12, "", CFGFLAG_SAVE|CFGFLAG_CLIENT, "Clan of the player")
MACRO_CONFIG_INT(PlayerCountry, player_country, -1, -1, 1000, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Country of the player")
MACRO_CONFIG_STR(Password, password, 32, "", CFGFLAG_CLIENT|CFGFLAG_SERVER, "Password to the server")
MACRO_CONFIG_STR(Password, password, 32, "", CFGFLAG_CLIENT|CFGFLAG_SERVER|CFGFLAG_NONTEEHISTORIC, "Password to the server")
MACRO_CONFIG_STR(Logfile, logfile, 128, "", CFGFLAG_SAVE|CFGFLAG_CLIENT|CFGFLAG_SERVER, "Filename to log all output to")
MACRO_CONFIG_INT(ConsoleOutputLevel, console_output_level, 0, 0, 2, CFGFLAG_CLIENT|CFGFLAG_SERVER, "Adjusts the amount of information in the console")
@ -147,9 +147,9 @@ MACRO_CONFIG_INT(SvMaxClients, sv_max_clients, MAX_CLIENTS, 1, MAX_CLIENTS, CFGF
MACRO_CONFIG_INT(SvMaxClientsPerIP, sv_max_clients_per_ip, 4, 1, MAX_CLIENTS, CFGFLAG_SERVER, "Maximum number of clients with the same IP that can connect to the server")
MACRO_CONFIG_INT(SvHighBandwidth, sv_high_bandwidth, 0, 0, 1, CFGFLAG_SERVER, "Use high bandwidth mode. Doubles the bandwidth required for the server. LAN use only")
MACRO_CONFIG_INT(SvRegister, sv_register, 1, 0, 1, CFGFLAG_SERVER, "Register server with master server for public listing")
MACRO_CONFIG_STR(SvRconPassword, sv_rcon_password, 32, "", CFGFLAG_SERVER, "Remote console password (full access)")
MACRO_CONFIG_STR(SvRconModPassword, sv_rcon_mod_password, 32, "", CFGFLAG_SERVER, "Remote console password for moderators (limited access)")
MACRO_CONFIG_STR(SvRconHelperPassword, sv_rcon_helper_password, 32, "", CFGFLAG_SERVER, "Remote console password for helpers (limited access)")
MACRO_CONFIG_STR(SvRconPassword, sv_rcon_password, 32, "", CFGFLAG_SERVER|CFGFLAG_NONTEEHISTORIC, "Remote console password (full access)")
MACRO_CONFIG_STR(SvRconModPassword, sv_rcon_mod_password, 32, "", CFGFLAG_SERVER|CFGFLAG_NONTEEHISTORIC, "Remote console password for moderators (limited access)")
MACRO_CONFIG_STR(SvRconHelperPassword, sv_rcon_helper_password, 32, "", CFGFLAG_SERVER|CFGFLAG_NONTEEHISTORIC, "Remote console password for helpers (limited access)")
MACRO_CONFIG_INT(SvRconMaxTries, sv_rcon_max_tries, 30, 0, 100, CFGFLAG_SERVER, "Maximum number of tries for remote console authentication")
MACRO_CONFIG_INT(SvRconBantime, sv_rcon_bantime, 5, 0, 1440, CFGFLAG_SERVER, "The time a client gets banned if remote console authentication fails. 0 makes it just use kick")
MACRO_CONFIG_INT(SvAutoDemoRecord, sv_auto_demo_record, 0, 0, 1, CFGFLAG_SERVER, "Automatically record demos")
@ -158,7 +158,7 @@ MACRO_CONFIG_INT(SvTeeHistorian, sv_tee_historian, 0, 0, 1, CFGFLAG_SERVER, "Act
MACRO_CONFIG_INT(SvVanillaAntiSpoof, sv_vanilla_antispoof, 1, 0, 1, CFGFLAG_SERVER, "Enable vanilla Antispoof")
MACRO_CONFIG_INT(SvDnsbl, sv_dnsbl, 0, 0, 1, CFGFLAG_SERVER, "Enable DNSBL (DNS-based Blackhole List)")
MACRO_CONFIG_STR(SvDnsblHost, sv_dnsbl_host, 128, "", CFGFLAG_SERVER, "Hostname of DNSBL provider to use for IP Verification")
MACRO_CONFIG_STR(SvDnsblKey, sv_dnsbl_key, 128, "", CFGFLAG_SERVER, "Optional Authentification Key for the specified DNSBL provider")
MACRO_CONFIG_STR(SvDnsblKey, sv_dnsbl_key, 128, "", CFGFLAG_SERVER|CFGFLAG_NONTEEHISTORIC, "Optional Authentification Key for the specified DNSBL provider")
MACRO_CONFIG_INT(SvDnsblVote, sv_dnsbl_vote, 0, 0, 1, CFGFLAG_SERVER, "Block votes by blacklisted addresses")
MACRO_CONFIG_INT(SvDnsblBan, sv_dnsbl_ban, 0, 0, 1, CFGFLAG_SERVER, "Automatically ban blacklisted addresses")

View file

@ -165,10 +165,11 @@ int CConsole::ParseArgs(CResult *pResult, const char *pFormat)
{
char *pVictim = 0;
if (Command != 'v')
pResult->AddArgument(pStr);
else
pResult->AddArgument(pStr);
if(Command != 'v')
{
pVictim = pStr;
}
if(Command == 'r') // rest of the string
break;
@ -187,8 +188,10 @@ int CConsole::ParseArgs(CResult *pResult, const char *pFormat)
pStr++;
}
if (pVictim)
if(pVictim)
{
pResult->SetVictim(pVictim);
}
}
}
// fetch next command
@ -258,6 +261,12 @@ void CConsole::Print(int Level, const char *pFrom, const char *pStr, bool Highli
}
}
void CConsole::SetTeeHistorianCommandCallback(FTeeHistorianCommandCallback pfnCallback, void *pUser)
{
m_pfnTeeHistorianCommandCallback = pfnCallback;
m_pTeeHistorianCommandUserdata = pUser;
}
bool CConsole::LineIsValid(const char *pStr)
{
if(!pStr || *pStr == 0)
@ -407,27 +416,29 @@ void CConsole::ExecuteLineStroked(int Stroke, const char *pStr, int ClientID, bo
}
else
{
if(Result.GetVictim() == CResult::VICTIM_ME)
Result.SetVictim(ClientID);
if(pCommand->m_Flags&CMDFLAG_TEST && !g_Config.m_SvTestingCommands)
return;
if (Result.HasVictim())
if(m_pfnTeeHistorianCommandCallback && !(pCommand->m_Flags&CFGFLAG_NONTEEHISTORIC))
{
if(Result.GetVictim() == CResult::VICTIM_ALL)
m_pfnTeeHistorianCommandCallback(ClientID, m_FlagMask, pCommand->m_pName, &Result, m_pTeeHistorianCommandUserdata);
}
if(Result.GetVictim() == CResult::VICTIM_ME)
Result.SetVictim(ClientID);
if(Result.HasVictim() && Result.GetVictim() == CResult::VICTIM_ALL)
{
for (int i = 0; i < MAX_CLIENTS; i++)
{
for (int i = 0; i < MAX_CLIENTS; i++)
{
Result.SetVictim(i);
pCommand->m_pfnCallback(&Result, pCommand->m_pUserData);
}
}
else
Result.SetVictim(i);
pCommand->m_pfnCallback(&Result, pCommand->m_pUserData);
}
}
else
{
pCommand->m_pfnCallback(&Result, pCommand->m_pUserData);
}
if (pCommand->m_Flags&CMDFLAG_TEST)
m_Cheated = true;
@ -805,6 +816,8 @@ CConsole::CConsole(int FlagMask)
m_pFirstExec = 0;
mem_zero(m_aPrintCB, sizeof(m_aPrintCB));
m_NumPrintCB = 0;
m_pfnTeeHistorianCommandCallback = 0;
m_pTeeHistorianCommandUserdata = 0;
m_pStorage = 0;

View file

@ -71,6 +71,9 @@ class CConsole : public IConsole
} m_aPrintCB[MAX_PRINT_CB];
int m_NumPrintCB;
FTeeHistorianCommandCallback m_pfnTeeHistorianCommandCallback;
void *m_pTeeHistorianCommandUserdata;
enum
{
CONSOLE_MAX_STR_LENGTH = 8192,
@ -203,6 +206,7 @@ public:
virtual int RegisterPrintCallback(int OutputLevel, FPrintCallback pfnPrintCallback, void *pUserData);
virtual void SetPrintOutputLevel(int Index, int OutputLevel);
virtual void Print(int Level, const char *pFrom, const char *pStr, bool Highlighted = false);
virtual void SetTeeHistorianCommandCallback(FTeeHistorianCommandCallback pfnCallback, void *pUser);
void SetAccessLevel(int AccessLevel) { m_AccessLevel = clamp(AccessLevel, (int)(ACCESS_LEVEL_ADMIN), (int)(ACCESS_LEVEL_USER)); }
void ResetServerGameSettings();

View file

@ -46,6 +46,9 @@ public:
const char *GetString(int SanitizeType = SANITIZE);
const unsigned char *GetRaw(int Size);
bool Error() const { return m_Error; }
int CompleteSize() const { return m_pEnd - m_pStart; }
const unsigned char *CompleteData() const { return m_pStart; }
};
#endif

View file

@ -48,8 +48,8 @@ CONSOLE_COMMAND("muteip", "s[ip] i[seconds]", CFGFLAG_SERVER, ConMuteIP, this, "
CONSOLE_COMMAND("unmute", "v[id]", CFGFLAG_SERVER, ConUnmute, this, "");
CONSOLE_COMMAND("mutes", "", CFGFLAG_SERVER, ConMutes, this, "");
CONSOLE_COMMAND("freezehammer", "v[id]", CFGFLAG_SERVER, ConFreezeHammer, this, "Gives a player Freeze Hammer")
CONSOLE_COMMAND("unfreezehammer", "v[id]", CFGFLAG_SERVER, ConUnFreezeHammer, this, "Removes Freeze Hammer from a player")
CONSOLE_COMMAND("freezehammer", "v[id]", CFGFLAG_SERVER|CMDFLAG_TEST, ConFreezeHammer, this, "Gives a player Freeze Hammer")
CONSOLE_COMMAND("unfreezehammer", "v[id]", CFGFLAG_SERVER|CMDFLAG_TEST, ConUnFreezeHammer, this, "Removes Freeze Hammer from a player")
#undef CONSOLE_COMMAND
#endif

View file

@ -12,19 +12,19 @@ CHAT_COMMAND("eyeemote", "?s['on'|'off'|'toggle']", CFGFLAG_CHAT|CFGFLAG_SERVER,
CHAT_COMMAND("settings", "?s[configname]", CFGFLAG_CHAT|CFGFLAG_SERVER, ConSettings, this, "Shows gameplay information for this server")
CHAT_COMMAND("help", "?r[command]", CFGFLAG_CHAT|CFGFLAG_SERVER, ConHelp, this, "Shows help to command r, general help if left blank")
CHAT_COMMAND("info", "", CFGFLAG_CHAT|CFGFLAG_SERVER, ConInfo, this, "Shows info about this server")
CHAT_COMMAND("me", "r[message]", CFGFLAG_CHAT|CFGFLAG_SERVER, ConMe, this, "Like the famous irc command '/me says hi' will display '<yourname> says hi'")
CHAT_COMMAND("w", "s[player name] r[message]", CFGFLAG_CHAT|CFGFLAG_SERVER, ConWhisper, this, "Whisper something to someone (private message)")
CHAT_COMMAND("whisper", "s[player name] r[message]", CFGFLAG_CHAT|CFGFLAG_SERVER, ConWhisper, this, "Whisper something to someone (private message)")
CHAT_COMMAND("c", "r[message]", CFGFLAG_CHAT|CFGFLAG_SERVER, ConConverse, this, "Converse with the last person you whispered to (private message)");
CHAT_COMMAND("converse", "r[message]", CFGFLAG_CHAT|CFGFLAG_SERVER, ConConverse, this, "Converse with the last person you whispered to (private message)");
CHAT_COMMAND("me", "r[message]", CFGFLAG_CHAT|CFGFLAG_SERVER|CFGFLAG_NONTEEHISTORIC, ConMe, this, "Like the famous irc command '/me says hi' will display '<yourname> says hi'")
CHAT_COMMAND("w", "s[player name] r[message]", CFGFLAG_CHAT|CFGFLAG_SERVER|CFGFLAG_NONTEEHISTORIC, ConWhisper, this, "Whisper something to someone (private message)")
CHAT_COMMAND("whisper", "s[player name] r[message]", CFGFLAG_CHAT|CFGFLAG_SERVER|CFGFLAG_NONTEEHISTORIC, ConWhisper, this, "Whisper something to someone (private message)")
CHAT_COMMAND("c", "r[message]", CFGFLAG_CHAT|CFGFLAG_SERVER|CFGFLAG_NONTEEHISTORIC, ConConverse, this, "Converse with the last person you whispered to (private message)");
CHAT_COMMAND("converse", "r[message]", CFGFLAG_CHAT|CFGFLAG_SERVER|CFGFLAG_NONTEEHISTORIC, ConConverse, this, "Converse with the last person you whispered to (private message)");
CHAT_COMMAND("pause", "?r[player name]", CFGFLAG_CHAT|CFGFLAG_SERVER, ConTogglePause, this, "Toggles pause")
CHAT_COMMAND("spec", "?r[player name]", CFGFLAG_CHAT|CFGFLAG_SERVER, ConToggleSpec, this, "Toggles spec (if not available behaves as /pause)")
CHAT_COMMAND("dnd", "", CFGFLAG_CHAT|CFGFLAG_SERVER, ConDND, this, "Toggle Do Not Disturb (no chat and server messages)")
CHAT_COMMAND("dnd", "", CFGFLAG_CHAT|CFGFLAG_SERVER|CFGFLAG_NONTEEHISTORIC, ConDND, this, "Toggle Do Not Disturb (no chat and server messages)")
CHAT_COMMAND("mapinfo", "?r[map]", CFGFLAG_CHAT|CFGFLAG_SERVER, ConMapInfo, this, "Show info about the map with name r gives (current map by default)")
CHAT_COMMAND("timeout", "s[code]", CFGFLAG_CHAT|CFGFLAG_SERVER, ConTimeout, this, "Set timeout protection code s")
CHAT_COMMAND("save", "r[code]", CFGFLAG_CHAT|CFGFLAG_SERVER, ConSave, this, "Save team with code r")
CHAT_COMMAND("load", "r[code]", CFGFLAG_CHAT|CFGFLAG_SERVER, ConLoad, this, "Load with code r")
CHAT_COMMAND("map", "?r[map]", CFGFLAG_CHAT|CFGFLAG_SERVER, ConMap, this, "Vote a map by name")
CHAT_COMMAND("map", "?r[map]", CFGFLAG_CHAT|CFGFLAG_SERVER|CFGFLAG_NONTEEHISTORIC, ConMap, this, "Vote a map by name")
CHAT_COMMAND("rankteam", "?r[player name]", CFGFLAG_CHAT|CFGFLAG_SERVER, ConTeamRank, this, "Shows the team rank of player with name r (your team rank by default)")
CHAT_COMMAND("teamrank", "?r[player name]", CFGFLAG_CHAT|CFGFLAG_SERVER, ConTeamRank, this, "Shows the team rank of player with name r (your team rank by default)")
CHAT_COMMAND("rank", "?r[player name]", CFGFLAG_CHAT|CFGFLAG_SERVER, ConRank, this, "Shows the rank of player with name r (your rank by default)")
@ -38,8 +38,8 @@ CHAT_COMMAND("top5", "?i[rank to start with]", CFGFLAG_CHAT|CFGFLAG_SERVER, ConT
CHAT_COMMAND("showothers", "?i['0'|'1']", CFGFLAG_CHAT|CFGFLAG_SERVER, ConShowOthers, this, "Whether to show players from other teams or not (off by default), optional i = 0 for off else for on")
CHAT_COMMAND("specteam", "?i['0'|'1']", CFGFLAG_CHAT|CFGFLAG_SERVER, ConSpecTeam, this, "Whether to show players from other teams when spectating (on by default), optional i = 0 for off else for on")
CHAT_COMMAND("ninjajetpack", "?i['0'|'1']", CFGFLAG_CHAT|CFGFLAG_SERVER, ConNinjaJetpack, this, "Whether to use ninja jetpack or not. Makes jetpack look more awesome")
CHAT_COMMAND("saytime", "?r[player name]", CFGFLAG_CHAT|CFGFLAG_SERVER, ConSayTime, this, "Privately messages someone's current time in this current running race (your time by default)")
CHAT_COMMAND("saytimeall", "", CFGFLAG_CHAT|CFGFLAG_SERVER, ConSayTimeAll, this, "Publicly messages everyone your current time in this current running race")
CHAT_COMMAND("saytime", "?r[player name]", CFGFLAG_CHAT|CFGFLAG_SERVER|CFGFLAG_NONTEEHISTORIC, ConSayTime, this, "Privately messages someone's current time in this current running race (your time by default)")
CHAT_COMMAND("saytimeall", "", CFGFLAG_CHAT|CFGFLAG_SERVER|CFGFLAG_NONTEEHISTORIC, ConSayTimeAll, this, "Publicly messages everyone your current time in this current running race")
CHAT_COMMAND("time", "", CFGFLAG_CHAT|CFGFLAG_SERVER, ConTime, this, "Privately shows you your current time in this current running race in the broadcast message")
CHAT_COMMAND("timer", "?s['gametimer'|'broadcast'|'both'|'none'|'cycle']", CFGFLAG_CHAT|CFGFLAG_SERVER, ConSetTimerType, this, "Personal Setting of showing time in either broadcast or game/round timer, timer s, where s = broadcast for broadcast, gametimer for game/round timer, cycle for cycle, both for both, none for no timer and nothing to show current status")
CHAT_COMMAND("r", "", CFGFLAG_CHAT|CFGFLAG_SERVER, ConRescue, this, "Teleport yourself out of freeze (use sv_rescue 1 to enable this feature)")

View file

@ -296,7 +296,7 @@ void CGameContext::ConToCheckTeleporter(IConsole::IResult *pResult, void *pUserD
void CGameContext::ConTeleport(IConsole::IResult *pResult, void *pUserData)
{
CGameContext *pSelf = (CGameContext *) pUserData;
int TeleTo = pResult->GetInteger(0);
int TeleTo = pResult->GetInteger(1);
int Tele = pResult->m_ClientID;
if (pResult->NumArguments() > 0)
Tele = pResult->GetVictim();
@ -337,7 +337,7 @@ void CGameContext::ConForcePause(IConsole::IResult *pResult, void *pUserData)
int Victim = pResult->GetVictim();
int Seconds = 0;
if (pResult->NumArguments() > 0)
Seconds = clamp(pResult->GetInteger(0), 0, 360);
Seconds = clamp(pResult->GetInteger(1), 0, 360);
CPlayer *pPlayer = pSelf->m_apPlayers[Victim];
if (!pPlayer)
@ -481,7 +481,7 @@ void CGameContext::ConSetDDRTeam(IConsole::IResult *pResult, void *pUserData)
CGameControllerDDRace *pController = (CGameControllerDDRace *)pSelf->m_pController;
int Target = pResult->GetVictim();
int Team = pResult->GetInteger(0);
int Team = pResult->GetInteger(1);
if(pController->m_Teams.m_Core.Team(Target) && pController->m_Teams.GetDDRaceState(pSelf->m_apPlayers[Target]) == DDRACE_STARTED)
pSelf->m_apPlayers[Target]->KillCharacter(WEAPON_SELF);

View file

@ -107,6 +107,15 @@ void CGameContext::TeeHistorianWrite(const void *pData, int DataSize, void *pUse
io_write(pSelf->m_TeeHistorianFile, pData, DataSize);
}
void CGameContext::CommandCallback(int ClientID, int FlagMask, const char *pCmd, IConsole::IResult *pResult, void *pUser)
{
CGameContext *pSelf = (CGameContext *)pUser;
if(pSelf->m_TeeHistorianActive)
{
pSelf->m_TeeHistorian.RecordConsoleCommand(ClientID, FlagMask, pCmd, pResult);
}
}
class CCharacter *CGameContext::GetPlayerChar(int ClientID)
{
if(ClientID < 0 || ClientID >= MAX_CLIENTS || !m_apPlayers[ClientID])
@ -846,8 +855,6 @@ void CGameContext::OnClientDirectInput(int ClientID, void *pInput)
if(m_TeeHistorianActive)
{
// TODO: Only record when not in spectators. Be careful not to
// miss the first tick though.
m_TeeHistorian.RecordPlayerInput(ClientID, (CNetObj_PlayerInput *)pInput);
}
}
@ -1068,11 +1075,32 @@ void CGameContext::OnClientDrop(int ClientID, const char *pReason)
}
}
void CGameContext::OnClientEngineJoin(int ClientID)
{
if(m_TeeHistorianActive)
{
m_TeeHistorian.RecordPlayerJoin(ClientID);
}
}
void CGameContext::OnClientEngineDrop(int ClientID, const char *pReason)
{
if(m_TeeHistorianActive)
{
m_TeeHistorian.RecordPlayerDrop(ClientID, pReason);
}
}
void CGameContext::OnMessage(int MsgID, CUnpacker *pUnpacker, int ClientID)
{
void *pRawMsg = m_NetObjHandler.SecureUnpackMsg(MsgID, pUnpacker);
CPlayer *pPlayer = m_apPlayers[ClientID];
if(m_TeeHistorianActive)
{
m_TeeHistorian.RecordPlayerMessage(ClientID, pUnpacker->CompleteData(), pUnpacker->CompleteSize());
}
if(!pRawMsg)
{
//char aBuf[256];
@ -2444,9 +2472,6 @@ void CGameContext::OnConsoleInit()
Console()->Register("say", "r[message]", CFGFLAG_SERVER, ConSay, this, "Say in chat");
Console()->Register("set_team", "i[id] i[team-id] ?i[delay in minutes]", CFGFLAG_SERVER, ConSetTeam, this, "Set team of player to team");
Console()->Register("set_team_all", "i[team-id]", CFGFLAG_SERVER, ConSetTeamAll, this, "Set team of all players to team");
//Console()->Register("swap_teams", "", CFGFLAG_SERVER, ConSwapTeams, this, "Swap the current teams");
//Console()->Register("shuffle_teams", "", CFGFLAG_SERVER, ConShuffleTeams, this, "Shuffle the current teams");
//Console()->Register("lock_teams", "", CFGFLAG_SERVER, ConLockTeams, this, "Lock/unlock teams");
Console()->Register("add_vote", "s[name] r[command]", CFGFLAG_SERVER, ConAddVote, this, "Add a voting option");
Console()->Register("remove_vote", "s[name]", CFGFLAG_SERVER, ConRemoveVote, this, "remove a voting option");
@ -2456,10 +2481,10 @@ void CGameContext::OnConsoleInit()
Console()->Chain("sv_motd", ConchainSpecialMotdupdate, this);
#define CONSOLE_COMMAND(name, params, flags, callback, userdata, help) m_pConsole->Register(name, params, flags, callback, userdata, help);
#include "game/ddracecommands.h"
#define CHAT_COMMAND(name, params, flags, callback, userdata, help) m_pConsole->Register(name, params, flags, callback, userdata, help);
#include "ddracechat.h"
#define CONSOLE_COMMAND(name, params, flags, callback, userdata, help) m_pConsole->Register(name, params, flags, callback, userdata, help);
#include <game/ddracecommands.h>
#define CHAT_COMMAND(name, params, flags, callback, userdata, help) m_pConsole->Register(name, params, flags, callback, userdata, help);
#include "ddracechat.h"
}
void CGameContext::OnInit(/*class IKernel *pKernel*/)
@ -2470,6 +2495,7 @@ void CGameContext::OnInit(/*class IKernel *pKernel*/)
m_Events.SetGameServer(this);
m_GameUuid = RandomUuid();
Console()->SetTeeHistorianCommandCallback(CommandCallback, this);
DeleteTempfile();
@ -2573,6 +2599,9 @@ void CGameContext::OnInit(/*class IKernel *pKernel*/)
GameInfo.m_ServerPort = g_Config.m_SvPort;
GameInfo.m_pGameType = "DDraceNetwork";
GameInfo.m_pConfig = &g_Config;
GameInfo.m_pTuning = Tuning();
char aMapName[128];
Server()->GetMapInfo(aMapName, sizeof(aMapName), &GameInfo.m_MapSize, &GameInfo.m_MapCrc);
GameInfo.m_pMapName = aMapName;

View file

@ -67,6 +67,7 @@ class CGameContext : public IGameServer
IOHANDLE m_TeeHistorianFile;
CUuid m_GameUuid;
static void CommandCallback(int ClientID, int FlagMask, const char *pCmd, IConsole::IResult *pResult, void *pUser);
static void TeeHistorianWrite(const void *pData, int DataSize, void *pUser);
static void ConTuneParam(IConsole::IResult *pResult, void *pUserData);
@ -220,6 +221,9 @@ public:
virtual void OnClientDirectInput(int ClientID, void *pInput);
virtual void OnClientPredictedInput(int ClientID, void *pInput);
virtual void OnClientEngineJoin(int ClientID);
virtual void OnClientEngineDrop(int ClientID, const char *pReason);
virtual bool IsClientReady(int ClientID);
virtual bool IsClientPlayer(int ClientID);

View file

@ -1,6 +1,8 @@
#include "teehistorian.h"
#include <engine/shared/config.h>
#include <engine/shared/snapshot.h>
#include <game/gamecore.h>
static const CUuid TEEHISTORIAN_UUID = CalculateUuid("teehistorian@ddnet.tw");
static const char TEEHISTORIAN_VERSION[] = "1";
@ -14,6 +16,10 @@ enum
TEEHISTORIAN_PLAYER_OLD,
TEEHISTORIAN_INPUT_DIFF,
TEEHISTORIAN_INPUT_NEW,
TEEHISTORIAN_MESSAGE,
TEEHISTORIAN_JOIN,
TEEHISTORIAN_DROP,
TEEHISTORIAN_CONSOLE_COMMAND,
};
static char EscapeJsonChar(char c)
@ -115,11 +121,11 @@ void CTeeHistorian::WriteHeader(const CGameInfo *pGameInfo)
char aGameTypeBuffer[128];
char aMapNameBuffer[128];
char aJson[1024];
char aJson[2048];
#define E(buf, str) EscapeJson(buf, sizeof(buf), str)
str_format(aJson, sizeof(aJson), "{\"version\":\"%s\",\"game_uuid\":\"%s\",\"server_version\":\"%s\",\"start_time\":\"%s\",\"server_name\":\"%s\",\"server_port\":%d,\"game_type\":\"%s\",\"map_name\":\"%s\",\"map_size\":%d,\"map_crc\":\"%08x\"}",
str_format(aJson, sizeof(aJson), "{\"version\":\"%s\",\"game_uuid\":\"%s\",\"server_version\":\"%s\",\"start_time\":\"%s\",\"server_name\":\"%s\",\"server_port\":%d,\"game_type\":\"%s\",\"map_name\":\"%s\",\"map_size\":%d,\"map_crc\":\"%08x\",\"config\":{",
TEEHISTORIAN_VERSION,
aGameUuid,
E(aServerVersionBuffer, pGameInfo->m_pServerVersion),
@ -130,11 +136,62 @@ void CTeeHistorian::WriteHeader(const CGameInfo *pGameInfo)
E(aMapNameBuffer, pGameInfo->m_pMapName),
pGameInfo->m_MapSize,
pGameInfo->m_MapCrc);
Write(aJson, str_length(aJson));
// Include null-termination.
Write(aJson, str_length(aJson) + 1);
char aBuffer1[1024];
char aBuffer2[1024];
bool First = true;
#define MACRO_CONFIG_INT(Name,ScriptName,Def,Min,Max,Flags,Desc) \
if((Flags)&CFGFLAG_SERVER && !((Flags)&CFGFLAG_NONTEEHISTORIC)) \
{ \
str_format(aJson, sizeof(aJson), "%s\"%s\":\"%d\"", \
First ? "" : ",", \
E(aBuffer1, #ScriptName), \
pGameInfo->m_pConfig->m_##Name); \
Write(aJson, str_length(aJson)); \
First = false; \
}
#define MACRO_CONFIG_STR(Name,ScriptName,Len,Def,Flags,Desc) \
if((Flags)&CFGFLAG_SERVER && !((Flags)&CFGFLAG_NONTEEHISTORIC)) \
{ \
str_format(aJson, sizeof(aJson), "%s\"%s\":\"%s\"", \
First ? "" : ",", \
E(aBuffer1, #ScriptName), \
E(aBuffer2, pGameInfo->m_pConfig->m_##Name)); \
Write(aJson, str_length(aJson)); \
First = false; \
}
#include <engine/shared/config_variables.h>
#undef MACRO_CONFIG_INT
#undef MACRO_CONFIG_STR
str_format(aJson, sizeof(aJson), "},\"tuning\":{");
Write(aJson, str_length(aJson));
First = true;
#define MACRO_TUNING_PARAM(Name,ScriptName,Value,Description) \
{ \
str_format(aJson, sizeof(aJson), "%s\"%s\":\"%d\"", \
First ? "" : ",", \
E(aBuffer1, #ScriptName), \
pGameInfo->m_pTuning->m_##Name.Get()); \
Write(aJson, str_length(aJson)); \
First = false; \
}
#include <game/tuning.h>
#undef MACRO_TUNING_PARAM
str_format(aJson, sizeof(aJson), "}}");
Write(aJson, str_length(aJson));
Write("", 1); // Null termination.
}
void CTeeHistorian::BeginTick(int Tick)
{
dbg_assert(m_State == STATE_START || m_State == STATE_BEFORE_TICK, "invalid teehistorian state");
@ -321,6 +378,66 @@ void CTeeHistorian::RecordPlayerInput(int ClientID, const CNetObj_PlayerInput *p
pPrev->m_Input = *pInput;
}
void CTeeHistorian::RecordPlayerMessage(int ClientID, const void *pMsg, int MsgSize)
{
// TODO: Check if the size of `m_Buffer` suffices (probably not).
m_Buffer.AddInt(-TEEHISTORIAN_MESSAGE);
m_Buffer.AddInt(ClientID);
m_Buffer.AddInt(MsgSize);
m_Buffer.AddRaw(pMsg, MsgSize);
if(m_Debug)
{
CUnpacker Unpacker;
Unpacker.Reset(pMsg, MsgSize);
int MsgID = Unpacker.GetInt();
int Sys = MsgID & 1;
MsgID >>= 1;
dbg_msg("teehistorian", "msg cid=%d sys=%d msgid=%d", ClientID, Sys, MsgID);
}
}
void CTeeHistorian::RecordPlayerJoin(int ClientID)
{
m_Buffer.AddInt(-TEEHISTORIAN_JOIN);
m_Buffer.AddInt(ClientID);
if(m_Debug)
{
dbg_msg("teehistorian", "join cid=%d", ClientID);
}
}
void CTeeHistorian::RecordPlayerDrop(int ClientID, const char *pReason)
{
m_Buffer.AddInt(-TEEHISTORIAN_DROP);
m_Buffer.AddInt(ClientID);
m_Buffer.AddString(pReason, 0);
if(m_Debug)
{
dbg_msg("teehistorian", "drop cid=%d reason='%s'", ClientID, pReason);
}
}
void CTeeHistorian::RecordConsoleCommand(int ClientID, int FlagMask, const char *pCmd, IConsole::IResult *pResult)
{
m_Buffer.AddInt(-TEEHISTORIAN_CONSOLE_COMMAND);
m_Buffer.AddInt(ClientID);
m_Buffer.AddInt(FlagMask);
m_Buffer.AddString(pCmd, 0);
m_Buffer.AddInt(pResult->NumArguments());
for(int i = 0; i < pResult->NumArguments(); i++)
{
m_Buffer.AddString(pResult->GetString(i), 0);
}
if(m_Debug)
{
dbg_msg("teehistorian", "ccmd cid=%d cmd='%s'", ClientID, pCmd);
}
}
void CTeeHistorian::EndInputs()
{
dbg_assert(m_State == STATE_INPUTS, "invalid teehistorian state");
@ -358,4 +475,9 @@ void CTeeHistorian::Finish()
m_Buffer.Reset();
m_Buffer.AddInt(-TEEHISTORIAN_FINISH);
Write(m_Buffer.Data(), m_Buffer.Size());
if(m_Debug)
{
dbg_msg("teehistorian", "finish");
}
}

View file

@ -1,9 +1,13 @@
#include <engine/console.h>
#include <engine/shared/packer.h>
#include <engine/shared/protocol.h>
#include <game/generated/protocol.h>
#include <time.h>
struct CConfiguration;
class CTuningParams;
class CTeeHistorian
{
public:
@ -22,6 +26,9 @@ public:
const char *m_pMapName;
int m_MapSize;
int m_MapCrc;
CConfiguration *m_pConfig;
CTuningParams *m_pTuning;
};
CTeeHistorian();
@ -40,6 +47,10 @@ public:
void BeginInputs();
void RecordPlayerInput(int ClientID, const CNetObj_PlayerInput *pInput);
void RecordPlayerMessage(int ClientID, const void *pMsg, int MsgSize);
void RecordPlayerJoin(int ClientID);
void RecordPlayerDrop(int ClientID, const char *pReason);
void RecordConsoleCommand(int ClientID, int FlagMask, const char *pCmd, IConsole::IResult *pResult);
void EndInputs();
void EndTick();

View file

@ -127,20 +127,10 @@ MACRO_CONFIG_INT(ClHTTPLowSpeedTime, cl_http_low_speed_time, 5, 0, 100000, CFGFL
// server
MACRO_CONFIG_INT(SvWarmup, sv_warmup, 0, 0, 0, CFGFLAG_SERVER, "Number of seconds to do warmup before round starts")
MACRO_CONFIG_STR(SvMotd, sv_motd, 900, "", CFGFLAG_SERVER, "Message of the day to display for the clients")
MACRO_CONFIG_INT(SvTeamdamage, sv_teamdamage, 0, 0, 1, CFGFLAG_SERVER, "Team damage")
MACRO_CONFIG_STR(SvMaprotation, sv_maprotation, 768, "", CFGFLAG_SERVER, "Maps to rotate between")
MACRO_CONFIG_INT(SvRoundsPerMap, sv_rounds_per_map, 1, 1, 100, CFGFLAG_SERVER, "Number of rounds on each map before rotating")
MACRO_CONFIG_INT(SvRoundSwap, sv_round_swap, 1, 0, 1, CFGFLAG_SERVER, "Swap teams between rounds")
MACRO_CONFIG_INT(SvPowerups, sv_powerups, 1, 0, 1, CFGFLAG_SERVER, "Allow powerups like ninja")
MACRO_CONFIG_INT(SvScorelimit, sv_scorelimit, 20, 0, 1000, CFGFLAG_SERVER, "Score limit (0 disables)")
MACRO_CONFIG_INT(SvTimelimit, sv_timelimit, 0, 0, 1000, CFGFLAG_SERVER, "Time limit in minutes (0 disables)")
MACRO_CONFIG_INT(SvTournamentMode, sv_tournament_mode, 0, 0, 1, CFGFLAG_SERVER, "Tournament mode. When enabled, players joins the server as spectator")
MACRO_CONFIG_INT(SvSpamprotection, sv_spamprotection, 1, 0, 1, CFGFLAG_SERVER, "Spam protection")
MACRO_CONFIG_INT(SvRespawnDelayTDM, sv_respawn_delay_tdm, 3, 0, 10, CFGFLAG_SERVER, "Time needed to respawn after death in tdm gametype")
MACRO_CONFIG_INT(SvSpectatorSlots, sv_spectator_slots, 0, 0, MAX_CLIENTS, CFGFLAG_SERVER, "Number of slots to reserve for spectators")
MACRO_CONFIG_INT(SvTeambalanceTime, sv_teambalance_time, 1, 0, 1000, CFGFLAG_SERVER, "How many minutes to wait before autobalancing teams")
MACRO_CONFIG_INT(SvInactiveKickTime, sv_inactivekick_time, 0, 0, 1000, CFGFLAG_SERVER, "How many minutes to wait before taking care of inactive players")
MACRO_CONFIG_INT(SvInactiveKick, sv_inactivekick, 0, 0, 2, CFGFLAG_SERVER, "How to deal with inactive players (0=move to spectator, 1=move to free spectator slot/kick, 2=kick)")