ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/ext/schmorplog.ext
Revision: 1.28
Committed: Thu Apr 29 07:52:02 2010 UTC (14 years ago) by root
Branch: MAIN
Changes since 1.27: +5 -5 lines
Log Message:
logging

File Contents

# User Rev Content
1 root 1.22 #! perl # depends=irc mandatory
2 root 1.1
3 root 1.17 # statistics-package
4    
5 root 1.12 use Fcntl;
6     use Coro::AIO;
7    
8 root 1.26 our %PLAYERSEEN;
9    
10 root 1.25 our $UPDATE_LOGINS = AE::idle sub {
11 root 1.11 $_[0]->stop;
12    
13 root 1.12 cf::async {
14     my ($status, @pl) = ext::commands::who_listing;
15 root 1.1
16 root 1.12 my $fh = aio_open "$LOCALDIR/usercount", O_WRONLY | O_CREAT | O_TRUNC, 0644
17     or return;
18     aio_write $fh, 0, undef, scalar @pl, 0;
19     aio_close $fh;
20    
21     my $who;
22     for ($status, @pl) {
23     s/[<&]//g;
24     $who .= "$_<br />\n";
25     }
26    
27     my $fh = aio_open "$LOCALDIR/userlisting.html", O_WRONLY | O_CREAT | O_TRUNC, 0644
28     or return;
29     aio_write $fh, 0, undef, $who, 0;
30     aio_close $fh;
31     };
32 root 1.11 };
33 root 1.1
34 root 1.14 cf::object->attach (
35     on_kill => sub {
36     my ($ob, $hitter) = @_;
37    
38     return unless $hitter;
39     $hitter = $hitter->outer_owner;
40     my $pl = $hitter->contr
41     or return;
42    
43 root 1.16 ++$hitter->{stats_kill}{$ob->name};
44 root 1.14 },
45     );
46    
47 root 1.3 cf::player->attach (
48 root 1.1 on_login => sub {
49     my ($pl) = @_;
50 root 1.26
51 root 1.19 $pl->ob->kv_set (schmorplog_last_login => time);
52 root 1.1
53 root 1.19 $pl->ob->kv_set (schmorplog_login_count =>
54     1 + $pl->ob->kv_get ("schmorplog_login_count"));
55 root 1.1
56 root 1.24 $pl->ob->kv_set (schmorplog_client => $pl->ns->{who_version});
57 root 1.1
58 root 1.26 my $name = $pl->ob->name;
59 root 1.1
60 root 1.26 ext::irc::do_notice $name . " logged in";
61    
62     undef $PLAYERSEEN{$name};
63 root 1.1 $UPDATE_LOGINS->start;
64 root 1.5
65 root 1.28 cf::trace "LOGIN: ", $pl->ob->name, " from ", $pl->ns->host;
66 root 1.1 },
67     on_logout => sub {
68 root 1.6 my ($pl, $cleanly) = @_;
69 root 1.19 $pl->ob->kv_set (schmorplog_last_logout => time);
70 root 1.26 ext::irc::do_notice $pl->ob->name . " left";
71 root 1.1
72     $UPDATE_LOGINS->start;
73 root 1.5
74 root 1.28 cf::trace "LOGOUT: ", $pl->ob->name, " from ", $pl->ns->host, " ($cleanly)";
75 root 1.1 },
76     on_birth => sub {
77     my ($pl) = @_;
78 root 1.19 $pl->ob->kv_set (schmorplog_birthdate => time);
79 root 1.26 ext::irc::do_notice $pl->ob->name . " was just born";
80 root 1.5
81 root 1.28 cf::trace "BIRTH: ", $pl->ob->name, " from ", $pl->ns->host;
82 root 1.1 },
83     on_quit => sub {
84     my ($pl) = @_;
85 root 1.26 ext::irc::do_notice $pl->ob->name . " quit the game";
86 root 1.5
87 root 1.28 cf::trace "QUIT: ", $pl->ob->name, " from ", $pl->ns->host;
88 root 1.1 },
89     on_death => sub {
90     my ($pl) = @_;
91 root 1.22
92 root 1.26 my $msg = $pl->expand_cfpod ($pl->ob->name . " was killed by " . $pl->killer_name . ".");
93     ext::irc::do_notice $msg;
94 root 1.1
95 root 1.14 ++$pl->ob->{stats_death}{$pl->killer_name};
96    
97 root 1.19 $pl->ob->kv_set (schmorplog_death_count =>
98     1 + $pl->ob->kv_get ("schmorplog_death_count"));
99 root 1.22
100     $_->send_msg ("" => $msg, cf::NDI_VERBATIM)
101     for cf::player::list;
102 root 1.1 },
103     on_load => sub {
104     my ($pl, $path) = @_;
105 root 1.19 $pl->ob->kv_set (schmorplog_last_load => time);
106 root 1.1 },
107     on_save => sub {
108     my ($pl, $path) = @_;
109 root 1.19 $pl->ob->kv_set (schmorplog_last_save => time);
110 root 1.1 },
111 root 1.3 );
112 root 1.1
113 root 1.17 cf::register_script_function "statistician::talk" => sub {
114     my ($who, $msg, $npc) = @_;
115    
116     my ($cmd, $args) = split /\s+/, $msg, 2;
117    
118     $args ||= $who->name;
119    
120     if ($cmd eq "deaths") {
121     cf::async {
122     my $pl = cf::player::find $args
123     or return $who->reply ($npc, "I don't know any person named '$args'.");
124    
125     my $s = $pl->ob->{stats_death}
126     or return $who->reply ($npc, "$args didn't die even once.");
127    
128 root 1.23 my $rep = "$args died a total of " . $pl->ob->kv_get ("schmorplog_death_count") . " times, among them:\n\n";
129 root 1.17
130     for (sort { $s->{$b} <=> $s->{$a} } keys %$s) {
131 root 1.23 $rep .= sprintf " C<%4d> time(s) due to %s.\n", $s->{$_}, $_;
132 root 1.17 }
133    
134     $who->reply ($npc, $rep);
135     };
136     } elsif ($cmd eq "kills") {
137     cf::async {
138     my $pl = cf::player::find $args
139     or return $who->reply ($npc, "I don't know any person named '$args'.");
140    
141     my $s = $pl->ob->{stats_kill}
142     or return $who->reply ($npc, "I don't know of I<anything> that $args has killed so far.");
143    
144 root 1.23 my $rep = sprintf "Here is a list of all the kills I know about:\n\n";
145     for (sort { $s->{$b} <=> $s->{$a} } keys %$s) {
146     $rep .= sprintf " C<%6s> %s\n", $s->{$_}, $_;
147 root 1.17 }
148    
149     $who->reply ($npc, $rep);
150     };
151     } elsif ($cmd eq "hi") {
152     $who->reply ($npc, "Hello!\n\n"
153     . "I am a statistician, I keep statistics about all people here.\n\n"
154 root 1.23 . " - To know how often somebody died, ask C<deaths> I<playername>\n"
155     . " - To know how many kills somebody scored, ask C<kills> I<playername>");
156 root 1.17 } else {
157     $who->reply ($npc, "No idea what you want of me, how about saying 'hi' first?");
158     }
159    
160     $cmd = lc $cmd;
161     };
162    
163 root 1.21 # log "crash" messages, i.e. client exit reasons
164     cf::register_exticmd clientlog => sub {
165     my ($ns, $msg) = @_;
166    
167     my $name = $ns->pl && $ns->pl->ob ? $ns->pl->ob->name : "<unknown>";
168    
169     $msg =~ y/\x0a\x20-\x7f//cd;
170     $msg =~ s/\s+$//;
171    
172 root 1.28 cf::error sprintf "clientlog [%s/%s]: %s\n", $ns->host, $name, $msg;
173 root 1.21
174     ()
175     };
176    
177 root 1.26 # log max playercount every minute
178     #############################################################################
179    
180     our $STATSDIR = "$LOCALDIR/maxplayers";
181    
182     mkdir $STATSDIR;
183    
184     our $WRITE_MAXPLAYERS = EV::periodic 0, 60, undef, sub {
185     my $now = AE::now;
186     my $cnt = scalar keys %PLAYERSEEN;
187    
188     %PLAYERSEEN = map +($_->ob->name => undef), grep $_->ns, cf::player::list;
189    
190     my @time = gmtime $now;
191    
192     my $path = sprintf "%s/%04d-%02d-%02d", $STATSDIR, $time[5] + 1900, $time[4] + 1, $time[3];
193     my $offs = $time [2] * 60 + $time [1];
194    
195     $cnt++;
196     $cnt = 254 if $cnt > 254;
197     $cnt = chr $cnt;
198    
199     IO::AIO::aio_open $path, O_WRONLY | O_CREAT, 0666, sub {
200     my $fh = shift
201     or return;
202    
203 root 1.27 # the truncate is 1440 extra syscalls, but saves 1439
204     # slow metadata updates.
205     IO::AIO::aio_truncate $fh, 1440, sub {
206     IO::AIO::aio_write $fh, $offs, 1, $cnt, 0, sub {
207     IO::AIO::aio_close $fh;
208     };
209 root 1.26 };
210     };
211     };
212    
213