rcon2irc enhancements by merlijn
authordiv0 <div0@f962a42d-fe04-0410-a3ab-8c8b0445ebaa>
Mon, 1 Jun 2009 15:21:41 +0000 (15:21 +0000)
committerdiv0 <div0@f962a42d-fe04-0410-a3ab-8c8b0445ebaa>
Mon, 1 Jun 2009 15:21:41 +0000 (15:21 +0000)
git-svn-id: svn://svn.icculus.org/nexuiz/trunk@6835 f962a42d-fe04-0410-a3ab-8c8b0445ebaa

server/rcon2irc/joinsparts.pl [new file with mode: 0644]
server/rcon2irc/ping-pl.pl [new file with mode: 0644]
server/rcon2irc/rcon2irc-example.conf
server/rcon2irc/rcon2irc.pl
server/rcon2irc/suggestmap.pl [new file with mode: 0644]

diff --git a/server/rcon2irc/joinsparts.pl b/server/rcon2irc/joinsparts.pl
new file mode 100644 (file)
index 0000000..8861347
--- /dev/null
@@ -0,0 +1,58 @@
+# Nexuiz rcon2irc plugin by Merlijn Hofstra licensed under GPL - joinsparts.pl
+# Place this file inside the same directory as rcon2irc.pl and add the full filename to the plugins.
+# Don't forget to edit the options below to suit your needs.
+
+my %pj = (
+       irc_announce_joins => 1,
+       irc_announce_parts => 1,
+       irc_show_playerip => 0,
+       irc_show_mapname => 0,
+       irc_show_amount_of_players => 0
+);
+
+$store{plugin_joinsparts} = \%pj;
+
+sub out($$@);
+
+sub get_player_count
+{
+       my $count = 0;
+       for (1 .. $store{slots_max}) {
+               my $id = $store{"playerid_byslot_$_"};
+               $count++ if (defined $id && $store{"playerip_byid_$id"} ne 'bot');
+       }
+       return $count;
+}
+
+# chat: Nexuiz server -> IRC channel, nick set
+[ dp => q{:join:(\d+):(\d+):([^:]*):(.*)} => sub {
+       my ($id, $slot, $ip, $nick) = @_;
+       my $pj = $store{plugin_joinsparts};
+       $store{"playernickraw_byid_$id"} = $nick;
+       $nick = color_dp2irc $nick;
+       if ($pj->{irc_announce_joins} && !$store{"playerid_byslot_$slot"} && $ip ne 'bot') {
+               out irc => 0, "PRIVMSG $config{irc_channel} :\00309+ join\017: $nick\017" . 
+                       ($pj->{irc_show_playerip} ? " (\00304$ip\017)" : '') .
+                       ($pj->{irc_show_mapname} ? " playing on \00304$store{map}\017" : '') .
+                       ($pj->{irc_show_amount_of_players} ? " players: \00304" . (get_player_count()+1) . "\017/$store{slots_max}" : '');
+       }
+       return 0;
+} ],
+# Record parts so the info in $store is always up to date
+[ dp => q{:part:(\d+)} => sub {
+       my ($id) = @_;
+       my $pj = $store{plugin_joinsparts};
+       if ($pj->{irc_announce_parts} && defined $store{"playernick_byid_$id"} && $store{"playerip_byid_$id"} ne 'bot') {
+               out irc => 0, "PRIVMSG $config{irc_channel} :\00304- part\017: " . $store{"playernick_byid_$id"} . "\017" . 
+                       ($pj->{irc_show_playerip} ? " (\00304" . $store{"playerip_byid_$id"} . "\017)" : '') .
+                       ($pj->{irc_show_mapname} ? " playing on \00304$store{map}\017" : '') .
+                       ($pj->{irc_show_amount_of_players} ? " players: \00304" . (get_player_count()-1) . "\017/$store{slots_max}" : '');
+       }
+       my $slot = $store{"playerslot_byid_$id"};
+       $store{"playernickraw_byid_$id"} = undef;
+       $store{"playernick_byid_$id"} = undef;
+       $store{"playerip_byid_$id"} = undef;
+       $store{"playerslot_byid_$id"} = undef;
+       $store{"playerid_byslot_$slot"} = undef;
+       return 0;
+} ],
diff --git a/server/rcon2irc/ping-pl.pl b/server/rcon2irc/ping-pl.pl
new file mode 100644 (file)
index 0000000..627eb3d
--- /dev/null
@@ -0,0 +1,78 @@
+# Nexuiz rcon2irc plugin by Merlijn Hofstra licensed under GPL - ping-pl.pl
+# Place this file inside the same directory as rcon2irc.pl and add the full filename to the plugins.
+# Don't forget to edit the options below to suit your needs.
+
+# This script monitors players ping and packet loss, people with really large values here are 
+# lagging a lot, and this lag appears to other players as well as seeing the lagging player move
+# with lots of stutter. Bare in mind that even those of us on very good connections may lose a
+# packet or have a high ping every once in the while.
+# PLEASE CHOOSE SANE VALUES HERE !!!
+
+my %pp = (
+       max_ping => 300,
+       max_pl => 15,
+       warn_player => 1, # send a tell command to the player to notify of bad connection (0 or 1)
+       warn_irc => 1, # send a warning to irc to notify that a player has a bad connection (0 or 1)
+       warnings => 3, # how many times must ping/pl exceed the limit before a warning
+       kick => 0, # how many times must ping/pl exceed the limit before a kick (0 to disable)
+       timeframe => 20, # minutes until a count is forgotten
+       warnmsg => 'You are having connection problems, causing you to lag - please fix them',
+       kickmsg => 'You are getting kicked for having connection problems.'
+);
+
+$store{plugin_ping-pl} = \%pp;
+
+sub out($$@);
+
+# Check users ping and packet loss
+[ dp => q{\^\d(\S+)\s+(\d+)\s+(\d+)\s+(\S+)\s+(-?\d+)\s+\#(\d+)\s+\^\d(.*)} => sub {
+       my ($ip, $pl, $ping, $time, $frags, $no, $name) = ($1, $2, $3, $4, $5, $6, $7);
+       my $id = $store{"playerid_byslot_$no"};
+       return 0 unless ( defined $id );
+       return 0 if ($frags == -666 || $ip eq 'bot');
+       my $pp = $store{plugin_ping-pl};
+
+       #does the player violate one of our limits?
+       my $warn = 0;
+       if ($ping >= $pp->{max_ping} || $pl >= $pp->{max_pl}) {
+               #add a violation
+               push @{ $pp->{"violation_$id"} }, time();
+               $warn = 1;
+       }
+
+       #maybe we need to clear the oldest violation
+       shift @{ $pp->{"violation_$id"} } if (defined ${ $pp->{"violation_$id"} }[0] && (${ $pp->{"violation_$id"} }[0] + (60 * $pp->{timeframe})) <= time());
+
+       #do we have to kick the user?
+       if ((scalar @{ $pp->{"violation_$id"} }) >= $pp->{kick} && $pp->{kick} > 0) {
+               if ($pp->{warn_player}) {
+                       out dp => 0, "tell #$no " . $pp{kickmsg};
+               }
+               if ($pp->{warn_irc}) {
+                       out irc => 0, "PRIVMSG $config{irc_channel} :* \00304kicking\017 " . $store{"playernick_byid_$id"} . "\017 for having a bad connection";
+               }
+               out dp => 0, "kick # $no bad connection";
+               $pp->{"violation_$id"} = undef;
+               return 0;
+       }
+
+       #do we have to warn the user?
+       if ($warn && (scalar @{ $pp->{"violation_$id"} }) && ((scalar @{ $pp->{"violation_$id"} }) % $pp->{warnings}) == 0) {
+               if ($pp->{warn_player}) {
+                       out dp => 0, "tell #$no $pp{warnmsg}";
+               }
+               if ($pp->{warn_irc}) {
+                       out irc => 0, "PRIVMSG $config{irc_channel} :* \00308warning\017 " . $store{"playernick_byid_$id"} . "\017 for having a bad connection";
+               }
+       }
+       return 0;
+} ],
+
+# For now will just empty our data at the end of a match
+[ dp => q{^:end} => sub {
+       my $pp = $store{plugin_ping-pl};
+       foreach ( keys %{ $pp } ) {
+               $pp->{$_} = undef if ($_ =~ m/^violation/);
+       }
+       return 0;
+} ],
index d899372..e9eac8d 100644 (file)
@@ -25,6 +25,11 @@ irc_channel = #Nexuiz-Pwayers
 # Alternate IRC trigger (can be used instead of nickname to send stuff to the server)
 #irc_trigger = nexnexnex
 
