From b3c8973f30f73bfc2cc9302ae1f0ad664f7e3b70 Mon Sep 17 00:00:00 2001 From: div0 Date: Sun, 3 May 2009 19:28:02 +0000 Subject: [PATCH] handle "tell" messages in qc too, to do flood protection on them git-svn-id: svn://svn.icculus.org/nexuiz/trunk@6643 f962a42d-fe04-0410-a3ab-8c8b0445ebaa --- data/defaultNexuiz.cfg | 3 ++ data/qcsrc/server/cl_player.qc | 61 ++++++++++++++++++------ data/qcsrc/server/clientcommands.qc | 18 ++++++-- data/qcsrc/server/miscfunctions.qc | 72 +++++++++++++++++++++++++++++ data/qcsrc/server/vote.qc | 46 +++++------------- 5 files changed, 148 insertions(+), 52 deletions(-) diff --git a/data/defaultNexuiz.cfg b/data/defaultNexuiz.cfg index b23db0f27..9fdf7412d 100644 --- a/data/defaultNexuiz.cfg +++ b/data/defaultNexuiz.cfg @@ -1076,6 +1076,9 @@ set g_chat_flood_burst 2 "normal chat: allow bursts of so many chat lines" set g_chat_flood_spl_team 1 "team chat:seconds between lines to not count as flooding" set g_chat_flood_lmax_team 2 "team chat: maximum number of lines per chat message at once" set g_chat_flood_burst_team 2 "team chat: allow bursts of so many chat lines" +set g_chat_flood_spl_tell 1 "team chat:seconds between lines to not count as flooding" +set g_chat_flood_lmax_tell 2 "team chat: maximum number of lines per chat message at once" +set g_chat_flood_burst_tell 2 "team chat: allow bursts of so many chat lines" set g_chat_flood_notify_flooder 1 "when 0, the flooder still can see his own message" set g_chat_teamcolors 0 "colorize nicknames in team color for chat" set g_voice_flood_spv 4 "normal voices: seconds between voices to not count as flooding" diff --git a/data/qcsrc/server/cl_player.qc b/data/qcsrc/server/cl_player.qc index 545a429ce..653064470 100644 --- a/data/qcsrc/server/cl_player.qc +++ b/data/qcsrc/server/cl_player.qc @@ -667,16 +667,17 @@ void UpdateSelectedPlayer() .float floodcontrol_chat; .float floodcontrol_chatteam; -void Say(entity source, float teamsay, string msgin, float floodcontrol) +.float floodcontrol_chattell; +void Say(entity source, float teamsay, entity privatesay, string msgin, float floodcontrol) { - string msgstr, colorstr, cmsgstr, namestr, fullmsgstr, sourcemsgstr, fullcmsgstr, sourcecmsgstr; - float flood; + string msgstr, colorstr, cmsgstr, namestr, fullmsgstr, sourcemsgstr, fullcmsgstr, sourcecmsgstr, privatemsgprefix; + float flood, privatemsgprefixlen; entity head; if(Ban_MaybeEnforceBan(source)) return; - - if(!teamsay) + + if(!teamsay && !privatesay) if(substring(msgin, 0, 1) == " ") msgin = substring(msgin, 1, strlen(msgin) - 1); // work around DP say bug (say_team does not have this!) @@ -710,7 +711,19 @@ void Say(entity source, float teamsay, string msgin, float floodcontrol) namestr = playername(source); else namestr = source.netname; - if(teamsay) + + if(privatesay) + { + msgstr = strcat("\{1}\{13}* ^3", namestr, "^3 tells you: ^7"); + privatemsgprefixlen = strlen(msgstr); + msgstr = strcat(msgstr, msgin); + cmsgstr = strcat(colorstr, "^3", namestr, "^3 tells you:\n^7", msgin); + if(cvar("g_chat_teamcolors")) + privatemsgprefix = strcat("\{1}\{13}* ^3You tell ", playername(privatesay), ": ^7"); + else + privatemsgprefix = strcat("\{1}\{13}* ^3You tell ", privatesay.netname, ": ^7"); + } + else if(teamsay) { msgstr = strcat("\{1}\{13}", colorstr, "(^3", namestr, colorstr, ") ^7", msgin); cmsgstr = strcat(colorstr, "(^3", namestr, colorstr, ")\n^7", msgin); @@ -734,7 +747,14 @@ void Say(entity source, float teamsay, string msgin, float floodcontrol) float flood_lmax; var .float flood_field; float lines; - if(teamsay) + if(privatesay) + { + flood_spl = cvar("g_chat_flood_spl_tell"); + flood_burst = cvar("g_chat_flood_burst_tell"); + flood_lmax = cvar("g_chat_flood_lmax_tell"); + flood_field = floodcontrol_chattell; + } + else if(teamsay) { flood_spl = cvar("g_chat_flood_spl_team"); flood_burst = cvar("g_chat_flood_burst_team"); @@ -765,10 +785,13 @@ void Say(entity source, float teamsay, string msgin, float floodcontrol) if(getWrappedLine_remaining != "") flood = 2; - if(time >= self.flood_field) - self.flood_field = max(time - flood_burst * flood_spl, self.flood_field) + lines * flood_spl; + if(time >= source.flood_field) + source.flood_field = max(time - flood_burst * flood_spl, source.flood_field) + lines * flood_spl; else + { flood = 1; + msgstr = fullmsgstr; + } } if(flood == 2) @@ -791,6 +814,7 @@ void Say(entity source, float teamsay, string msgin, float floodcontrol) sourcecmsgstr = cmsgstr; } + if(!privatesay) if(source.classname != "player") { if(teamsay || (cvar("g_chat_nospectators") == 1) || (cvar("g_chat_nospectators") == 2 && !inWarmupStage)) @@ -798,14 +822,25 @@ void Say(entity source, float teamsay, string msgin, float floodcontrol) } if(flood) - print("NOTE: ", playername(self), "^7 is flooding.\n"); + print("NOTE: ", playername(source), "^7 is flooding.\n"); + + // build sourcemsgstr by cutting off a prefix and replacing it by the other one + if(privatesay) + sourcemsgstr = strcat(privatemsgprefix, substring(msgstr, privatemsgprefixlen, -1)); if(flood == 1) { if(cvar("g_chat_flood_notify_flooder")) - sprint(self, strcat("^3FLOOD CONTROL: ^7wait ^1", ftos(self.flood_field - time), "^3 seconds\n")); + sprint(source, strcat("^3FLOOD CONTROL: ^7wait ^1", ftos(source.flood_field - time), "^3 seconds\n")); else - sprint(self, fullmsgstr); + sprint(source, sourcemsgstr); + } + else if(privatesay) + { + sprint(source, sourcemsgstr); + sprint(privatesay, msgstr); + if(cmsgstr != "") + centerprint(privatesay, cmsgstr); } else if(teamsay > 0) { @@ -1099,7 +1134,7 @@ void VoiceMessage(string type, string msg) flood = 1; if (msg != "") - Say(self, ownteam, msg, 0); + Say(self, ownteam, world, msg, 0); if (!flood) PlayerSound(sample, CHAN_VOICE, voicetype); diff --git a/data/qcsrc/server/clientcommands.qc b/data/qcsrc/server/clientcommands.qc index 15885af1b..047ce40c7 100644 --- a/data/qcsrc/server/clientcommands.qc +++ b/data/qcsrc/server/clientcommands.qc @@ -101,9 +101,10 @@ entity GetPlayer(string name) float readyrestart_happened; .float lms_spectate_warning; void SV_ParseClientCommand(string s) { - local string cmd; - local float tokens, f, effectnum; - local vector start, end; + string cmd; + float tokens, f, effectnum; + vector start, end; + entity e; tokens = tokenize_console(s); @@ -266,11 +267,18 @@ void SV_ParseClientCommand(string s) { VoiceMessage(argv(1), ""); } else if(argv(0) == "say") { if(tokens >= 2) - Say(self, FALSE, substring(s, argv_start_index(1), argv_end_index(-1) - argv_start_index(1)), 1); + Say(self, FALSE, world, substring(s, argv_start_index(1), argv_end_index(-1) - argv_start_index(1)), 1); //clientcommand(self, formatmessage(s)); } else if(argv(0) == "say_team") { if(tokens >= 2) - Say(self, TRUE, substring(s, argv_start_index(1), argv_end_index(-1) - argv_start_index(1)), 1); + Say(self, TRUE, world, substring(s, argv_start_index(1), argv_end_index(-1) - argv_start_index(1)), 1); + //clientcommand(self, formatmessage(s)); + } else if(argv(0) == "tell") { + e = GetCommandPlayerSlotTargetFromTokenizedCommand(tokens, 1); + if(e && tokens > ParseCommandPlayerSlotTarget_firsttoken) + Say(self, FALSE, e, substring(s, argv_start_index(ParseCommandPlayerSlotTarget_firsttoken), argv_end_index(-1) - argv_start_index(ParseCommandPlayerSlotTarget_firsttoken)), 1); + else + sprint(self, "ERROR: usage: tell # playerid text...\n"); //clientcommand(self, formatmessage(s)); } else if(argv(0) == "info") { cmd = cvar_string(strcat("sv_info_", argv(1))); diff --git a/data/qcsrc/server/miscfunctions.qc b/data/qcsrc/server/miscfunctions.qc index 6acf4b977..6a2d6307c 100644 --- a/data/qcsrc/server/miscfunctions.qc +++ b/data/qcsrc/server/miscfunctions.qc @@ -2221,3 +2221,75 @@ void SoundEntity_Detach(entity pl) for(i = 0; i <= 7; ++i) SoundEntity_StopSound(pl, i); } + + +float ParseCommandPlayerSlotTarget_firsttoken; +entity GetCommandPlayerSlotTargetFromTokenizedCommand(float tokens, float idx) // idx = start index +{ + string s; + entity e, head; + float n; + + s = string_null; + + ParseCommandPlayerSlotTarget_firsttoken = -1; + + if(tokens > idx) + { + if(substring(argv(idx), 0, 1) == "#") + { + s = substring(argv(idx), 1, -1); + ++idx; + if(s == "") + if(tokens > idx) + { + s = argv(idx); + ++idx; + } + if(s == ftos(stof(s))) + { + e = edict_num(stof(s)); + if(e.flags & FL_CLIENT) + { + ParseCommandPlayerSlotTarget_firsttoken = idx; + return e; + } + } + } + else + { + // it must be a nick name + s = argv(idx); + ++idx; + + n = 0; + FOR_EACH_CLIENT(head) + if(head.netname == s) + { + e = head; + ++n; + } + if(n == 1) + { + ParseCommandPlayerSlotTarget_firsttoken = idx; + return e; + } + + s = strdecolorize(s); + n = 0; + FOR_EACH_CLIENT(head) + if(strdecolorize(head.netname) == s) + { + e = head; + ++n; + } + if(n == 1) + { + ParseCommandPlayerSlotTarget_firsttoken = idx; + return e; + } + } + } + + return world; +} diff --git a/data/qcsrc/server/vote.qc b/data/qcsrc/server/vote.qc index 72323afda..63e5e633e 100644 --- a/data/qcsrc/server/vote.qc +++ b/data/qcsrc/server/vote.qc @@ -17,7 +17,6 @@ string GetKickVoteVictim_reason; entity GetKickVoteVictim(string vote, string cmd, entity caller) { float tokens; - float n, t; string ns; entity e; string reason; @@ -25,24 +24,11 @@ entity GetKickVoteVictim(string vote, string cmd, entity caller) tokens = tokenize_console(vote); ns = ""; - if(tokens >= 2) - if(substring(argv(1), 0, 1) == "#") - { - ns = substring(argv(1), 1, 999); - t = 2; - } - - if(tokens >= 3) - if(argv(1) == "#") - { - ns = argv(2); - t = 3; - } - - if(ns != "") + e = GetCommandPlayerSlotTargetFromTokenizedCommand(tokens, 1); + if(e) { - if(t < tokens) - GetKickVoteVictim_reason = substring(vote, argv_start_index(t), argv_end_index(-1) - argv_start_index(t)); + if(ParseCommandPlayerSlotTarget_firsttoken < tokens) + GetKickVoteVictim_reason = substring(vote, argv_start_index(ParseCommandPlayerSlotTarget_firsttoken), argv_end_index(-1) - argv_start_index(ParseCommandPlayerSlotTarget_firsttoken)); else GetKickVoteVictim_reason = ""; @@ -66,24 +52,16 @@ entity GetKickVoteVictim(string vote, string cmd, entity caller) if not(cvar_value_issafe(reason)) reason = uri_escape(reason); - n = stof(ns); - if(ns == ftos(n)) if(n >= 1) if(n <= maxclients) + GetKickVoteVictim_newcommand = strcat(argv(0), " # ", ftos(num_for_edict(e))); + if(argv(0) == "kickban") { - e = edict_num(n); - if(clienttype(e) == CLIENTTYPE_REAL) - { - GetKickVoteVictim_newcommand = strcat(argv(0), " # ", ns); - if(argv(0) == "kickban") - { - GetKickVoteVictim_newcommand = strcat(GetKickVoteVictim_newcommand, " ", cvar_string("g_ban_default_bantime"), " ", cvar_string("g_ban_default_masksize"), " ", reason); - } - else if(argv(0) == "kick") - { - GetKickVoteVictim_newcommand = strcat(GetKickVoteVictim_newcommand, " ", reason); - } - return e; - } + GetKickVoteVictim_newcommand = strcat(GetKickVoteVictim_newcommand, " ", cvar_string("g_ban_default_bantime"), " ", cvar_string("g_ban_default_masksize"), " ", reason); + } + else if(argv(0) == "kick") + { + GetKickVoteVictim_newcommand = strcat(GetKickVoteVictim_newcommand, " ", reason); } + return e; } print_to(caller, strcat("Usage: ", cmd, " ", argv(0), " #playernumber (as in \"status\")\n")); -- 2.39.2