]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/commitdiff
New banning systems (ignore, muteban, voteban and playban) and new features for moder...
authorLegendaryGuard <rootuser999@gmail.com>
Thu, 25 May 2023 07:53:21 +0000 (07:53 +0000)
committerbones_was_here <bones_was_here@xonotic.au>
Thu, 25 May 2023 07:53:21 +0000 (07:53 +0000)
15 files changed:
commands.cfg
notifications.cfg
qcsrc/common/mutators/mutator/kick_teamkiller/sv_kick_teamkiller.qc
qcsrc/common/notifications/all.inc
qcsrc/server/chat.qc
qcsrc/server/chat.qh
qcsrc/server/client.qc
qcsrc/server/client.qh
qcsrc/server/command/banning.qc
qcsrc/server/command/banning.qh
qcsrc/server/command/cmd.qc
qcsrc/server/command/cmd.qh
qcsrc/server/command/vote.qc
qcsrc/server/world.qc
xonotic-server.cfg

index 3a1ab30b706b3a3a6f57ee6815732969f0fe415a..d5b03ee3e4dc89d5b120f75c9e211088240ae850 100644 (file)
@@ -276,11 +276,29 @@ alias banlist              "qc_cmd_sv     banlist              ${* ?}" // List a
 alias kickban              "qc_cmd_sv     kickban              ${* ?}" // Disconnect a client and ban it at the same time
 alias mute                 "qc_cmd_sv     mute                 ${* ?}" // Disallow a client from talking by muting them
 alias unban                "qc_cmd_sv     unban                ${* ?}" // Remove an existing ban
-alias unmute               "qc_cmd_sv     unmute               ${* ?}" // Unmute a client
+alias unmute               "qc_cmd_sv     unmute               ${* ?}" // Unmute a client (Remove an existing muting ban)
 
 // other aliases for ban commands
 alias bans "banlist"
 
+
+// Client
+alias ignore                  "qc_cmd_cmd    ignore               ${* ?}" // Keep client out of your personal chat log for a match
+alias unignore                "qc_cmd_cmd    unignore             ${* ?}" // Remove an existing ignored client
+alias clear_ignores           "qc_cmd_cmd    clear_ignores"               // Remove all existing ignored clients
+
+// Server
+alias playban                 "qc_cmd_sv     playban              ${* ?}" // Ban disallowing a client from playing (forced to spectate)
+alias unplayban               "qc_cmd_sv     unplayban            ${* ?}" // Remove an existing play ban client
+alias voteban                 "qc_cmd_sv     voteban              ${* ?}" // Ban disallowing a client from voting
+alias unvoteban               "qc_cmd_sv     unvoteban            ${* ?}" // Remove an existing vote ban client
+
+// other aliases for muteban, playban and voteban lists
+alias mutebans  "g_muteban_list ${* ?}"
+alias playbans  "g_playban_list ${* ?}"
+alias votebans  "g_voteban_list ${* ?}"
+
+
 // character classes (intersected with 32..126 minus ", $, ;, ^, \ - if you
 // want these, include them explicitly)
 // note that QC code always forbids $ and ; in VoteCommand_checknasty
index c2225f26e1f6e43a5739e3fbb48932c0b61ab5f6..b38304dbe88d72fa9bb766eab7ba0e5c8334a191 100644 (file)
@@ -96,7 +96,11 @@ seta notification_ANNCE_VOTE_FAIL "2" "0 = disabled, 1 = enabled if gentle mode
 // MSG_INFO notifications:
 seta notification_INFO_CA_JOIN_LATE "1" "0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
 seta notification_INFO_CA_LEAVE "1" "0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_CHAT_DISABLED "2" "0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
 seta notification_INFO_CHAT_NOSPECTATORS "2" "0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_CHAT_PRIVATE_DISABLED "2" "0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_CHAT_SPECTATOR_DISABLED "2" "0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_CHAT_TEAM_DISABLED "2" "0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
 seta notification_INFO_COINTOSS "2" "0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
 seta notification_INFO_CONNECTING "1" "0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
 seta notification_INFO_COUNTDOWN_RESTART "2" "0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
@@ -258,6 +262,7 @@ seta notification_INFO_QUIT_DISCONNECT "2" "0 = off, 1 = print to console, 2 = p
 seta notification_INFO_QUIT_KICK_IDLING "2" "0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
 seta notification_INFO_QUIT_KICK_SPECTATING "1" "0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
 seta notification_INFO_QUIT_KICK_TEAMKILL "2" "0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_QUIT_PLAYBAN_TEAMKILL "2" "0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
 seta notification_INFO_QUIT_SPECTATE "2" "0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
 seta notification_INFO_RACE_ABANDONED "1" "0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
 seta notification_INFO_RACE_FAIL_RANKED "1" "0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
@@ -476,6 +481,7 @@ seta notification_CENTER_ITEM_WEAPON_NOAMMO "1" "0 = off, 1 = centerprint"
 seta notification_CENTER_ITEM_WEAPON_PRIMORSEC "1" "0 = off, 1 = centerprint"
 seta notification_CENTER_ITEM_WEAPON_UNAVAILABLE "1" "0 = off, 1 = centerprint"
 seta notification_CENTER_JOIN_NOSPAWNS "1" "0 = off, 1 = centerprint"
+seta notification_CENTER_JOIN_PLAYBAN "1" "0 = off, 1 = centerprint"
 seta notification_CENTER_JOIN_PREVENT "1" "0 = off, 1 = centerprint"
 seta notification_CENTER_JOIN_PREVENT_MINIGAME "1" "0 = off, 1 = centerprint"
 seta notification_CENTER_KEEPAWAY_DROPPED "1" "0 = off, 1 = centerprint"
@@ -523,6 +529,7 @@ seta notification_CENTER_POWERUP_INVISIBILITY "1" "0 = off, 1 = centerprint"
 seta notification_CENTER_POWERUP_SHIELD "1" "0 = off, 1 = centerprint"
 seta notification_CENTER_POWERUP_SPEED "1" "0 = off, 1 = centerprint"
 seta notification_CENTER_POWERUP_STRENGTH "1" "0 = off, 1 = centerprint"
+seta notification_CENTER_QUIT_PLAYBAN_TEAMKILL "1" "0 = off, 1 = centerprint"
 seta notification_CENTER_RACE_FINISHLAP "1" "0 = off, 1 = centerprint"
 seta notification_CENTER_ROUND_OVER "1" "0 = off, 1 = centerprint"
 seta notification_CENTER_ROUND_PLAYER_WIN "1" "0 = off, 1 = centerprint"
@@ -550,6 +557,8 @@ seta notification_CENTER_VEHICLE_ENTER_GUNNER "1" "0 = off, 1 = centerprint"
 seta notification_CENTER_VEHICLE_ENTER_STEAL "1" "0 = off, 1 = centerprint"
 seta notification_CENTER_VEHICLE_STEAL "1" "0 = off, 1 = centerprint"
 seta notification_CENTER_VEHICLE_STEAL_SELF "1" "0 = off, 1 = centerprint"
+seta notification_CENTER_VOTEBAN "1" "0 = off, 1 = centerprint"
+seta notification_CENTER_VOTEBANYN "1" "0 = off, 1 = centerprint"
 seta notification_CENTER_WEAPON_MINELAYER_LIMIT "1" "0 = off, 1 = centerprint"
 
 // MSG_MULTI notifications:
index f8e364fddca307cab249b853f72c8ec3ac6921a5..5d55fc1cf6cdfe8cf74555c0fd69680fdbb7b68c 100644 (file)
@@ -1,7 +1,10 @@
 #include "sv_kick_teamkiller.qh"
+#include <server/ipban.qh>
 
 float autocvar_g_kick_teamkiller_rate;
 float autocvar_g_kick_teamkiller_lower_limit;
+int autocvar_g_kick_teamkiller_severity;
+float autocvar_g_kick_teamkiller_bantime;
 
 REGISTER_MUTATOR(kick_teamkiller, (autocvar_g_kick_teamkiller_rate > 0));
 
@@ -21,14 +24,53 @@ MUTATOR_HOOKFUNCTION(kick_teamkiller, PlayerDies)
                return;
        }
 
+       float masksize = autocvar_g_ban_default_masksize;
+       float bantime = autocvar_g_kick_teamkiller_bantime;
+
        int teamkills = PlayerScore_Get(attacker, SP_TEAMKILLS);
        // use the players actual playtime
        float playtime = time - CS(attacker).startplaytime;
        // rate is in teamkills/minutes, playtime in seconds
        if (teamkills >= autocvar_g_kick_teamkiller_lower_limit &&
-           teamkills >= autocvar_g_kick_teamkiller_rate*playtime/60.0)
+               teamkills >= autocvar_g_kick_teamkiller_rate*playtime/60.0)
        {
-               if (dropclient_schedule(attacker))
-                       Send_Notification(NOTIF_ALL, NULL, MSG_INFO, INFO_QUIT_KICK_TEAMKILL, attacker.netname);
+               switch (autocvar_g_kick_teamkiller_severity)
+               {
+                       case 1:
+                       {
+                               if (dropclient_schedule(attacker))
+                                       Send_Notification(NOTIF_ALL, NULL, MSG_INFO, INFO_QUIT_KICK_TEAMKILL, attacker.netname);
+                               return;
+                       }
+                       case 2:
+                       {
+                               attacker.respawn_flags = RESPAWN_SILENT;
+                               Ban_KickBanClient(attacker, bantime, masksize, "Team Killing");
+                               Send_Notification(NOTIF_ALL, NULL, MSG_INFO, INFO_QUIT_KICK_TEAMKILL, attacker.netname);
+                               return;
+                       }
+                       default:
+                       {
+                               attacker.respawn_flags = RESPAWN_SILENT;
+                               string theid = "";
+
+                               if(!PlayerInIPList(attacker, autocvar_g_playban_list))
+                                       theid = cons(theid, attacker.netaddress);
+                               if(!PlayerInIDList(attacker, autocvar_g_playban_list))
+                                       theid = cons(theid, attacker.crypto_idfp);
+
+                               LOG_INFO(strcat("Play-banning player ", GetCallerName(attacker), " (", attacker.netaddress, ")."));
+                               PutObserverInServer(attacker, true, true);
+                               cvar_set("g_playban_list", cons(autocvar_g_playban_list, theid));
+
+                               Send_Notification(NOTIF_ALL, NULL, MSG_INFO, INFO_QUIT_PLAYBAN_TEAMKILL, attacker.netname);
+                               Send_Notification(NOTIF_ONE, attacker, MSG_CENTER, CENTER_QUIT_PLAYBAN_TEAMKILL);
+
+                               if (PlayerInList(attacker, autocvar_g_playban_list))
+                                       TRANSMUTE(Observer, attacker);
+
+                               return;
+                       }
+               }
        }
 }