+# Custom output options
+#irc_announce_slotsfree = 1
+# The var irc_announce_mapchange can be set to either never, notempty or always
+#irc_announce_mapchange = always
+
 # Tuning
 #dp_secure = 1
 #dp_server_from_wan =
index 02f1069..be34149 100755 (executable)
@@ -664,6 +664,9 @@ our %config = (
        irc_quakenet_challengeauth => 'PRIVMSG Q@CServe.quakenet.org :CHALLENGEAUTH',
        irc_quakenet_challengeprefix => ':Q!TheQBot@CServe.quakenet.org NOTICE [^:]+ :CHALLENGE',
 
+       irc_announce_slotsfree => 1,
+       irc_announce_mapchange => 'always',
+
        dp_server => undef,
        dp_secure => 1,
        dp_listen => "", 
@@ -1050,8 +1053,8 @@ sub cond($)
                if($full != ($store{slots_full} || 0))
                {
                        $store{slots_full} = $full;
-                       return 0
-                               if $store{lms_blocked};
+                       return 0 if $store{lms_blocked};
+                       return 0 if !$config{irc_announce_slotsfree};
                        if($full)
                        {
                                out irc => 0, "PRIVMSG $config{irc_channel} :\001ACTION is full!\001";
@@ -1142,7 +1145,7 @@ sub cond($)
                        $dpreason =~ s/(["\\])/\\$1/g;
                        out dp => 0, "kick # $id $dpreason";
                        my $slotnik = "playerslot_$id";
-                       out irc => 0, "PRIVMSG $nick :kicked #$id (@{[color_dp2irc $store{$slotnik}{name}]} @ $store{$slotnik}{ip}) ($reason)";
+                       out irc => 0, "PRIVMSG $nick :kicked #$id (@{[color_dp2irc $store{$slotnik}{name}]}\017 @ $store{$slotnik}{ip}) ($reason)";
                        return 0;
                }
 
@@ -1154,7 +1157,7 @@ sub cond($)
                        $dpreason =~ s/(["\\])/\\$1/g;
                        out dp => 0, "kickban # $id $bantime $mask $dpreason";
                        my $slotnik = "playerslot_$id";
-                       out irc => 0, "PRIVMSG $nick :kickbanned #$id (@{[color_dp2irc $store{$slotnik}{name}]} @ $store{$slotnik}{ip}), netmask $mask, for $bantime seconds ($reason)";
+                       out irc => 0, "PRIVMSG $nick :kickbanned #$id (@{[color_dp2irc $store{$slotnik}{name}]}\017 @ $store{$slotnik}{ip}), netmask $mask, for $bantime seconds ($reason)";
                        return 0;
                }
 
@@ -1178,6 +1181,24 @@ sub cond($)
                        return 0;
                }
 
+               if($command =~ /^mute (\d+)$/)
+               {
+                       my $id = $1;
+                       out dp => 0, "mute $id";
+                       my $slotnik = "playerslot_$id";
+                       out irc => 0, "PRIVMSG $nick :muted $id (@{[color_dp2irc $store{$slotnik}{name}]}\017 @ $store{$slotnik}{ip})";
+                       return 0;
+               }
+
+               if($command =~ /^unmute (\d+)$/)
+               {
+                       my ($id) = ($1);
+                       out dp => 0, "unmute $id";
+                       my $slotnik = "playerslot_$id";
+                       out irc => 0, "PRIVMSG $nick :unmuted $id (@{[color_dp2irc $store{$slotnik}{name}]}\017 @ $store{$slotnik}{ip})";
+                       return 0;
+               }
+
                if($command =~ /^quote (.*)$/)
                {
                        my ($cmd) = ($1);
@@ -1193,7 +1214,7 @@ sub cond($)
                        return 0;
                }
 
-               out irc => 0, "PRIVMSG $nick :unknown command (supported: status [substring], kick # id reason, kickban # id bantime mask reason, bans, unban banid)";
+               out irc => 0, "PRIVMSG $nick :unknown command (supported: status [substring], kick # id reason, kickban # id bantime mask reason, bans, unban banid, mute id, unmute id)";
 
                return -1;
        } ],
@@ -1402,8 +1423,10 @@ sub cond($)
                $store{playing} = 1;
                $store{map} = $map;
                $store{map_starttime} = time();
-               my $slotsstr = nex_slotsstring();
-               out irc => 0, "PRIVMSG $config{irc_channel} :\00304" . $map . "\017 has begun$slotsstr";
+               if ($config{irc_announce_mapchange} eq 'always' || ($config{irc_announce_mapchange} eq 'notempty' && $store{slots_active} > 0)) {
+                       my $slotsstr = nex_slotsstring();
+                       out irc => 0, "PRIVMSG $config{irc_channel} :\00304" . $map . "\017 has begun$slotsstr";
+               }
                delete $store{lms_blocked};
                return 0;
        } ],
diff --git a/server/rcon2irc/suggestmap.pl b/server/rcon2irc/suggestmap.pl
new file mode 100644 (file)
index 0000000..0acd66f
--- /dev/null
@@ -0,0 +1,13 @@
+# Nexuiz rcon2irc plugin by Merlijn Hofstra licensed under GPL - suggestmap.pl
+# Place this file inside the same directory as rcon2irc.pl and add the full filename to the plugins.
+
+sub out($$@);
+
+#read the suggest vote
+[ dp => q{:vote:suggested:(.+):(\d+)} => sub {
+       my ($map, $id) = @_;
+       my $nick = color_dp2irc $store{"playernick_byid_$id"};
+       $nick ||= '(console)';
+       out irc => 0, "PRIVMSG $config{irc_channel} :* map suggested: \00304$map\017 by $nick\017";
+       return 0;
+} ],