diff --git a/minecraft/images/playtime.gif b/minecraft/images/playtime.gif new file mode 100644 index 000000000..2ca3de493 Binary files /dev/null and b/minecraft/images/playtime.gif differ diff --git a/minecraft/lang/en b/minecraft/lang/en index 3744d8d7b..38622eb67 100644 --- a/minecraft/lang/en +++ b/minecraft/lang/en @@ -302,3 +302,23 @@ monitor_notype=Unknown monitor type! monitor_newversion=New version is available monitor_nojar=JAR file $1 does not exist monitor_checklog=Check server response to commands? + +playtime_title=Daily Play Time +playtime_user=Username +playtime_time=Time online +playtime_now=Status +playtime_none=No players were connected for this day. +playtime_on=Online +playtime_off=Off +playtime_header=Daily play limit settings +playtime_enabled=Limits enabled? +playtime_max=Maximum time per day +playtime_unlimited=Unlimited +playtime_mins=minutes +playtime_days=Days to enforce on +playtime_users=Apply to users +playtime_sel=Listed +playtime_all=All users +playtime_ips=Apply to connections from +playtime_sel2=Listed IPs and networks +playtime_all2=All addresses diff --git a/minecraft/list_playtime.cgi b/minecraft/list_playtime.cgi new file mode 100644 index 000000000..ead98f04f --- /dev/null +++ b/minecraft/list_playtime.cgi @@ -0,0 +1,69 @@ +#!/usr/local/bin/perl +# Show per-player time over the last day + +use strict; +use warnings; +require './minecraft-lib.pl'; +our (%in, %text, %config); + +&ui_print_header(undef, $text{'playtime_title'}, ""); + +my $playtime = &get_current_day_usage(); +my @conns = &list_connected_players(); + +if (keys %$playtime) { + print &ui_columns_start([ $text{'playtime_user'}, + $text{'playtime_time'}, + $text{'playtime_now'} ]); + foreach my $u (sort { $playtime->{$b} <=> $playtime->{$a} } + keys %$playtime) { + print &ui_columns_row([ + "". + &html_escape($u)."", + &nice_seconds($playtime->{$u}), + &indexof($u, @conns) >= 0 ? + "$text{'playtime_on'}" : + $text{'playtime_off'}, + ]); + } + print &ui_columns_end(); + } +else { + print "$text{'playtime_none'}

\n"; + } + +print &ui_hr(); + +# Show form for setting up play time limits +print &ui_form_start("save_playtime.cgi"); +print &ui_table_start($text{'playtime_header'}, undef, 2); + +# Cron job enabled? +print &ui_table_row($text{'playtime_enabled'}, + &ui_yesno_radio("enabled", $config{'playtime_enabled'})); + +# Max time per day +print &ui_table_row($text{'playtime_max'}, + &ui_opt_textbox("max", $config{'playtime_max'}, 6, + $text{'playtime_unlimited'})." ".$text{'playtime_mins'}); + +# Apply to users +print &ui_table_row($text{'playtime_users'}, + &ui_opt_textbox("users", $config{'playtime_users'}, 40, + $text{'playtime_all'}, $text{'playtime_sel'})); + +# Days of the week +my @days = split(/\s+/, $config{'playtime_days'}); +@days = (0 .. 6) if (!@days); +print &ui_table_row($text{'playtime_days'}, + join(" ", map { &ui_checkbox("days", $_, $text{'day_'.$_}, + &indexof($_, @days) >= 0) } (0 .. 6))); + +# For connections from IPs +print &ui_table_row($text{'playtime_ips'}, + &ui_opt_textbox("ips", $config{'playtime_ips'}, 40, + $text{'playtime_all2'}, $text{'playtime_sel2'})); + +print &ui_form_end([ [ undef, $text{'save'} ] ]); + +&ui_print_footer("", $text{'index_return'}); diff --git a/minecraft/minecraft-lib.pl b/minecraft/minecraft-lib.pl index 31ff90a6d..703c60f07 100644 --- a/minecraft/minecraft-lib.pl +++ b/minecraft/minecraft-lib.pl @@ -755,4 +755,82 @@ if (time() - $config{'last_check'} > 6*60*60) { } } +# get_current_day_usage() +# Returns a hash ref from usernames to usage over the last day +sub get_current_day_usage +{ +my $logfile = $config{'minecraft_dir'}."/server.log"; + +# Seek back till we find a day line from a previous day +my @st = stat($logfile); +return { } if (!@st); +my $pos = $st[7]; +open(LOGFILE, $logfile); +my @tm = localtime(time()); +my $wantday = sprintf("%4.4d-%2.2d-%2.2d", $tm[5]+1900, $tm[4]+1, $tm[3]); +while(1) { + $pos -= 4096; + $pos = 0 if ($pos < 0); + seek(LOGFILE, $pos, 0); + last if ($pos == 0); + my $dummy = ; # Skip partial line + my $line = ; + $line =~ /^((\d+)\-(\d+)\-(\d+))/ || next; + if ($1 ne $wantday) { + # Found a line for another day + last; + } + } + +# Read forwards, looking for logins and logouts for today +my %rv; +my %lastlogin; +while(my $line = ) { + $line =~ /^((\d+)\-(\d+)\-(\d+))\s+(\d+):(\d+):(\d+)/ || next; + $1 eq $wantday || next; + my $secs = $5*60*60 + $6*60 + $7; + if ($line =~ /\s(\S+)\s*\[[^\]]+\]\s+logged\s+in\s/) { + # Login by a user + $lastlogin{$1} = $secs; + } + elsif ($line =~ /\s(\S+)(\s*\[[^\]]+\])?\s+lost\s+connection/) { + # Logout .. count time + if (defined($lastlogin{$1})) { + # Add time from last login + $rv{$1} += $secs - $lastlogin{$1}; + delete($lastlogin{$1}); + } + } + } +close(LOGFILE); + +# Add any active sessions +my $now = $tm[2]*60*60 + $tm[1]*60 + $tm[0]; +foreach my $u (keys %lastlogin) { + $rv{$u} += $now - $lastlogin{$u}; + } + +return \%rv; +} + +# nice_seconds(secs) +# Converts a number of seconds into HH:MM format +sub nice_seconds +{ +my ($time) = @_; +my $days = int($time / (24*60*60)); +my $hours = int($time / (60*60)) % 24; +my $mins = sprintf("%d", int($time / 60) % 60); +my $secs = sprintf("%d", int($time) % 60); +if ($days) { + return "$days days, $hours hours, $mins mins"; + } +elsif ($hours) { + return "$hours hours, $mins mins"; + } +else { + return "$mins mins"; + } +} + 1;