1125 lines
26 KiB
Perl
1125 lines
26 KiB
Perl
|
package HLstats_Player;
|
||
|
# HLstatsX Community Edition - Real-time player and clan rankings and statistics
|
||
|
# Copyleft (L) 2008-20XX Nicholas Hastings (nshastings@gmail.com)
|
||
|
# http://www.hlxcommunity.com
|
||
|
#
|
||
|
# HLstatsX Community Edition is a continuation of
|
||
|
# ELstatsNEO - Real-time player and clan rankings and statistics
|
||
|
# Copyleft (L) 2008-20XX Malte Bayer (steam@neo-soft.org)
|
||
|
# http://ovrsized.neo-soft.org/
|
||
|
#
|
||
|
# ELstatsNEO is an very improved & enhanced - so called Ultra-Humongus Edition of HLstatsX
|
||
|
# HLstatsX - Real-time player and clan rankings and statistics for Half-Life 2
|
||
|
# http://www.hlstatsx.com/
|
||
|
# Copyright (C) 2005-2007 Tobias Oetzel (Tobi@hlstatsx.com)
|
||
|
#
|
||
|
# HLstatsX is an enhanced version of HLstats made by Simon Garner
|
||
|
# HLstats - Real-time player and clan rankings and statistics for Half-Life
|
||
|
# http://sourceforge.net/projects/hlstats/
|
||
|
# Copyright (C) 2001 Simon Garner
|
||
|
#
|
||
|
# This program is free software; you can redistribute it and/or
|
||
|
# modify it under the terms of the GNU General Public License
|
||
|
# as published by the Free Software Foundation; either version 2
|
||
|
# of the License, or (at your option) any later version.
|
||
|
#
|
||
|
# This program is distributed in the hope that it will be useful,
|
||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
|
# GNU General Public License for more details.
|
||
|
#
|
||
|
# You should have received a copy of the GNU General Public License
|
||
|
# along with this program; if not, write to the Free Software
|
||
|
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||
|
#
|
||
|
# For support and installation notes visit http://www.hlxcommunity.com
|
||
|
|
||
|
#
|
||
|
# Constructor
|
||
|
#
|
||
|
|
||
|
use Encode;
|
||
|
|
||
|
do "$::opt_libdir/HLstats_GameConstants.plib";
|
||
|
|
||
|
sub new
|
||
|
{
|
||
|
my $class_name = shift;
|
||
|
my %params = @_;
|
||
|
|
||
|
my $self = {};
|
||
|
bless($self, $class_name);
|
||
|
|
||
|
# Initialise Properties
|
||
|
$self->{userid} = 0;
|
||
|
$self->{server} = "";
|
||
|
$self->{server_id} = 1;
|
||
|
$self->{name} = "";
|
||
|
$self->{uniqueid} = "";
|
||
|
$self->{plain_uniqueid} = "";
|
||
|
$self->{address} = "";
|
||
|
$self->{cli_port} = "";
|
||
|
$self->{ping} = 0;
|
||
|
$self->{connect_time} = time();
|
||
|
$self->{last_update} = 0;
|
||
|
$self->{last_update_skill} = 0;
|
||
|
$self->{day_skill_change} = 0;
|
||
|
|
||
|
$self->{city} = "";
|
||
|
$self->{state} = "";
|
||
|
$self->{country} = "";
|
||
|
$self->{flag} = "";
|
||
|
$self->{lat} = undef;
|
||
|
$self->{lng} = undef;
|
||
|
|
||
|
$self->{playerid} = 0;
|
||
|
$self->{clan} = 0;
|
||
|
$self->{kills} = 0;
|
||
|
$self->{total_kills} = 0;
|
||
|
$self->{deaths} = 0;
|
||
|
$self->{suicides} = 0;
|
||
|
$self->{skill} = 1000;
|
||
|
$self->{game} = "";
|
||
|
$self->{team} = "";
|
||
|
$self->{role} = "";
|
||
|
$self->{timestamp} = 0;
|
||
|
$self->{headshots} = 0;
|
||
|
$self->{shots} = 0;
|
||
|
$self->{hits} = 0;
|
||
|
$self->{teamkills} = 0;
|
||
|
$self->{kill_streak} = 0;
|
||
|
$self->{death_streak} = 0;
|
||
|
|
||
|
$self->{auto_command} = "";
|
||
|
$self->{auto_type} = "";
|
||
|
$self->{auto_time} = 0;
|
||
|
$self->{auto_time_count} = 0;
|
||
|
|
||
|
$self->{session_skill} = 0;
|
||
|
$self->{session_kills} = 0;
|
||
|
$self->{session_deaths} = 0;
|
||
|
$self->{session_suicides} = 0;
|
||
|
$self->{session_headshots} = 0;
|
||
|
$self->{session_shots} = 0;
|
||
|
$self->{session_hits} = 0;
|
||
|
$self->{session_start_pos} = -1;
|
||
|
|
||
|
$self->{map_kills} = 0;
|
||
|
$self->{map_deaths} = 0;
|
||
|
$self->{map_suicides} = 0;
|
||
|
$self->{map_headshots} = 0;
|
||
|
$self->{map_shots} = 0;
|
||
|
$self->{map_hits} = 0;
|
||
|
$self->{is_dead} = 0;
|
||
|
$self->{has_bomb} = 0;
|
||
|
|
||
|
$self->{is_banned} = 0;
|
||
|
$self->{is_bot} = 0;
|
||
|
|
||
|
$self->{display_events} = 1;
|
||
|
$self->{display_chat} = 1;
|
||
|
$self->{kills_per_life} = 0;
|
||
|
$self->{last_history_day} = "";
|
||
|
$self->{last_death_weapon} = 0;
|
||
|
$self->{last_sg_build} = 0;
|
||
|
$self->{last_disp_build} = 0;
|
||
|
$self->{last_entrance_build} = 0;
|
||
|
$self->{last_exit_build} = 0;
|
||
|
$self->{last_team_change} = "";
|
||
|
$self->{deaths_in_a_row} = 0;
|
||
|
$self->{trackable} = 0;
|
||
|
$self->{needsupdate} = 0;
|
||
|
|
||
|
|
||
|
# Set Property Values
|
||
|
|
||
|
die("HLstats_Player->new(): must specify player's uniqueid\n")
|
||
|
unless (defined($params{uniqueid}));
|
||
|
|
||
|
|
||
|
while (my($key, $value) = each(%params))
|
||
|
{
|
||
|
if ($key ne "name" && $key ne "uniqueid")
|
||
|
{
|
||
|
$self->set($key, $value);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
$self->updateTrackable();
|
||
|
$self->{plain_uniqueid} = $params{plain_uniqueid};
|
||
|
$self->setUniqueId($params{uniqueid});
|
||
|
if ($::g_stdin == 0 && $self->{userid} > 0) {
|
||
|
$self->insertPlayerLivestats();
|
||
|
}
|
||
|
$self->setName($params{name});
|
||
|
$self->getAddress();
|
||
|
$self->flushDB();
|
||
|
|
||
|
|
||
|
|
||
|
&::printNotice("Created new player object " . $self->getInfoString());
|
||
|
return $self;
|
||
|
}
|
||
|
|
||
|
sub playerCleanup
|
||
|
{
|
||
|
my ($self) = @_;
|
||
|
$self->flushDB();
|
||
|
$self->deleteLivestats();
|
||
|
}
|
||
|
|
||
|
|
||
|
#
|
||
|
# Set property 'key' to 'value'
|
||
|
#
|
||
|
|
||
|
sub set
|
||
|
{
|
||
|
my ($self, $key, $value, $no_updatetime) = @_;
|
||
|
|
||
|
if (defined($self->{$key}))
|
||
|
{
|
||
|
if ($no_updatetime == 0) {
|
||
|
$self->{timestamp} = $::ev_daemontime;
|
||
|
}
|
||
|
|
||
|
if ($self->{$key} eq $value)
|
||
|
{
|
||
|
if ($::g_debug > 2)
|
||
|
{
|
||
|
&::printNotice("Hlstats_Player->set ignored: Value of \"$key\" is already \"$value\"");
|
||
|
}
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
if ($key eq "uniqueid")
|
||
|
{
|
||
|
return $self->setUniqueId($value);
|
||
|
}
|
||
|
elsif ($key eq "name")
|
||
|
{
|
||
|
return $self->setName($value);
|
||
|
}
|
||
|
elsif ($key eq "skill" && $self->{userid} < 1)
|
||
|
{
|
||
|
return $self->{skill};
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
$self->{$key} = $value;
|
||
|
return 1;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
warn("HLstats_Player->set: \"$key\" is not a valid property name\n");
|
||
|
return 0;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
#
|
||
|
# Increment (or decrement) the value of 'key' by 'amount' (or 1 by default)
|
||
|
#
|
||
|
|
||
|
sub increment
|
||
|
{
|
||
|
my ($self, $key, $amount, $no_updatetime) = @_;
|
||
|
|
||
|
if ($key eq "skill" && $self->{userid} < 1) {
|
||
|
return $self->{skill};
|
||
|
}
|
||
|
|
||
|
$amount = 1 if (!defined($amount));
|
||
|
|
||
|
if ($amount != 0) {
|
||
|
my $value = $self->{$key};
|
||
|
$self->set($key, $value + $amount, $no_updatetime);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
sub check_history
|
||
|
{
|
||
|
my ($self) = @_;
|
||
|
|
||
|
#my ($sec,$min,$hour,$mday,$mon,$year) = localtime(time());
|
||
|
my ($sec,$min,$hour,$mday,$mon,$year) = localtime($::ev_unixtime);
|
||
|
my $date = sprintf("%04d-%02d-%02d", $year+1900, $mon+1, $mday, $hour, $min, $sec);
|
||
|
my $srv_addr = $self->{server};
|
||
|
my $is_bot = 0;
|
||
|
my $playerId = $self->{playerid};
|
||
|
|
||
|
if ($self->{is_bot} || $self->{userid} < 0) {
|
||
|
$is_bot = 1;
|
||
|
}
|
||
|
if (($playerId > 0) && ($::g_stdin == 0 || $::g_timestamp > 0))
|
||
|
{
|
||
|
if (($is_bot == 0) || (($is_bot == 1) && ($::g_servers{$srv_addr}->{ignore_bots} == 0))) {
|
||
|
$self->{last_history_day} = sprintf("%02d", $mday);
|
||
|
my $query = "
|
||
|
SELECT
|
||
|
skill_change
|
||
|
FROM
|
||
|
hlstats_Players_History
|
||
|
WHERE
|
||
|
playerId=" . $playerId . "
|
||
|
AND eventTime='".$date."'
|
||
|
AND game='".&::quoteSQL($::g_servers{$srv_addr}->{game})."'
|
||
|
";
|
||
|
my $result = &::doQuery($query);
|
||
|
|
||
|
if ($result->rows < 1)
|
||
|
{
|
||
|
my $query = "
|
||
|
INSERT INTO
|
||
|
hlstats_Players_History
|
||
|
(
|
||
|
playerId,
|
||
|
eventTime,
|
||
|
game
|
||
|
)
|
||
|
VALUES
|
||
|
(
|
||
|
$playerId,
|
||
|
'$date',
|
||
|
'" . &::quoteSQL($::g_servers{$srv_addr}->{game}) . "'
|
||
|
)
|
||
|
";
|
||
|
&::execNonQuery($query);
|
||
|
$self->{day_skill_change} = 0;
|
||
|
} else {
|
||
|
($self->{day_skill_change}) = $result->fetchrow_array;
|
||
|
}
|
||
|
$result->finish;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
#
|
||
|
# Set player's uniqueid
|
||
|
#
|
||
|
|
||
|
sub setUniqueId
|
||
|
{
|
||
|
my ($self, $uniqueid) = @_;
|
||
|
my $tempPlayerId = &::getPlayerId($uniqueid);
|
||
|
|
||
|
if ($tempPlayerId > 0)
|
||
|
{
|
||
|
$self->{playerid} = $tempPlayerId;
|
||
|
# An existing player. Get their skill rating.
|
||
|
my $query = "
|
||
|
SELECT
|
||
|
skill, kills, displayEvents, flag
|
||
|
FROM
|
||
|
hlstats_Players
|
||
|
WHERE
|
||
|
playerId=$tempPlayerId
|
||
|
";
|
||
|
my $result = &::doQuery($query);
|
||
|
if ($result->rows > 0) {
|
||
|
($self->{skill}, $self->{total_kills}, $self->{display_events},$self->{flag}) = $result->fetchrow_array;
|
||
|
} else {
|
||
|
# Have record in hlstats_PlayerUniqueIds but not in hlstats_Players
|
||
|
$self->insertPlayer($tempPlayerId);
|
||
|
}
|
||
|
$self->{session_start_pos} = $self->getRank();
|
||
|
$result->finish;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
# This is a new player. Create a new record for them in the Players
|
||
|
# table.
|
||
|
$self->insertPlayer();
|
||
|
|
||
|
$query = "
|
||
|
INSERT INTO
|
||
|
hlstats_PlayerUniqueIds
|
||
|
(
|
||
|
playerId,
|
||
|
uniqueId,
|
||
|
game
|
||
|
)
|
||
|
VALUES
|
||
|
(
|
||
|
".$self->{playerid}.",
|
||
|
'" . &::quoteSQL($uniqueid) . "',
|
||
|
'" . &::quoteSQL($::g_servers{$self->{server}}->{game}) . "'
|
||
|
)
|
||
|
";
|
||
|
&::execNonQuery($query);
|
||
|
}
|
||
|
|
||
|
$self->{uniqueid} = $uniqueid;
|
||
|
$self->check_history();
|
||
|
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
|
||
|
#
|
||
|
# Inserts new player
|
||
|
#
|
||
|
|
||
|
sub insertPlayer
|
||
|
{
|
||
|
my ($self, $playerid) = @_;
|
||
|
|
||
|
my $hideval = 0;
|
||
|
my $playeridins = "";
|
||
|
my $playeridval = "";
|
||
|
my $srv_addr = $self->{server};
|
||
|
|
||
|
if ($::g_servers{$srv_addr}->{play_game} == L4D() && $self->{userid} < 0) {
|
||
|
$hideval = 1;
|
||
|
}
|
||
|
if ($playerid) {
|
||
|
my $query = "
|
||
|
INSERT INTO
|
||
|
hlstats_Players
|
||
|
(
|
||
|
lastName,
|
||
|
clan,
|
||
|
game,
|
||
|
displayEvents,
|
||
|
createdate,
|
||
|
hideranking,
|
||
|
playerId
|
||
|
)
|
||
|
VALUES
|
||
|
(
|
||
|
?,
|
||
|
?,
|
||
|
?,
|
||
|
?,
|
||
|
UNIX_TIMESTAMP(),
|
||
|
?,
|
||
|
?
|
||
|
)
|
||
|
";
|
||
|
my @vals = ($self->{name}, $self->{clan}, $::g_servers{$srv_addr}->{game}, $self->{display_events}, $hideval, $playerid);
|
||
|
&::execCached("player_insert_playerid", $query, @vals);
|
||
|
return $playerid;
|
||
|
}
|
||
|
|
||
|
my $query = "
|
||
|
INSERT INTO
|
||
|
hlstats_Players
|
||
|
(
|
||
|
lastName,
|
||
|
clan,
|
||
|
game,
|
||
|
displayEvents,
|
||
|
createdate,
|
||
|
hideranking
|
||
|
)
|
||
|
VALUES
|
||
|
(
|
||
|
?,
|
||
|
?,
|
||
|
?,
|
||
|
?,
|
||
|
UNIX_TIMESTAMP(),
|
||
|
?
|
||
|
)
|
||
|
";
|
||
|
my @vals = ($self->{name}, $self->{clan}, $::g_servers{$srv_addr}->{game}, $self->{display_events}, $hideval);
|
||
|
&::execCached("player_insert", $query, @vals);
|
||
|
|
||
|
$self->{playerid} = $::db_conn->{'mysql_insertid'};
|
||
|
}
|
||
|
|
||
|
#
|
||
|
# Insert initial live stats
|
||
|
#
|
||
|
sub insertPlayerLivestats
|
||
|
{
|
||
|
my ($self) = @_;
|
||
|
my $query = "
|
||
|
REPLACE INTO
|
||
|
hlstats_Livestats
|
||
|
(
|
||
|
player_id,
|
||
|
server_id,
|
||
|
cli_address,
|
||
|
steam_id,
|
||
|
name,
|
||
|
team,
|
||
|
ping,
|
||
|
connected,
|
||
|
skill,
|
||
|
cli_flag
|
||
|
)
|
||
|
VALUES
|
||
|
(
|
||
|
?,?,?,?,?,?,?,?,?,?
|
||
|
)
|
||
|
";
|
||
|
my @vals = ($self->{playerid}, $self->{server_id}, $self->{address}, $self->{plain_uniqueid},
|
||
|
$self->{name}, $self->{team}, $self->{ping}, $self->{connect_time}, $self->{skill}, $self->{flag});
|
||
|
&::execCached("player_livestats_insert", $query, @vals);
|
||
|
}
|
||
|
|
||
|
|
||
|
#
|
||
|
# Set player's name
|
||
|
#
|
||
|
|
||
|
sub setName
|
||
|
{
|
||
|
my ($self, $name) = @_;
|
||
|
|
||
|
my $oldname = $self->{name};
|
||
|
|
||
|
if ($oldname eq $name)
|
||
|
{
|
||
|
return 2;
|
||
|
}
|
||
|
|
||
|
if ($oldname)
|
||
|
{
|
||
|
$self->updateDB();
|
||
|
}
|
||
|
|
||
|
$self->{name} = $name;
|
||
|
|
||
|
my $is_bot = $self->{is_bot};
|
||
|
my $server_address = $self->{server};
|
||
|
if (($is_bot == 1) && ($::g_servers{$server_address}->{ignore_bots} == 1)) {
|
||
|
$self->{clan} = "";
|
||
|
} else {
|
||
|
$self->{clan} = &::getClanId($name);
|
||
|
}
|
||
|
|
||
|
my $playerid = $self->{playerid};
|
||
|
|
||
|
if ($playerid)
|
||
|
{
|
||
|
my $query = "
|
||
|
SELECT
|
||
|
playerId
|
||
|
FROM
|
||
|
hlstats_PlayerNames
|
||
|
WHERE
|
||
|
playerId = $playerid
|
||
|
AND name ='" . &::quoteSQL($self->{name}) . "'
|
||
|
";
|
||
|
my $result = &::doQuery($query);
|
||
|
|
||
|
if ($result->rows < 1)
|
||
|
{
|
||
|
my $query = "
|
||
|
REPLACE INTO
|
||
|
hlstats_PlayerNames
|
||
|
(
|
||
|
playerId,
|
||
|
name,
|
||
|
lastuse,
|
||
|
numuses
|
||
|
)
|
||
|
VALUES
|
||
|
(
|
||
|
$playerid,
|
||
|
'" . &::quoteSQL($self->{name}) . "',
|
||
|
FROM_UNIXTIME(" . $::ev_unixtime . "),
|
||
|
1
|
||
|
)
|
||
|
";
|
||
|
&::execNonQuery($query);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
my $query = "
|
||
|
UPDATE
|
||
|
hlstats_PlayerNames
|
||
|
SET
|
||
|
lastuse=FROM_UNIXTIME(" . $::ev_unixtime . "),
|
||
|
numuses=numuses+1
|
||
|
WHERE
|
||
|
playerId = $playerid
|
||
|
AND name='" . &::quoteSQL($self->{name}) . "'
|
||
|
";
|
||
|
&::execNonQuery($query);
|
||
|
}
|
||
|
|
||
|
$result->finish;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
&::error("HLstats_Player->setName(): No playerid");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
#
|
||
|
# Update player information in database
|
||
|
#
|
||
|
|
||
|
sub flushDB
|
||
|
{
|
||
|
my ($self, $leaveLastUse, $callref) = @_;
|
||
|
|
||
|
my $playerid = $self->{playerid};
|
||
|
my $srv_addr = $self->{server};
|
||
|
my $serverid = $self->{server_id};
|
||
|
my $name = $self->{name};
|
||
|
my $clan = $self->{clan};
|
||
|
my $kills = $self->{kills};
|
||
|
my $deaths = $self->{deaths};
|
||
|
my $suicides = $self->{suicides};
|
||
|
my $skill = $self->{skill};
|
||
|
if ($skill < 0) {$skill = 0;}
|
||
|
my $headshots = $self->{headshots};
|
||
|
my $shots = $self->{shots};
|
||
|
my $hits = $self->{hits};
|
||
|
my $teamkills = $self->{teamkills};
|
||
|
|
||
|
my $team = $self->{team};
|
||
|
my $map_kills = $self->{map_kills};
|
||
|
my $map_deaths = $self->{map_deaths};
|
||
|
my $map_suicides = $self->{map_suicides};
|
||
|
my $map_headshots = $self->{map_headshots};
|
||
|
my $map_shots = $self->{map_shots};
|
||
|
my $map_hits = $self->{map_hits};
|
||
|
my $steamid = $self->{plain_uniqueid};
|
||
|
|
||
|
my $is_dead = $self->{is_dead};
|
||
|
my $has_bomb = $self->{has_bomb};
|
||
|
my $ping = $self->{ping};
|
||
|
my $connected = $self->{connect_time};
|
||
|
my $skill_change = $self->{session_skill};
|
||
|
|
||
|
my $death_streak = $self->{death_streak};
|
||
|
my $kill_streak = $self->{kill_streak};
|
||
|
|
||
|
my $add_connect_time = 0;
|
||
|
if (($::g_stdin == 0) && ($self->{last_update} > 0)) {
|
||
|
$add_connect_time = time() - $self->{last_update};
|
||
|
} elsif (($::g_stdin == 1) && ($self->{last_update} > 0)) {
|
||
|
$add_connect_time = $::ev_unixtime - $self->{last_update};
|
||
|
}
|
||
|
if (($::g_stdin == 1) && ($add_connect_time > 600)) {
|
||
|
$self->{last_update} = $::ev_unixtime;
|
||
|
$add_connect_time = 0;
|
||
|
}
|
||
|
|
||
|
my $address = $self->{address};
|
||
|
|
||
|
unless ($playerid)
|
||
|
{
|
||
|
warn ("Player->Update() with no playerid set!\n");
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
if (($::g_stdin == 0) && ($self->{session_start_pos} == 0)) {
|
||
|
$self->{session_start_pos} = $self->getRank();
|
||
|
}
|
||
|
|
||
|
# TAG - review this, should probably be localtime($ev_unixtime);
|
||
|
# and why no Players_History if stdin?
|
||
|
#my ($sec,$min,$hour,$mday,$mon,$year) = localtime(time());
|
||
|
my ($sec,$min,$hour,$mday,$mon,$year) = localtime($::ev_unixtime);
|
||
|
my $date = sprintf("%04d-%02d-%02d", $year+1900, $mon+1, $mday, $hour, $min, $sec);
|
||
|
|
||
|
if ($::g_stdin == 0 || $::g_timestamp > 0) {
|
||
|
my $last_history_day = $self->{last_history_day};
|
||
|
if ($last_history_day ne sprintf("%02d", $mday)) {
|
||
|
my $query = "
|
||
|
INSERT IGNORE INTO
|
||
|
hlstats_Players_History
|
||
|
(
|
||
|
playerId,
|
||
|
eventTime,
|
||
|
game
|
||
|
) VALUES (
|
||
|
?,
|
||
|
?,
|
||
|
?
|
||
|
)
|
||
|
";
|
||
|
my @vals = ($playerid, $date, $::g_servers{$srv_addr}->{game});
|
||
|
&::execCached("player_flushdb_history_1", $query, @vals);
|
||
|
$self->{day_skill_change} = 0;
|
||
|
$self->{last_history_day} = sprintf("%02d", $mday);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
my $add_history_skill = 0;
|
||
|
if ($self->{last_update_skill} > 0) {
|
||
|
$add_history_skill = $skill - $self->{last_update_skill};
|
||
|
}
|
||
|
$self->{day_skill_change} += $add_history_skill;
|
||
|
my $last_skill_change = $self->{day_skill_change};
|
||
|
|
||
|
|
||
|
my $is_bot = $self->{is_bot};
|
||
|
my $server_address = $self->{server};
|
||
|
if (($is_bot == 1) && ($::g_servers{$server_address}->{ignore_bots} == 1)) {
|
||
|
# Update player details
|
||
|
my $query = "
|
||
|
UPDATE
|
||
|
hlstats_Players
|
||
|
SET
|
||
|
connection_time = connection_time + ?,
|
||
|
lastName=?,
|
||
|
clan=0,
|
||
|
kills=kills + ?,
|
||
|
deaths=deaths + ?,
|
||
|
suicides=suicides + ?,
|
||
|
skill=0,
|
||
|
headshots=headshots + ?,
|
||
|
shots=shots + ?,
|
||
|
hits=hits + ?,
|
||
|
teamkills=teamkills + ?,
|
||
|
last_event=?,
|
||
|
hideranking=1
|
||
|
WHERE
|
||
|
playerId=?
|
||
|
";
|
||
|
my @vals = ($add_connect_time, $name, $kills, $deaths, $suicides, $headshots,
|
||
|
$shots, $hits, $teamkills, $::ev_unixtime, $playerid);
|
||
|
&::execCached("player_flushdb_player_1", $query, @vals);
|
||
|
} else {
|
||
|
# Update player details
|
||
|
my $query = "
|
||
|
UPDATE
|
||
|
hlstats_Players
|
||
|
SET
|
||
|
connection_time = connection_time + ?,
|
||
|
lastName=?,
|
||
|
clan=?,
|
||
|
kills=kills + ?,
|
||
|
deaths=deaths + ?,
|
||
|
suicides=suicides + ?,
|
||
|
skill=?,
|
||
|
headshots=headshots + ?,
|
||
|
shots=shots + ?,
|
||
|
hits=hits + ?,
|
||
|
teamkills=teamkills + ?,
|
||
|
last_event=?,
|
||
|
last_skill_change=?,
|
||
|
death_streak=IF(?>death_streak,?,death_streak),
|
||
|
kill_streak=IF(?>kill_streak,?,kill_streak),
|
||
|
hideranking=IF(hideranking=3,0,hideranking),
|
||
|
activity = 100
|
||
|
WHERE
|
||
|
playerId=?
|
||
|
";
|
||
|
my @vals = ($add_connect_time, $name, $clan, $kills, $deaths, $suicides, $skill,
|
||
|
$headshots, $shots, $hits, $teamkills, $::ev_unixtime, $last_skill_change, $death_streak,
|
||
|
$death_streak, $kill_streak, $kill_streak, $playerid);
|
||
|
&::execCached("player_flushdb_player_2", $query, @vals);
|
||
|
|
||
|
if ($::g_stdin == 0 || $::g_timestamp > 0) {
|
||
|
# Update player details
|
||
|
my $query = "
|
||
|
UPDATE
|
||
|
hlstats_Players_History
|
||
|
SET
|
||
|
connection_time = connection_time + ?,
|
||
|
kills=kills + ?,
|
||
|
deaths=deaths + ?,
|
||
|
suicides=suicides + ?,
|
||
|
skill=?,
|
||
|
headshots=headshots + ?,
|
||
|
shots=shots + ?,
|
||
|
hits=hits + ?,
|
||
|
teamkills=teamkills + ?,
|
||
|
death_streak=IF(?>death_streak,?,death_streak),
|
||
|
kill_streak=IF(?>kill_streak,?,kill_streak),
|
||
|
skill_change=skill_change + ?
|
||
|
WHERE
|
||
|
playerId=?
|
||
|
AND eventTime=?
|
||
|
AND game=?
|
||
|
";
|
||
|
my @vals = ($add_connect_time, $kills, $deaths, $suicides, $skill, $headshots,
|
||
|
$shots, $hits, $teamkills, $death_streak, $death_streak, $kill_streak,
|
||
|
$kill_streak, $add_history_skill, $playerid, $date, $::g_servers{$srv_addr}->{game});
|
||
|
&::execCached("player_flushdb_history_2", $query, @vals);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ($name)
|
||
|
{
|
||
|
# Update alias details
|
||
|
$query = "
|
||
|
UPDATE
|
||
|
hlstats_PlayerNames
|
||
|
SET
|
||
|
connection_time = connection_time + ?,
|
||
|
kills=kills + ?,
|
||
|
deaths=deaths + ?,
|
||
|
suicides=suicides + ?,
|
||
|
headshots=headshots + ?,
|
||
|
shots=shots + ?,
|
||
|
hits=hits + ?"
|
||
|
;
|
||
|
my @vals = ($add_connect_time, $kills, $deaths, $suicides, $headshots, $shots, $hits);
|
||
|
|
||
|
unless ($leaveLastUse)
|
||
|
{
|
||
|
# except on ChangeName we update the last use on a player's old name
|
||
|
|
||
|
$query .= ",
|
||
|
lastuse=FROM_UNIXTIME(?)"
|
||
|
;
|
||
|
push(@vals, $::ev_unixtime);
|
||
|
}
|
||
|
|
||
|
$query .= "
|
||
|
WHERE
|
||
|
playerId=?
|
||
|
AND name=?
|
||
|
";
|
||
|
push(@vals, $playerid);
|
||
|
push(@vals, $self->{name});
|
||
|
|
||
|
&::execCached("player_flushdb_playernames", $query, @vals);
|
||
|
}
|
||
|
|
||
|
# reset player stat properties
|
||
|
$self->set("kills", 0, 1);
|
||
|
$self->set("deaths", 0, 1);
|
||
|
$self->set("suicides", 0, 1);
|
||
|
$self->set("headshots", 0, 1);
|
||
|
$self->set("shots", 0, 1);
|
||
|
$self->set("hits", 0, 1);
|
||
|
$self->set("teamkills", 0, 1);
|
||
|
|
||
|
if (($is_bot == 1) && ($::g_servers{$server_address}->{ignore_bots} == 1)) {
|
||
|
$skill = 0;
|
||
|
$skill_change = 0;
|
||
|
}
|
||
|
|
||
|
if ($::g_stdin == 0 && $self->{userid} > 0) {
|
||
|
# Update live stats
|
||
|
my $query = "
|
||
|
UPDATE
|
||
|
hlstats_Livestats
|
||
|
SET
|
||
|
cli_address=?,
|
||
|
steam_id=?,
|
||
|
name=?,
|
||
|
team=?,
|
||
|
kills=?,
|
||
|
deaths=?,
|
||
|
suicides=?,
|
||
|
headshots=?,
|
||
|
shots=?,
|
||
|
hits=?,
|
||
|
is_dead=?,
|
||
|
has_bomb=?,
|
||
|
ping=?,
|
||
|
connected=?,
|
||
|
skill_change=?,
|
||
|
skill=?
|
||
|
WHERE
|
||
|
player_id=?
|
||
|
";
|
||
|
my @vals = ($address, $steamid, $name,
|
||
|
$team, $map_kills, $map_deaths, $map_suicides, $map_headshots, $map_shots,
|
||
|
$map_hits, $is_dead, $has_bomb, $ping, $connected, $skill_change, $skill, $playerid);
|
||
|
&::execCached("player_flushdb_livestats", $query, @vals);
|
||
|
}
|
||
|
|
||
|
if ($::g_stdin == 0) {
|
||
|
$self->{last_update} = time();
|
||
|
} elsif ($::g_stdin == 1) {
|
||
|
$self->{last_update} = $::ev_unixtime;
|
||
|
}
|
||
|
|
||
|
$self->{last_update_skill} = $skill;
|
||
|
|
||
|
$self->{needsupdate} = 0;
|
||
|
|
||
|
&::printNotice("Updated player object " . $self->getInfoString());
|
||
|
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
|
||
|
#
|
||
|
# Update player timestamp (time of last event for player - used to detect idle
|
||
|
# players)
|
||
|
#
|
||
|
|
||
|
sub updateTimestamp
|
||
|
{
|
||
|
my ($self, $timestamp) = @_;
|
||
|
$timestamp = $::ev_unixtime
|
||
|
unless ($timestamp);
|
||
|
$self->{timestamp} = $::ev_daemontime;
|
||
|
return $timestamp;
|
||
|
}
|
||
|
|
||
|
sub updateDB
|
||
|
{
|
||
|
my ($self) = @_;
|
||
|
$self->{needsupdate} = 1;
|
||
|
|
||
|
}
|
||
|
|
||
|
sub deleteLivestats
|
||
|
{
|
||
|
my ($self) = @_;
|
||
|
|
||
|
# delete live stats
|
||
|
my $query = "DELETE FROM hlstats_Livestats WHERE player_id=".$self->{playerid};
|
||
|
&::execNonQuery($query);
|
||
|
}
|
||
|
|
||
|
|
||
|
#
|
||
|
# Returns a string of information about the player.
|
||
|
#
|
||
|
|
||
|
sub getInfoString
|
||
|
{
|
||
|
my ($self) = @_;
|
||
|
return sprintf("\"%s\" \<P:%d,U:%d,W:%s,T:%s\>", $self->{name}, $self->{playerid}, $self->{userid}, $self->{uniqueid}, $self->{team});
|
||
|
}
|
||
|
|
||
|
|
||
|
sub getAddress
|
||
|
{
|
||
|
my ($self) = @_;
|
||
|
my $haveAddress = 0;
|
||
|
|
||
|
if ($self->{address} ne "")
|
||
|
{
|
||
|
$haveAddress = 1;
|
||
|
}
|
||
|
elsif ($::g_stdin == 0 && $self->{is_bot} == 0 && $self->{userid} > 0)
|
||
|
{
|
||
|
$s_addr = $self->{server};
|
||
|
|
||
|
&::printNotice("rcon_getaddress");
|
||
|
my $result = $::g_servers{$s_addr}->rcon_getaddress($self->{uniqueid});
|
||
|
if ($result->{Address} ne "") {
|
||
|
$haveAddress = 1;
|
||
|
$self->{address} = $result->{Address};
|
||
|
$self->{cli_port} = $result->{ClientPort};
|
||
|
$self->{ping} = $result->{Ping};
|
||
|
|
||
|
&::printEvent("RCON", "Got Address $self->{address} for Player $self->{name}", 1);
|
||
|
&::printNotice("rcon_getaddress successfully");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ($haveAddress > 0)
|
||
|
{
|
||
|
# Update player IP address in database
|
||
|
my $query = "
|
||
|
UPDATE
|
||
|
hlstats_Players
|
||
|
SET
|
||
|
lastAddress=?
|
||
|
WHERE
|
||
|
playerId=?
|
||
|
";
|
||
|
my @vals = ($self->{address}, $self->{playerid});
|
||
|
&::execCached("player_update_lastaddress", $query, @vals);
|
||
|
&::printEvent("DEBUG", "Updated IP for ".$self->{playerid}." to ".$self->{address});
|
||
|
|
||
|
$self->geoLookup();
|
||
|
}
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
sub geoLookup
|
||
|
{
|
||
|
my ($self) = @_;
|
||
|
my $ip_address = $self->{address};
|
||
|
my $found = 0;
|
||
|
|
||
|
if ($ip_address ne "")
|
||
|
{
|
||
|
my $country_code = undef;
|
||
|
my $country_code3 = undef;
|
||
|
my $country_name = undef;
|
||
|
my $region = undef;
|
||
|
my $city = undef;
|
||
|
my $postal_code = undef;
|
||
|
my $lat = undef;
|
||
|
my $lng = undef;
|
||
|
my $metro_code = undef;
|
||
|
my $area_code = undef;
|
||
|
|
||
|
if ($::g_geoip_binary > 0) {
|
||
|
if(!defined($::g_gi)) {
|
||
|
return;
|
||
|
}
|
||
|
($country_code, $country_code3, $country_name, $region, $city, $postal_code, $lat, $lng, $metro_code, $area_code) = $::g_gi->get_city_record($ip_address);
|
||
|
if ($lng) {
|
||
|
$found++;
|
||
|
$self->{city} = ((defined($city))?encode("utf8",$city):"");
|
||
|
$self->{state} = ((defined($region))?encode("utf8",$region):"");
|
||
|
$self->{country} = ((defined($country_name))?encode("utf8",$country_name):"");
|
||
|
$self->{flag} = ((defined($country_code))?encode("utf8",$country_code):"");
|
||
|
$self->{lat} = (($lat eq "")?undef:$lat);
|
||
|
$self->{lng} = (($lng eq "")?undef:$lng);
|
||
|
}
|
||
|
} else {
|
||
|
my @ipp = split (/\./,$ip_address);
|
||
|
my $ip_number = $ipp[0]*16777216+$ipp[1]*65536+$ipp[2]*256+$ipp[3];
|
||
|
my $query = "
|
||
|
SELECT locId FROM geoLiteCity_Blocks WHERE startIpNum<=".$ip_number." AND endIpNum>=".$ip_number." LIMIT 1;";
|
||
|
my $result = &::doQuery($query);
|
||
|
if ($result->rows > 0) {
|
||
|
my $locid = $result->fetchrow_array;
|
||
|
$result->finish;
|
||
|
my $query = "SELECT city, region AS state, name AS country, country AS flag, latitude AS lat, longitude AS lng FROM geoLiteCity_Location a inner join hlstats_Countries b ON a.country=b.flag WHERE locId=".$locid." LIMIT 1;";
|
||
|
my $result = &::doQuery($query);
|
||
|
if ($result->rows > 0) {
|
||
|
$found++;
|
||
|
($city, $state, $country, $flag, $lat, $lng) = $result->fetchrow_array;
|
||
|
$self->{city} = ((defined($city))?$city:"");
|
||
|
$self->{state} = ((defined($state))?$state:"");
|
||
|
$self->{country} = ((defined($country))?$country:"");
|
||
|
$self->{flag} = ((defined($flag))?$flag:"");
|
||
|
$self->{lat} = (($lat eq "")?undef:$lat);
|
||
|
$self->{lng} = (($lng eq "")?undef:$lng);
|
||
|
}
|
||
|
$result->finish;
|
||
|
}
|
||
|
}
|
||
|
if ($found > 0) {
|
||
|
&::execNonQuery("
|
||
|
UPDATE
|
||
|
hlstats_Players
|
||
|
SET
|
||
|
city='".&::quoteSQL($self->{city})."',
|
||
|
`state`='".&::quoteSQL($self->{state})."',
|
||
|
country='".&::quoteSQL($self->{country})."',
|
||
|
flag='".&::quoteSQL($self->{flag})."',
|
||
|
lat=".((defined($self->{lat}))?$self->{lat}:"NULL").",
|
||
|
lng=".((defined($self->{lng}))?$self->{lng}:"NULL")."
|
||
|
WHERE
|
||
|
playerId = ".$self->{playerid}
|
||
|
);
|
||
|
&::execNonQuery("
|
||
|
UPDATE
|
||
|
hlstats_Livestats
|
||
|
SET
|
||
|
cli_city='".&::quoteSQL($self->{city})."',
|
||
|
cli_country='".&::quoteSQL($self->{country})."',
|
||
|
cli_flag='".&::quoteSQL($self->{flag})."',
|
||
|
cli_state='".&::quoteSQL($self->{state})."',
|
||
|
cli_lat=".((defined($self->{lat}))?$self->{lat}:"NULL").",
|
||
|
cli_lng=".((defined($self->{lng}))?$self->{lng}:"NULL")."
|
||
|
WHERE
|
||
|
player_id =".$self->{playerid}
|
||
|
);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
sub getRank
|
||
|
{
|
||
|
my ($self) = @_;
|
||
|
|
||
|
my $srv_addr = $self->{server};
|
||
|
$query = "
|
||
|
SELECT
|
||
|
kills,
|
||
|
deaths,
|
||
|
hideranking
|
||
|
FROM
|
||
|
hlstats_Players
|
||
|
WHERE
|
||
|
playerId=?
|
||
|
";
|
||
|
my $result = &::execCached("get_player_rank_stats", $query, $self->{playerid});
|
||
|
|
||
|
my ($kills, $deaths, $hideranking) = $result->fetchrow_array;
|
||
|
$result->finish;
|
||
|
|
||
|
return 0 if ($hideranking > 0);
|
||
|
|
||
|
$deaths = 1 if ($deaths == 0);
|
||
|
my $kpd = $kills/$deaths;
|
||
|
|
||
|
my $rank = 0;
|
||
|
|
||
|
if ($::g_ranktype ne "kills")
|
||
|
{
|
||
|
if (!defined($self->{skill}))
|
||
|
{
|
||
|
&::printEvent("ERROR","Attempted to get rank for uninitialized player \"".$self->{name}."\"");
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
my $query = "
|
||
|
SELECT
|
||
|
COUNT(*)
|
||
|
FROM
|
||
|
hlstats_Players
|
||
|
WHERE
|
||
|
game=?
|
||
|
AND hideranking = 0
|
||
|
AND kills >= 1
|
||
|
AND (
|
||
|
(skill > ?) OR (
|
||
|
(skill = ?) AND ((kills/IF(deaths=0,1,deaths)) > ?)
|
||
|
)
|
||
|
)
|
||
|
";
|
||
|
my @vals = (
|
||
|
&::quoteSQL($self->{game}),
|
||
|
$self->{skill},
|
||
|
$self->{skill},
|
||
|
$kpd
|
||
|
);
|
||
|
my $rankresult = &::execCached("get_player_skill_value", $query, @vals);
|
||
|
($rank) = $rankresult->fetchrow_array;
|
||
|
$rankresult->finish;
|
||
|
$rank++;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
my $query ="
|
||
|
SELECT
|
||
|
COUNT(*)
|
||
|
FROM
|
||
|
hlstats_Players
|
||
|
WHERE
|
||
|
game=?
|
||
|
AND hideranking = 0
|
||
|
AND (
|
||
|
(kills > ?) OR (
|
||
|
(kills = ?) AND ((kills/IF(deaths=0,1,deaths)) > ?)
|
||
|
)
|
||
|
)
|
||
|
";
|
||
|
my @vals = (
|
||
|
&::quoteSQL($self->{game}),
|
||
|
$kills,
|
||
|
$kills,
|
||
|
$kpd
|
||
|
);
|
||
|
my $rankresult = &::execCached("get_player_rank_value", $query, @vals);
|
||
|
($rank) = $rankresult->fetchrow_array;
|
||
|
$rankresult->finish;
|
||
|
$rank++;
|
||
|
}
|
||
|
|
||
|
return $rank;
|
||
|
}
|
||
|
|
||
|
sub updateTrackable
|
||
|
{
|
||
|
my ($self) = @_;
|
||
|
|
||
|
if ((&::isTrackableTeam($self->{team}) == 0) || (($::g_servers{$self->{server}}->{ignore_bots} == 1) && (($self->{is_bot} == 1) || ($self->{userid} <= 0)))) {
|
||
|
$self->{trackable} = 0;
|
||
|
return;
|
||
|
}
|
||
|
$self->{trackable} = 1;
|
||
|
}
|
||
|
|
||
|
1;
|