index aa42501a017f073c8c65c7c7fbea654685a405af..061d951a66015b6752470980a649bbf427d7a54a 100644 (file)
@@ -231,7 +231,11 @@ string multiteam_info_sprintf(string input, string teamname) { return ((input !=
     MSG_INFO_NOTIF_TEAM(NUM_TEAM_4, prefix##_PINK, prefix, defaultvalue, strnum, flnum, args, hudargs, multiteam_info_sprintf(icon, strtolower(STATIC_NAME_TEAM_4)), TCR(normal, type, 4), TCR(gentle, type, 4))
 
 // MSG_INFO_NOTIFICATIONS
+    MSG_INFO_NOTIF(CHAT_DISABLED,                           N_CHATCON,  0, 0, "", "",       "",     _("^F4NOTE: ^BGChat is currently disabled on this server"), "")
     MSG_INFO_NOTIF(CHAT_NOSPECTATORS,                       N_CHATCON,  0, 0, "", "",       "",     _("^F4NOTE: ^BGSpectator chat is not sent to players during the match"), "")
+    MSG_INFO_NOTIF(CHAT_PRIVATE_DISABLED,                   N_CHATCON,  0, 0, "", "",       "",     _("^F4NOTE: ^BGPrivate chat is currently disabled on this server"), "")
+    MSG_INFO_NOTIF(CHAT_SPECTATOR_DISABLED,                 N_CHATCON,  0, 0, "", "",       "",     _("^F4NOTE: ^BGSpectator chat is currently disabled on this server"), "")
+    MSG_INFO_NOTIF(CHAT_TEAM_DISABLED,                      N_CHATCON,  0, 0, "", "",       "",     _("^F4NOTE: ^BGTeam chat is currently disabled on this server"), "")
 
     MULTITEAM_INFO(CTF_CAPTURE,                             N_CONSOLE,  1, 0, "s1", "s1",                       "notify_%s_captured",       _("^BG%s^BG captured the ^TC^TT^BG flag"), "", FLAG)
     MULTITEAM_INFO(CTF_CAPTURE_BROKEN,                      N_CONSOLE,  2, 2, "s1 f1dtime s2 f2dtime", "s1",    "notify_%s_captured",       _("^BG%s^BG captured the ^TC^TT^BG flag in ^F1%s^BG seconds, breaking ^BG%s^BG's previous record of ^F2%s^BG seconds"), "", FLAG)
@@ -423,6 +427,7 @@ string multiteam_info_sprintf(string input, string teamname) { return ((input !=
     MSG_INFO_NOTIF(MOVETOSPEC_IDLING,                       N_CHATCON,  1, 1, "s1 f1", "",      "",             _("^BG%s^F3 was moved to^BG spectators^F3 after idling for %s seconds"), "")
     MSG_INFO_NOTIF(QUIT_KICK_SPECTATING,                    N_CONSOLE,  0, 0, "", "",           "",             _("^F2You were kicked from the server because you are a spectator and spectators aren't allowed at the moment."), "")
     MSG_INFO_NOTIF(QUIT_KICK_TEAMKILL,                      N_CHATCON,  1, 0, "s1", "",         "",             _("^BG%s^F3 was kicked for excessive teamkilling"), "")
+    MSG_INFO_NOTIF(QUIT_PLAYBAN_TEAMKILL,                   N_CHATCON,  1, 0, "s1", "",         "",             _("^BG%s^F3 was forced to spectate for excessive teamkilling"), "")
     MSG_INFO_NOTIF(QUIT_SPECTATE,                           N_CHATCON,  1, 0, "s1", "",         "",             _("^BG%s^F3 is now^BG spectating"), "")
 
     MSG_INFO_NOTIF(RACE_ABANDONED,                          N_CONSOLE,  1, 0, "s1", "",                                                                     "",                         _("^BG%s^BG has abandoned the race"), "")
@@ -709,6 +714,7 @@ string multiteam_info_sprintf(string input, string teamname) { return ((input !=
 
     MSG_CENTER_NOTIF(JOIN_NOSPAWNS,                     N_ENABLE,    0, 0, "",               CPID_PREVENT_JOIN,      "0 0",  _("^K1No spawnpoints available!\nHope your team can fix it..."), "")
     MSG_CENTER_NOTIF(JOIN_PREVENT,                      N_ENABLE,    0, 1, "f1",             CPID_PREVENT_JOIN,      "0 0",  _("^K1You may not join the game at this time.\nThis match is limited to ^F2%s^BG players."), "")
+    MSG_CENTER_NOTIF(JOIN_PLAYBAN,                      N_ENABLE,    0, 0, "",               CPID_PREVENT_JOIN,      "0 0",  BOLD(_("^K1You aren't allowed to play because you are banned in this server, but you can play minigames")), "")
 
     MSG_CENTER_NOTIF(KEEPAWAY_DROPPED,                  N_ENABLE,    1, 0, "s1",             CPID_KEEPAWAY,          "0 0",  _("^BG%s^BG has dropped the ball!"), "")
     MSG_CENTER_NOTIF(KEEPAWAY_PICKUP,                   N_ENABLE,    1, 0, "s1",             CPID_KEEPAWAY,          "0 0",  _("^BG%s^BG has picked up the ball!"), "")
@@ -769,6 +775,8 @@ string multiteam_info_sprintf(string input, string teamname) { return ((input !=
     MSG_CENTER_NOTIF(POWERUP_INVISIBILITY,              N_ENABLE,    0, 0, "",               CPID_POWERUP,           "0 0",  _("^F2You are invisible"), "")
     MSG_CENTER_NOTIF(POWERDOWN_INVISIBILITY,            N_ENABLE,    0, 0, "",               CPID_POWERUP,           "0 0",  _("^F2Invisibility has worn off"), "")
 
+    MSG_CENTER_NOTIF(QUIT_PLAYBAN_TEAMKILL,             N_ENABLE,    0, 0, "",               CPID_Null,              "0 0",  BOLD(_("^K1You are forced to spectate and you aren't allowed to play because you are banned in this server")), "")
+
     MSG_CENTER_NOTIF(RACE_FINISHLAP,                    N_ENABLE,    0, 0, "",               CPID_RACE_FINISHLAP,    "0 0",  _("^F2The race is over, finish your lap!"), "")
 
     MSG_CENTER_NOTIF(SEQUENCE_COMPLETED,                N_ENABLE,    0, 0, "",               CPID_Null,              "0 0",  _("^BGSequence completed!"), "")
@@ -800,6 +808,9 @@ string multiteam_info_sprintf(string input, string teamname) { return ((input !=
     MSG_CENTER_NOTIF(VEHICLE_STEAL,                     N_ENABLE,    0, 0, "",               CPID_VEHICLES_OTHER,    "0 0",  _("^F2The enemy is stealing one of your vehicles!\n^F4Stop them!"), "")
     MSG_CENTER_NOTIF(VEHICLE_STEAL_SELF,                N_ENABLE,    0, 0, "",               CPID_VEHICLES_OTHER,    "4 0",  _("^F2Intruder detected, disabling shields!"), "")
 
+    MSG_CENTER_NOTIF(VOTEBAN,                           N_ENABLE,    0, 0, "",               CPID_Null,              "0 0",  BOLD(_("^K1You aren't allowed to call a vote because you are banned in this server")), "")
+    MSG_CENTER_NOTIF(VOTEBANYN,                         N_ENABLE,    0, 0, "",               CPID_Null,              "0 0",  BOLD(_("^K1You aren't allowed to vote because you are banned in this server")), "")
+
     MSG_CENTER_NOTIF(WEAPON_MINELAYER_LIMIT,            N_ENABLE,    0, 1, "f1",             CPID_Null,              "0 0",  _("^BGYou cannot place more than ^F2%s^BG mines at a time"), "")
 
 #undef N_DISABL
index 79d8665237b665841b54e0451e844cd1456e94f9..5a72b59774478a32cf5aacaf046ad4a864ab510b 100644 (file)
@@ -3,10 +3,12 @@
 #include <common/gamemodes/_mod.qh>
 #include <common/mapobjects/target/location.qh>
 #include <common/mapobjects/triggers.qh>
+#include <common/notifications/all.qh>
 #include <common/teams.qh>
 #include <common/util.qh>
 #include <common/weapons/weapon.qh>
 #include <common/wepent.qh>
+#include <server/command/cmd.qh>
 #include <server/command/common.qh>
 #include <server/gamelog.qh>
 #include <server/main.qh>
  */
 int Say(entity source, int teamsay, entity privatesay, string msgin, bool floodcontrol)
 {
+       if(!autocvar_g_chat_allowed && IS_REAL_CLIENT(source))
+       {
+               Send_Notification(NOTIF_ONE_ONLY, source, MSG_INFO, INFO_CHAT_DISABLED);
+               return 0;
+       }
+
+       if(!autocvar_g_chat_private_allowed && privatesay)
+       {
+               Send_Notification(NOTIF_ONE_ONLY, source, MSG_INFO, INFO_CHAT_PRIVATE_DISABLED);
+               return 0;
+       }
+
+       if(!autocvar_g_chat_spectator_allowed && IS_OBSERVER(source))
+       {
+               Send_Notification(NOTIF_ONE_ONLY, source, MSG_INFO, INFO_CHAT_SPECTATOR_DISABLED);
+               return 0;
+       }
+
+       if(!autocvar_g_chat_team_allowed && teamsay)
+       {
+               Send_Notification(NOTIF_ONE_ONLY, source, MSG_INFO, INFO_CHAT_TEAM_DISABLED);
+               return 0;
+       }
+
        if (!teamsay && !privatesay && substring(msgin, 0, 1) == " ")
                msgin = substring(msgin, 1, -1); // work around DP say bug (say_team does not have this!)
 
@@ -283,6 +309,9 @@ int Say(entity source, int teamsay, entity privatesay, string msgin, bool floodc
                        if (!autocvar_g_chat_tellprivacy) { dedicated_print(msgstr); } // send to server console too if "tellprivacy" is disabled
                        if(!MUTATOR_CALLHOOK(ChatMessageTo, privatesay, source))
                        {
+                               if(IS_REAL_CLIENT(source) && ignore_playerinlist(source, privatesay)) // check ignored players from personal chat log (from "ignore" command)
+                                       return -1; // no sending to this player, thank you very much
+
                                sprint(privatesay, msgstr);
                                if(cmsgstr != "")
                                        centerprint(privatesay, cmsgstr);
@@ -293,6 +322,9 @@ int Say(entity source, int teamsay, entity privatesay, string msgin, bool floodc
                        sprint(source, sourcemsgstr);
                        dedicated_print(msgstr); // send to server console too
                        FOREACH_CLIENT(IS_REAL_CLIENT(it) && it != source && CS(it).active_minigame == CS(source).active_minigame && !MUTATOR_CALLHOOK(ChatMessageTo, it, source), {
+                               if(IS_REAL_CLIENT(source) && ignore_playerinlist(source, it)) // check ignored players from personal chat log (from "ignore" command)
+                                       continue; // no sending to this player, thank you very much
+
                                sprint(it, msgstr);
                        });
                        event_log_msg = sprintf(":chat_minigame:%d:%s:%s", source.playerid, CS(source).active_minigame.netname, msgin);
@@ -305,6 +337,9 @@ int Say(entity source, int teamsay, entity privatesay, string msgin, bool floodc
                        if(sourcecmsgstr != "")
                                centerprint(source, sourcecmsgstr);
                        FOREACH_CLIENT((IS_PLAYER(it) || INGAME(it)) && IS_REAL_CLIENT(it) && it != source && it.team == source.team && !MUTATOR_CALLHOOK(ChatMessageTo, it, source), {
+                               if(IS_REAL_CLIENT(source) && ignore_playerinlist(source, it)) // check ignored players from personal chat log (from "ignore" command)
+                                       continue; // no sending to this player, thank you very much
+
                                sprint(it, msgstr);
                                if(cmsgstr != "")
                                        centerprint(it, cmsgstr);
@@ -316,6 +351,9 @@ int Say(entity source, int teamsay, entity privatesay, string msgin, bool floodc
                        sprint(source, sourcemsgstr);
                        dedicated_print(msgstr); // send to server console too
                        FOREACH_CLIENT(!(IS_PLAYER(it) || INGAME(it)) && IS_REAL_CLIENT(it) && it != source && !MUTATOR_CALLHOOK(ChatMessageTo, it, source), {
+                               if(IS_REAL_CLIENT(source) && ignore_playerinlist(source, it)) // check ignored players from personal chat log (from "ignore" command)
+                                       continue; // no sending to this player, thank you very much
+
                                sprint(it, msgstr);
                        });
                        event_log_msg = sprintf(":chat_spec:%d:%s", source.playerid, strreplace("\n", " ", msgin));
@@ -328,6 +366,9 @@ int Say(entity source, int teamsay, entity privatesay, string msgin, bool floodc
                                MX_Say(strcat(playername(source.netname, source.team, IS_PLAYER(source)), "^7: ", msgin));
                        }
                        FOREACH_CLIENT(IS_REAL_CLIENT(it) && it != source && !MUTATOR_CALLHOOK(ChatMessageTo, it, source), {
+                               if(IS_REAL_CLIENT(source) && ignore_playerinlist(source, it)) // check ignored players from personal chat log (from "ignore" command)
+                                       continue; // no sending to this player, thank you very much
+
                                sprint(it, msgstr);
                        });
                        event_log_msg = sprintf(":chat:%d:%s", source.playerid, strreplace("\n", " ", msgin));
@@ -348,7 +389,7 @@ entity findnearest(vector point, bool checkitems, vector axismod)
 
     IL_EACH(((checkitems) ? g_items : g_locations), ((checkitems) ? (it.target == "###item###") : (it.classname == "target_location")),
     {
-       if ((it.items == IT_KEY1 || it.items == IT_KEY2) && it.target == "###item###")
+        if ((it.items == IT_KEY1 || it.items == IT_KEY2) && it.target == "###item###")
             dist = it.oldorigin;
         else
             dist = it.origin;
index 500d757c02c0a80d82f07b1de0d7f08c35d015df..a921f61ece5c0cd41e60a4344dfffdf7bf4637cb 100644 (file)
@@ -10,6 +10,10 @@ bool autocvar_g_chat_flood_notify_flooder;
 float autocvar_g_chat_flood_spl;
 float autocvar_g_chat_flood_spl_team;
 float autocvar_g_chat_flood_spl_tell;
+bool autocvar_g_chat_allowed;
+bool autocvar_g_chat_private_allowed;
+bool autocvar_g_chat_spectator_allowed;
+bool autocvar_g_chat_team_allowed;
 int autocvar_g_chat_nospectators;
 bool autocvar_g_chat_teamcolors;
 bool autocvar_g_chat_tellprivacy;
index 4c19adcff1081e845e1d2314d8478843fcb7adad..1f61b18aa2729221c2d4be3d7e5bd5b9fd74d8d0 100644 (file)
@@ -51,7 +51,8 @@
 #include <server/chat.qh>
 #include <server/cheats.qh>
 #include <server/clientkill.qh>
-#include <server/command/common.qh>
+#include <server/command/banning.qh>
+#include <server/command/cmd.qh>
 #include <server/command/common.qh>
 #include <server/command/vote.qh>
 #include <server/compat/quake3.qh>
@@ -1186,6 +1187,13 @@ void ClientConnect(entity this)
 
        Handicap_Initialize(this);
 
+       // playban
+       if (PlayerInList(this, autocvar_g_playban_list))
+               TRANSMUTE(Observer, this);
+
+       if (PlayerInList(this, autocvar_g_muteban_list)) // muteban
+               CS(this).muted = true;
+
        MUTATOR_CALLHOOK(ClientConnect, this);
 
        if (player_count == 1)
@@ -1209,6 +1217,20 @@ void ClientDisconnect(entity this)
 {
        assert(IS_CLIENT(this), return);
 
+       /* from "ignore" command */
+       strfree(this.ignore_list);
+       FOREACH_CLIENT(IS_REAL_CLIENT(it) && it.ignore_list,
+       {
+               if(it.crypto_idfp && it.crypto_idfp != "")
+                       continue;
+               string mylist = ignore_removefromlist(it, this);
+               if(it.ignore_list)
+                       strunzone(it.ignore_list);
+
+               it.ignore_list = strzone(mylist);
+       });
+       /* from "ignore" command */
+
        PlayerStats_GameReport_FinalizePlayer(this);
        if (this.vehicle) vehicles_exit(this.vehicle, VHEF_RELEASE);
        if (CS(this).active_minigame) part_minigame(this);
@@ -2026,6 +2048,17 @@ int nJoinAllowed(entity this, entity ignore)
        if(this && (Player_GetForcedTeamIndex(this) == TEAM_FORCE_SPECTATOR))
                return 0; // forced spectators can never join
 
+       static float msg_time = 0;
+       if(this && !INGAME(this) && ignore && PlayerInList(this, autocvar_g_playban_list))
+       {
+               if(time > msg_time)
+               {
+                       Send_Notification(NOTIF_ONE_ONLY, this, MSG_CENTER, CENTER_JOIN_PLAYBAN);
+                       msg_time = time + 0.5;
+               }
+               return 0;
+       }
+
        // TODO simplify this
        int totalClients = 0;
        int currentlyPlaying = 0;
@@ -2044,7 +2077,6 @@ int nJoinAllowed(entity this, entity ignore)
        else if(player_limit > 0 && currentlyPlaying < player_limit)
                free_slots = min(maxclients - totalClients, player_limit - currentlyPlaying);
 
-       static float msg_time = 0;
        if(this && !INGAME(this) && ignore && !free_slots && time > msg_time)
        {
                Send_Notification(NOTIF_ONE_ONLY, this, MSG_CENTER, CENTER_JOIN_PREVENT, player_limit);
@@ -2288,6 +2320,7 @@ void ObserverOrSpectatorThink(entity this)
                if ((is_spec && !(PHYS_INPUT_BUTTON_ATCK(this) || PHYS_INPUT_BUTTON_ATCK2(this)))
                        || (!is_spec && !(PHYS_INPUT_BUTTON_ATCK(this) || PHYS_INPUT_BUTTON_JUMP(this)))) {
                        this.flags |= FL_JUMPRELEASED;
+                       // primary attack pressed
                        if(this.flags & FL_SPAWNING)
                        {
                                this.flags &= ~FL_SPAWNING;
index 33b9d4511967c5c0834fdc9f0190c78b78d10df3..8c607cf9af6af6911098007d0eb5f56a41af7c32 100644 (file)
@@ -359,6 +359,10 @@ void calculate_player_respawn_time(entity this);
 
 bool PlayerInList(entity player, string list);
 
+bool PlayerInIDList(entity p, string idlist);
+
+bool PlayerInIPList(entity p, string iplist);
+
 void ClientData_Touch(entity e);
 
 int nJoinAllowed(entity this, entity ignore);
index a73b09646f983467c7d5efa59d1ebc7896db5d1b..52c7e9c431d9ce75872fb8695d28a85636b8675d 100644 (file)
@@ -119,7 +119,7 @@ void BanCommand_kickban(int request, int argc, string command)
        }
 }
 
-void BanCommand_mute(int request, int argc, string command)  // TODO: Add a sort of mute-"ban" which allows players to be muted based on IP/cryptokey
+void BanCommand_mute(int request, int argc, string command)
 {
        switch (request)
        {
@@ -127,12 +127,20 @@ void BanCommand_mute(int request, int argc, string command)  // TODO: Add a sort
                {
                        if (argc >= 2)
                        {
-                               entity client = GetFilteredEntity(argv(1));
+                               entity client = GetIndexedEntity(argc, 1);
                                float accepted = VerifyClientEntity(client, true, false);
 
                                if (accepted > 0)
                                {
+                                       string theid = "";
+                                       if(!PlayerInIPList(client, autocvar_g_muteban_list))
+                                               theid = cons(theid, client.netaddress);
+                                       if(!PlayerInIDList(client, autocvar_g_muteban_list))
+                                               theid = cons(theid, client.crypto_idfp);
                                        CS(client).muted = true;
+                                       LOG_INFO(strcat("Mute-banning player ", GetCallerName(client), " (", argv(1), ")."));
+                                       cvar_set("g_muteban_list", cons(autocvar_g_muteban_list, theid));
+
                                        return;
                                }
                                else
@@ -148,7 +156,51 @@ void BanCommand_mute(int request, int argc, string command)  // TODO: Add a sort
                {
                        LOG_HELP("Usage:^3 sv_cmd mute <client>");
                        LOG_HELP("  <client> is the entity number or name of the player to mute.");
-                       LOG_HELP("See also: ^2unmute^7");
+                       LOG_HELP("See also: ^2unmute, g_muteban_list^7");
+                       return;
+               }
+       }
+}
+
+void BanCommand_playban(int request, int argc, string command)
+{
+       switch (request)
+       {
+               case CMD_REQUEST_COMMAND:
+               {
+                       if (argc >= 2)
+                       {
+                               entity client = GetIndexedEntity(argc, 1);
+                               float accepted = VerifyClientEntity(client, true, false);
+
+                               if (accepted > 0)
+                               {
+                                       string theid = "";
+                                       if(!PlayerInIPList(client, autocvar_g_playban_list))
+                                               theid = cons(theid, client.netaddress);
+                                       if(!PlayerInIDList(client, autocvar_g_playban_list))
+                                               theid = cons(theid, client.crypto_idfp);
+
+                                       LOG_INFO(strcat("Play-banning player ", GetCallerName(client), " (", argv(1), ")."));
+                                       PutObserverInServer(client, true, true);
+                                       cvar_set("g_playban_list", cons(autocvar_g_playban_list, theid));
+
+                                       return;
+                               }
+                               else
+                               {
+                                       LOG_INFO("playban: ", GetClientErrorString(accepted, argv(1)), ".");
+                               }
+                       }
+               }
+
+               default:
+                       LOG_INFOF("Incorrect parameters for ^2%s^7", argv(0));
+               case CMD_REQUEST_USAGE:
+               {
+                       LOG_HELP("Usage:^3 sv_cmd playban <client>");
+                       LOG_HELP("  <client> is the entity number or name of the player to ban being forced to spectate permanently,");
+                       LOG_HELP("See also: ^2g_playban_list, unplayban^7");
                        return;
                }
        }
@@ -208,12 +260,24 @@ void BanCommand_unmute(int request, int argc)
                {
                        if (argc >= 2)
                        {
-                               entity client = GetFilteredEntity(argv(1));
+                               entity client = GetIndexedEntity(argc, 1);
                                float accepted = VerifyClientEntity(client, true, false);
+                               string original_arg = argv(1);
 
                                if (accepted > 0)
                                {
+                                       string tmp_string = "";
+                                       FOREACH_WORD(autocvar_g_muteban_list, it != client.netaddress,
+                                       {
+                                               if(client.crypto_idfp && it == substring(client.crypto_idfp, 0, strlen(it)))
+                                                       continue;
+                                               tmp_string = cons(tmp_string, it);
+                                       });
+
+                                       cvar_set("g_muteban_list", tmp_string);
+                                       LOG_INFO(strcat("Unmuting player ", GetCallerName(client), " (", original_arg, ")."));
                                        CS(client).muted = false;
+
                                        return;
                                }
                                else
@@ -229,7 +293,140 @@ void BanCommand_unmute(int request, int argc)
                {
                        LOG_HELP("Usage:^3 sv_cmd unmute <client>");
                        LOG_HELP("  <client> is the entity number or name of the player to unmute.");
-                       LOG_HELP("See also: ^2mute^7");
+                       LOG_HELP("See also: ^2mute, g_muteban_list^7");
+                       return;
+               }
+       }
+}
+
+void BanCommand_unplayban(int request, int argc)
+{
+       switch (request)
+       {
+               case CMD_REQUEST_COMMAND:
+               {
+                       if (argv(1))
+                       {
+                               entity client = GetIndexedEntity(argc, 1);
+                               float accepted = VerifyClientEntity(client, true, false);
+                               string original_arg = argv(1);
+
+                               if (accepted > 0)
+                               {
+                                       string tmp_string = "";
+                                       FOREACH_WORD(autocvar_g_playban_list, it != client.netaddress,
+                                       {
+                                               if(client.crypto_idfp && it == substring(client.crypto_idfp, 0, strlen(it)))
+                                                       continue;
+                                               tmp_string = cons(tmp_string, it);
+                                       });
+
+                                       cvar_set("g_playban_list", tmp_string);
+                                       LOG_INFO(strcat("Releasing forced to spectate player ", GetCallerName(client), " (", original_arg, ")."));
+
+                                       return;
+                               }
+                               else
+                               {
+                                       LOG_INFO("unplayban: ", GetClientErrorString(accepted, argv(1)), ".");
+                               }
+                       }
+               }
+
+               default:
+               case CMD_REQUEST_USAGE:
+               {
+                       LOG_HELP("Usage:^3 sv_cmd unplayban <banid>");
+                       LOG_HELP("  Where <banid> is the ID of the forced to spectate ban of which to remove.");
+                       LOG_HELP("See also: ^2playban, g_playban_list^7");
+                       return;
+               }
+       }
+}
+
+void BanCommand_unvoteban(int request, int argc)
+{
+       switch (request)
+       {
+               case CMD_REQUEST_COMMAND:
+               {
+                       if (argv(1))
+                       {
+                               entity client = GetIndexedEntity(argc, 1);
+                               float accepted = VerifyClientEntity(client, true, false);
+                               string original_arg = argv(1);
+
+                               if (accepted > 0)
+                               {
+                                       string tmp_string = "";
+                                       FOREACH_WORD(autocvar_g_voteban_list, it != client.netaddress,
+                                       {
+                                               if(client.crypto_idfp && it == substring(client.crypto_idfp, 0, strlen(it)))
+                                                       continue;
+                                               tmp_string = cons(tmp_string, it);
+                                       });
+
+                                       cvar_set("g_voteban_list", tmp_string);
+                                       LOG_INFO(strcat("Unvote-banning player ", GetCallerName(client), " (", original_arg, ")."));
+
+                                       return;
+                               }
+                               else
+                               {
+                                       LOG_INFO("unvoteban: ", GetClientErrorString(accepted, argv(1)), ".");
+                               }
+                       }
+               }
+
+               default:
+               case CMD_REQUEST_USAGE:
+               {
+                       LOG_HELP("Usage:^3 sv_cmd unvoteban <banid>");
+                       LOG_HELP("  Where <banid> is the ID of the ban from voting of which to remove.");
+                       LOG_HELP("See also: ^2voteban, g_voteban_list^7");
+                       return;
+               }
+       }
+}
+
+void BanCommand_voteban(int request, int argc, string command)
+{
+       switch (request)
+       {
+               case CMD_REQUEST_COMMAND:
+               {
+                       if (argc >= 2)
+                       {
+                               entity client = GetIndexedEntity(argc, 1);
+                               float accepted = VerifyClientEntity(client, true, false);
+
+                               if (accepted > 0)
+                               {
+                                       string theid = "";
+                                       if(!PlayerInIPList(client, autocvar_g_voteban_list))
+                                               theid = cons(theid, client.netaddress);
+                                       if(!PlayerInIDList(client, autocvar_g_voteban_list))
+                                               theid = cons(theid, client.crypto_idfp);
+
+                                       LOG_INFO(strcat("Vote-banning player ", GetCallerName(client), " (", argv(1), ")."));
+                                       cvar_set("g_voteban_list", cons(autocvar_g_voteban_list, theid));
+
+                                       return;
+                               }
+                               else
+                               {
+                                       LOG_INFO("voteban: ", GetClientErrorString(accepted, argv(1)), ".");
+                               }
+                       }
+               }
+
+               default:
+                       LOG_INFOF("Incorrect parameters for ^2%s^7", argv(0));
+               case CMD_REQUEST_USAGE:
+               {
+                       LOG_HELP("Usage:^3 sv_cmd voteban <client>");
+                       LOG_HELP("  <client> is the entity number or name of the player to ban from voting,");
+                       LOG_HELP("See also: ^2g_voteban_list, unvoteban^7");
                        return;
                }
        }
@@ -269,8 +466,12 @@ void BanCommand_(int request)
        BAN_COMMAND("banlist", BanCommand_banlist(request), "List all existing bans") \
        BAN_COMMAND("kickban", BanCommand_kickban(request, arguments, command), "Disconnect a client and ban it at the same time") \
        BAN_COMMAND("mute", BanCommand_mute(request, arguments, command), "Disallow a client from talking by muting them") \
+       BAN_COMMAND("playban", BanCommand_playban(request, arguments, command), "Force to spectate a client permanently") \
        BAN_COMMAND("unban", BanCommand_unban(request, arguments), "Remove an existing ban") \
        BAN_COMMAND("unmute", BanCommand_unmute(request, arguments), "Unmute a client") \
+       BAN_COMMAND("unvoteban", BanCommand_unvoteban(request, arguments), "Remove an existing voting ban") \
+       BAN_COMMAND("unplayban", BanCommand_unplayban(request, arguments), "Remove an existing forced to spectate ban") \
+       BAN_COMMAND("voteban", BanCommand_voteban(request, arguments, command), "Disallow a client from voting") \
        /* nothing */
 
 void BanCommand_macro_help()
index 80eb85b56bf85b1cb4e39ee133cd9fb5d36d3da4..6aa70c6a8028a7dcca41d5ea229c5e51f3d71424 100644 (file)
@@ -10,6 +10,9 @@ string autocvar_g_ban_sync_uri;
 bool autocvar_g_ban_telluser = true;
 string autocvar_g_banned_list;
 bool autocvar_g_banned_list_idmode;
+string autocvar_g_muteban_list; // "List of banned players from chat"
+string autocvar_g_playban_list; // "List of banned players from playing (forced to spectate)"
+string autocvar_g_voteban_list; // "List of banned players from voting"
 
 #define GET_BAN_ARG(v, d) if (argc > reason_arg) { if ((v = stof(argv(reason_arg))) != 0) ++reason_arg; else v = d; } else { v = d; }
 #define GET_BAN_REASON(v, d) if (argc > reason_arg) v = substring(command, argv_start_index(reason_arg), strlen(command) - argv_start_index(reason_arg)); else v = d;
index 947edd891e96e4b171396a5bc054019bcbd76668..0eae7e0e67ad8a5537dfb81b3bdea554dcc84aff 100644 (file)
@@ -70,6 +70,35 @@ void ClientCommand_autoswitch(entity caller, int request, int argc)
        }
 }
 
+void ClientCommand_clear_ignores(entity caller, int request)
+{
+       switch (request)
+       {
+               case CMD_REQUEST_COMMAND:
+               {
+                       bool advanced = (caller.crypto_idfp && caller.crypto_idfp != "");
+
+                       if(!advanced)
+                       {
+                               sprint(caller, "You don't have a stats UID, unable to clear your ignore list.\n");
+                               return;
+                       }
+
+                       ignore_clearall(caller);
+                       sprint(caller, "All permanent ignores cleared!\n");
+                       return;
+               }
+
+               default:
+               case CMD_REQUEST_USAGE:
+               {
+                       sprint(caller, "\nUsage:^3 cmd clear_ignores\n");
+                       sprint(caller, "  Removes all existing ignored clients whose are kept out of personal chat log.\n");
+                       return;
+               }
+       }
+}
+
 void ClientCommand_clientversion(entity caller, int request, int argc)  // internal command, used only by code
 {
        switch (request)
@@ -249,6 +278,78 @@ void ClientCommand_wpeditor(entity caller, int request, int argc)
        }
 }
 
+void ClientCommand_ignore(entity caller, int request, int argc, string command)
+{
+       switch (request)
+       {
+               case CMD_REQUEST_COMMAND:
+               {
+                       if (argc >= 2)
+                       {
+                               bool advanced = (caller.crypto_idfp && caller.crypto_idfp != "");
+
+                               if(!argv(1) || argv(1) == "")
+                               {
+                                       sprint(caller, "This command requires an argument. Use a player's name or their ID from the ^2status^7 command.\n");
+                                       return;
+                               }
+
+                               entity ignore_to = GetIndexedEntity(argc, 1);
+                               float ignore_accepted = VerifyClientEntity(ignore_to, true, false);
+
+                               if (ignore_accepted > 0 && IS_REAL_CLIENT(ignore_to))   // the target is a real client
+                               {
+                                       if (ignore_to != caller) // and we're allowed to ignore them heh
+                                       {
+                                               if(ignore_playerinlist(ignore_to, caller))
+                                               {
+                                                       sprint(caller, ignore_to.netname, " ^7is already ignored!\n");
+                                                       return;
+                                               }
+
+                                               // advanced ignore mode, works if both the player and the sender have a stats UID
+                                               if(advanced && ignore_to.crypto_idfp && ignore_to.crypto_idfp != "")
+                                               {
+                                                       for(int j = 0; j < IGNORE_MAXPLAYERS; ++j)
+                                                       {
+                                                               string pos = db_get(ServerProgsDB, strcat("/ignore/", caller.crypto_idfp, "/", ftos(j)));
+                                                               if(pos == "")
+                                                               {
+                                                                       db_put(ServerProgsDB, strcat("/ignore/", caller.crypto_idfp, "/", ftos(j)), ignore_to.crypto_idfp);
+                                                                       sprint(caller, "You will no longer receive messages from ", ignore_to.netname, "^7, use ^2unignore^7 to hear them again.\n");
+                                                                       return;
+                                                               }
+                                                       }
+
+                                                       sprint(caller, "You may only ignore up to ", ftos(IGNORE_MAXPLAYERS), " players, remove one before trying again.\n");
+                                                       return;
+                                               }
+
+                                               if(caller.ignore_list)
+                                                       strunzone(caller.ignore_list);
+                                               caller.ignore_list = strzone(cons(caller.ignore_list, ftos(etof(ignore_to))));
+
+                                               sprint(caller, "You no longer receive messages from ", ignore_to.netname, "^7, use ^2unignore^7 to hear them again.\n");
+                                       }
+                                       else { sprint(caller, "You can't ^2ignore^7 yourself.\n"); }
+                               }
+                               else { print_to(caller, strcat("ignore: ", GetClientErrorString(ignore_accepted, argv(1)), ".\nUnable to ignore this player, check their ID.")); }
+
+                               return;
+                       }
+               }
+
+               default:
+                       sprint(caller, sprintf("Incorrect parameters for ^2%s^7\n", argv(0)));
+               case CMD_REQUEST_USAGE:
+               {
+                       sprint(caller, "\nUsage:^3 cmd ignore <client>\n");
+                       sprint(caller, "  Where <client> is the entity number or name of the player to ignore keeping out of personal chat log.\n");
+                       return;
+               }
+       }
+}
+
 void ClientCommand_join(entity caller, int request)
 {
        switch (request)
@@ -573,7 +674,7 @@ void ClientCommand_spectate(entity caller, int request)
                                        if(IS_SPEC(caller) || IS_OBSERVER(caller))
                                        {
                                                entity client = GetFilteredEntity(argv(1));
-                                               int spec_accepted = VerifyClientEntity(client, false, false);
+                                               float spec_accepted = VerifyClientEntity(client, false, false);
                                                if(spec_accepted > 0 && IS_PLAYER(client))
                                                {
                                                        bool caller_is_observer = (IS_OBSERVER(caller));
@@ -691,6 +792,60 @@ void ClientCommand_tell(entity caller, int request, int argc, string command)
        }
 }
 
+void ClientCommand_unignore(entity caller, int request, int argc, string command)
+{
+       switch (request)
+       {
+               case CMD_REQUEST_COMMAND:
+               {
+                       if (argc >= 2)
+                       {
+                               bool advanced = (caller.crypto_idfp && caller.crypto_idfp != "");
+
+                               if(!argv(1) || argv(1) == "")
+                               {
+                                       sprint(caller, "This command requires an argument. Use a player's name or their ID from the ^2status^7 command.\n");
+                                       return;
+                               }
+
+                               entity unignore_to = GetIndexedEntity(argc, 1);
+                               float unignore_accepted = VerifyClientEntity(unignore_to, true, false);
+
+                               if (unignore_accepted > 0 && IS_REAL_CLIENT(unignore_to))   // the target is a real client
+                               {
+                                       if (unignore_to != caller)
+                                       {
+                                               string mylist = ignore_removefromlist(caller, unignore_to);
+                                               if(!advanced)
+                                               {
+                                                       if(caller.ignore_list)
+                                                               strunzone(caller.ignore_list);
+
+                                                       caller.ignore_list = strzone(mylist);
+                                               }
+
+                                               sprint(caller, "You can now receive messages from ", unignore_to.netname, " ^7again.\n");
+                                               return;
+                                       }
+                                       else { sprint(caller, "You can't ^2unignore^7 yourself.\n"); }
+                               }
+                               else {  print_to(caller, strcat("unignore: ", GetClientErrorString(unignore_accepted, argv(1)), ".\nUnable to stop ignoring this player, check their ID.")); }
+
+                               return;
+                       }
+               }
+
+               default:
+                       sprint(caller, sprintf("Incorrect parameters for ^2%s^7\n", argv(0)));
+               case CMD_REQUEST_USAGE:
+               {
+                       sprint(caller, "\nUsage:^3 cmd unignore <client>\n");
+                       sprint(caller, "  Where <client> is the entity number or name of the player to stop ignoring when is keeping out of personal chat log.\n");
+                       return;
+               }
+       }
+}
+
 void ClientCommand_voice(entity caller, int request, int argc, string command)
 {
        switch (request)
@@ -770,7 +925,9 @@ void ClientCommand_(entity caller, int request)
 // Do not hard code aliases for these, instead create them in commands.cfg... also: keep in alphabetical order, please ;)
 #define CLIENT_COMMANDS(ent, request, arguments, command) \
        CLIENT_COMMAND("autoswitch", ClientCommand_autoswitch(ent, request, arguments), "Whether or not to switch automatically when getting a better weapon") \
+       CLIENT_COMMAND("clear_ignores", ClientCommand_clear_ignores(ent, request), "Remove all existing ignored clients") \
        CLIENT_COMMAND("clientversion", ClientCommand_clientversion(ent, request, arguments), "Release version of the game") \
+       CLIENT_COMMAND("ignore", ClientCommand_ignore(ent, request, arguments, command), "Ignore a client in the game keeping out of personal chat log for a match") \
        CLIENT_COMMAND("join", ClientCommand_join(ent, request), "Become a player in the game") \
        CLIENT_COMMAND("kill", ClientCommand_kill(ent, request), "Become a member of the dead") \
        CLIENT_COMMAND("minigame", ClientCommand_minigame(ent, request, arguments, command), "Start a minigame") \
@@ -786,6 +943,7 @@ void ClientCommand_(entity caller, int request)
        CLIENT_COMMAND("suggestmap", ClientCommand_suggestmap(ent, request, arguments), "Suggest a map to the mapvote at match end") \
        CLIENT_COMMAND("tell", ClientCommand_tell(ent, request, arguments, command), "Send a message directly to a player") \
        CLIENT_COMMAND("voice", ClientCommand_voice(ent, request, arguments, command), "Send voice message via sound") \
+       CLIENT_COMMAND("unignore", ClientCommand_unignore(ent, request, arguments, command), "Remove an existing ignored player") \
        CLIENT_COMMAND("wpeditor", ClientCommand_wpeditor(ent, request, arguments), "Waypoint editor commands") \
        /* nothing */
 
index bb97f0d0b17cf18926d1d0c05a996d4a515e116e..27be10dd32facfdb2cc69719edb3f00628958f9b 100644 (file)
@@ -1,11 +1,84 @@
 #pragma once
 
+#include <server/world.qh>
+
 float autocvar_sv_clientcommand_antispam_time;
 int autocvar_sv_clientcommand_antispam_count;
 
 .float cmd_floodtime;
+.string ignore_list; // stores player id's, maybe can be upgraded to store net address for reconnect protection
+
+const int IGNORE_MAXPLAYERS = 8; // maximum players to be ignored in the personal chat
 
 string MapVote_Suggest(entity this, string m);
 
 // used by common/command/generic.qc:GenericCommand_dumpcommands to list all commands into a .txt file
 void ClientCommand_macro_write_aliases(float fh);
+
+// functions for ignore command
+string ignore_removefromlist(entity list, entity ignore)
+{
+       if(ignore.crypto_idfp && ignore.crypto_idfp != "" && list.crypto_idfp && list.crypto_idfp != "")
+       {
+               for(int j = 0; j < IGNORE_MAXPLAYERS; ++j)
+               {
+                       string pos = db_get(ServerProgsDB, strcat("/ignore/", list.crypto_idfp, "/", ftos(j)));
+                       if(pos == ignore.crypto_idfp)
+                       {
+                               db_remove(ServerProgsDB, strcat("/ignore/", list.crypto_idfp, "/", ftos(j)));
+                               return string_null;
+                       }
+               }
+               // should this fall back? we know advanced mode is being used
+       }
+
+       string newlist = "";
+       string theid = ftos(etof(ignore));
+
+       FOREACH_WORD(list.ignore_list, it != theid,
+       {
+               newlist = cons(newlist, it);
+       });
+
+       if(newlist == "")
+               return string_null;
+       else
+               return newlist;
+}
+
+bool ignore_playerinlist(entity sender, entity targ)
+{
+       // TODO: optimize this by saving it to .ignore_list?
+       if(targ.crypto_idfp && targ.crypto_idfp != "" && sender.crypto_idfp && sender.crypto_idfp != "")
+       {
+               string thelist = "";
+               for(int j = 0; j < IGNORE_MAXPLAYERS; ++j)
+               {
+                       string pos = db_get(ServerProgsDB, strcat("/ignore/", targ.crypto_idfp, "/", ftos(j)));
+                       thelist = cons(thelist, pos);
+               }
+
+               return ((thelist != "") ? PlayerInList(sender, thelist) : false);
+       }
+       else if(!targ.ignore_list || targ.ignore_list == "")
+               return false;
+
+       string theid = ftos(etof(sender));
+
+       FOREACH_WORD(targ.ignore_list, it == theid,
+       {
+               return true;
+       });
+
+       return false;
+}
+
+void ignore_clearall(entity this)
+{
+       for(int j = 0; j < IGNORE_MAXPLAYERS; ++j)
+       {
+               string pos = db_get(ServerProgsDB, strcat("/ignore/", this.crypto_idfp, "/", ftos(j)));
+               if(pos != "")
+                       db_remove(ServerProgsDB, strcat("/ignore/", this.crypto_idfp, "/", ftos(j)));
+       }
+}
index 28fa7e7c056dae29e0675fce7c1eeb467fa4d469..6af0a28e4a79deb902c1e2e90ecfdaf7bc715f6a 100644 (file)
@@ -849,6 +849,13 @@ void VoteCommand_abstain(int request, entity caller)  // CLIENT ONLY
        {
                case CMD_REQUEST_COMMAND:
                {
+                       if (PlayerInList(caller, autocvar_g_voteban_list)) // voteban
+                       {
+                               print_to(caller, "^1You are banned from voting.");
+                               Send_Notification(NOTIF_ONE, caller, MSG_CENTER, CENTER_VOTEBANYN);
+                               return;
+                       }
+
                        if (!vote_called) { print_to(caller, "^1No vote called."); }
                        else if (caller.vote_selection != VOTE_SELECT_NULL && !autocvar_sv_vote_change)
                        {
@@ -891,6 +898,13 @@ void VoteCommand_call(int request, entity caller, int argc, string vote_command)
                        float tmp_playercount = 0;
                        int parse_error;
 
+                       if (PlayerInList(caller, autocvar_g_voteban_list)) // voteban
+                       {
+                               print_to(caller, "^1You are banned from calling a vote.");
+                               Send_Notification(NOTIF_ONE, caller, MSG_CENTER, CENTER_VOTEBAN);
+                               return;
+                       }
+
                        vote_command = VoteCommand_extractcommand(vote_command, 2, argc);
 
                        if (!autocvar_sv_vote_call && caller)
@@ -1106,6 +1120,13 @@ void VoteCommand_no(int request, entity caller)  // CLIENT ONLY
        {
                case CMD_REQUEST_COMMAND:
                {
+                       if (PlayerInList(caller, autocvar_g_voteban_list)) // voteban
+                       {
+                               print_to(caller, "^1You are banned from voting.");
+                               Send_Notification(NOTIF_ONE, caller, MSG_CENTER, CENTER_VOTEBANYN);
+                               return;
+                       }
+
                        if (!vote_called) { print_to(caller, "^1No vote called."); }
                        else if (caller.vote_selection != VOTE_SELECT_NULL && !autocvar_sv_vote_change)
                        {
@@ -1188,6 +1209,13 @@ void VoteCommand_yes(int request, entity caller)  // CLIENT ONLY
        {
                case CMD_REQUEST_COMMAND:
                {
+                       if (PlayerInList(caller, autocvar_g_voteban_list)) // voteban
+                       {
+                               print_to(caller, "^1You are banned from voting.");
+                               Send_Notification(NOTIF_ONE, caller, MSG_CENTER, CENTER_VOTEBANYN);
+                               return;
+                       }
+
                        if (!vote_called) { print_to(caller, "^1No vote called."); }
                        else if (caller.vote_selection != VOTE_SELECT_NULL && !autocvar_sv_vote_change)
                        {
index 124ca5afe85f32bf06e9f925a1372b2e8d56e8f8..b3b31ff1b9381c80761fd80ff416bbbb97130d79 100644 (file)
@@ -236,6 +236,9 @@ void cvar_changes_init()
                BADCVAR("timeformat");
                BADCVAR("timestamps");
                BADCVAR("g_require_stats");
+               BADCVAR("g_muteban_list");
+               BADCVAR("g_playban_list");
+               BADCVAR("g_voteban_list");
                BADPREFIX("developer_");
                BADPREFIX("g_ban_");
                BADPREFIX("g_banned_list");
@@ -259,8 +262,6 @@ void cvar_changes_init()
 
                // these can contain player IDs, so better hide
                BADPREFIX("g_forced_team_");
-               BADCVAR("sv_muteban_list");
-               BADCVAR("sv_voteban_list");
                BADCVAR("sv_allow_customplayermodels_idlist");
                BADCVAR("sv_allow_customplayermodels_speciallist");
 
index 03404ebf4555482d04ad7fe4047a7a248f02eb41..08987e7796f3efd9b27e0e8f02816d9bdddd15b5 100644 (file)
@@ -377,7 +377,11 @@ set g_chat_flood_burst_team 2 "team chat: allow bursts of so many chat lines"
 set g_chat_flood_spl_tell 1 "private chat: seconds between lines to not count as flooding"
 set g_chat_flood_lmax_tell 2 "private chat: maximum number of lines per chat message at once"
 set g_chat_flood_burst_tell 2 "private chat: allow bursts of so many chat lines"
-set g_chat_flood_notify_flooder 1 "when 0, the flooder still can see their own message"
+set g_chat_flood_notify_flooder 1 "when disabled, the flooder still can see their own message"
+set g_chat_allowed 1 "allow players to communicate via in-game chat"
+set g_chat_private_allowed 1 "allow players to communicate via in-game private chat"
+set g_chat_spectator_allowed 1 "allow spectators to communicate via in-game chat"
+set g_chat_team_allowed 1 "allow players to communicate via in-game team chat"
 set g_chat_teamcolors 0 "colorize nicknames in team color for chat"
 set g_chat_tellprivacy 1 "when disabled, tell messages are also sent to the server console log... otherwise they're kept private between players."
 set g_nick_flood_timeout 120 "time after which nick flood protection resets (set to 0 to disable nick flood checking)"