hlstats.pl

hlstats.pl

PageRenderTime 171ms CodeModel.GetById 4ms app.highlight 149ms RepoModel.GetById 1ms app.codeStats 1ms

/scripts/hlstats.pl

https://bitbucket.org/psychonic/hlstatsxce
Perl | 3626 lines | 3011 code | 327 blank | 288 comment | 469 complexity | 5eb88865da775b19ae0d23a2257d33e4 MD5 | raw file

Large files files are truncated, but you can click here to view the full file

1#!/usr/bin/perl 2# HLstatsX Community Edition – Real-time player and clan rankings and statistics 3# Copyleft (L) 2008-20XX Nicholas Hastings (nshastings@gmail.com) 4# http://www.hlxcommunity.com 5# 6# HLstatsX Community Edition is a continuation of 7# ELstatsNEO – Real-time player and clan rankings and statistics 8# Copyleft (L) 2008-20XX Malte Bayer (steam@neo-soft.org) 9# http://ovrsized.neo-soft.org/ 10# 11# ELstatsNEO is an very improved & enhanced – so called Ultra-Humongus Edition of HLstatsX 12# HLstatsX – Real-time player and clan rankings and statistics for Half-Life 2 13# http://www.hlstatsx.com/ 14# Copyright (C) 2005-2007 Tobias Oetzel (Tobi@hlstatsx.com) 15# 16# HLstatsX is an enhanced version of HLstats made by Simon Garner 17# HLstats – Real-time player and clan rankings and statistics for Half-Life 18# http://sourceforge.net/projects/hlstats/ 19# Copyright (C) 2001 Simon Garner 20# 21# This program is free software; you can redistribute it and/or 22# modify it under the terms of the GNU General Public License 23# as published by the Free Software Foundation; either version 2 24# of the License, or (at your option) any later version. 25# 26# This program is distributed in the hope that it will be useful, 27# but WITHOUT ANY WARRANTY; without even the implied warranty of 28# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 29# GNU General Public License for more details. 30# 31# You should have received a copy of the GNU General Public License 32# along with this program; if not, write to the Free Software 33# Foundation, Inc., 59 Temple Place – Suite 330, Boston, MA 02111-1307, USA. 34# 35# For support and installation notes visit http://www.hlxcommunity.com 36 37use strict; 38no strict ‘vars’; 39 40$SIG{HUP} = ‘HUP_handler’; 41$SIG{INT} = ‘INT_handler’; # unix 42$SIG{INT2} = ‘INT_handler’; # windows 43 44## 45## Settings 46## 47 48# $opt_configfile – Absolute path and filename of configuration file. 49$opt_configfile = “./hlstats.conf”; 50 51# $opt_libdir – Directory to look in for local required files 52# (our *.plib, *.pm files). 53$opt_libdir = “./”; 54 55 56## 57## 58################################################################################ 59## No need to edit below this line 60## 61 62use Getopt::Long; 63use Time::Local; 64use IO::Socket; 65use IO::Select; 66use DBI; 67use Digest::MD5; 68use Encode; 69use bytes; 70 71require “$opt_libdir/ConfigReaderSimple.pm”; 72require “$opt_libdir/TRcon.pm”; 73require “$opt_libdir/BASTARDrcon.pm”; 74require “$opt_libdir/HLstats_Server.pm”; 75require “$opt_libdir/HLstats_Player.pm”; 76require “$opt_libdir/HLstats_Game.pm”; 77do “$opt_libdir/HLstats_GameConstants.plib”; 78do “$opt_libdir/HLstats.plib”; 79do “$opt_libdir/HLstats_EventHandlers.plib”; 80 81$|=1; 82Getopt::Long::Configure (“bundling”); 83 84$last_trend_timestamp = 0; 85 86binmode STDIN, “:utf8”; 87binmode STDOUT, “:utf8”; 88 89## 90## Functions 91## 92 93sub lookupPlayer 94{ 95 my ($saddr, $id, $uniqueid) = @_; 96 if (defined($g_servers{$saddr}->{“srv_players”}->{“$id/$uniqueid”})) 97 { 98 return $g_servers{$saddr}->{“srv_players”}->{“$id/$uniqueid”}; 99 } 100 return undef; 101} 102 103sub removePlayer 104{ 105 my ($saddr, $id, $uniqueid, $dontUpdateCount) = @_; 106 my $deleteplayer = 0; 107 if(defined($g_servers{$saddr}->{“srv_players”}->{“$id/$uniqueid”})) 108 { 109 $deleteplayer = 1; 110 } 111 else 112 { 113 &::printEvent(“400”, “Bad attempted delete ($saddr) ($id/$uniqueid)”); 114 } 115 116 if ($deleteplayer == 1) { 117 $g_servers{$saddr}->{“srv_players”}->{“$id/$uniqueid”}->playerCleanup(); 118 delete($g_servers{$saddr}->{“srv_players”}->{“$id/$uniqueid”}); 119 if (!$dontUpdateCount) # double negative, i know… 120 { 121 $g_servers{$saddr}->updatePlayerCount(); 122 } 123 } 124} 125 126sub checkBonusRound 127{ 128 if ($g_servers{$s_addr}->{bonusroundtime} > 0 && ($::ev_remotetime > ($g_servers{$s_addr}->{bonusroundtime_ts} + $g_servers{$s_addr}->{bonusroundtime}))) { 129 if ($g_servers{$s_addr}->{bonusroundtime_state} == 1) { 130 &printEvent(“SERVER”, “Bonus Round Expired”,1); 131 } 132 $g_servers{$s_addr}->set(“bonusroundtime_state”,0); 133 } 134 135 if($g_servers{$s_addr}->{bonusroundignore} == 1 && $g_servers{$s_addr}->{bonusroundtime_state} == 1) { 136 return 1; 137 } 138 return 0; 139} 140 141sub is_number ($) { ( $_[0] ^ $_[0] ) eq ‘0’ } 142 143 144# 145# void printNotice (string notice) 146# 147# Prins a debugging notice to stdout. 148# 149 150sub printNotice 151{ 152 my ($notice) = @_; 153 154 if ($g_debug > 1) { 155 print “>> $noticen”; 156 } 157} 158 159sub track_hlstats_trend 160{ 161 if ($last_trend_timestamp > 0) { 162 if ($last_trend_timestamp+299 fetchrow_array) { 186 my $query = ” 187 SELECT 188 SUM(kills), 189 SUM(headshots), 190 COUNT(serverId), 191 SUM(act_players), 192 SUM(max_players) 193 FROM 194 hlstats_Servers 195 WHERE 196 game=? 197 “; 198 my $data = &execCached(“get_game_stat_counts”, $query, &quoteSQL($game)); 199 my ($total_kills, $total_headshots, $total_servers, $act_slots, $max_slots) = $data->fetchrow_array; 200 if ($max_slots > 0) { 201 if ($act_slots > $max_slots) { 202 $act_slots = $max_slots; 203 } 204 } 205 if ($insvalues ne “”) { 206 $insvalues .= “,”; 207 } 208 $insvalues .= ” 209 ( 210 $ev_daemontime, 211 ‘”.&quoteSQL($game).”‘, 212 $total_players, 213 $total_kills, 214 $total_headshots, 215 $total_servers, 216 $act_slots, 217 $max_slots 218 ) 219 “; 220 } 221 if ($insvalues ne “”) { 222 &execNonQuery(” 223 INSERT INTO 224 hlstats_Trend 225 ( 226 timestamp, 227 game, 228 players, 229 kills, 230 headshots, 231 servers, 232 act_slots, 233 max_slots 234 ) 235 VALUES $insvalues 236 “); 237 } 238 $last_trend_timestamp = $ev_daemontime; 239 &::printEvent(“HLSTATSX”, “Insert new server trend timestamp”, 1); 240 } 241 } else { 242 $last_trend_timestamp = $ev_daemontime; 243 } 244} 245 246sub send_global_chat 247{ 248 my ($message) = @_; 249 while( my($server) = each(%g_servers)) 250 { 251 if ($server ne $s_addr && $g_servers{$server}->{“srv_players”}) 252 { 253 my @userlist; 254 my %players_temp=%{$g_servers{$server}->{“srv_players”}}; 255 my $pcount = scalar keys %players_temp; 256 257 if ($pcount > 0) { 258 while ( my($pl, $b_player) = each(%players_temp) ) { 259 my $b_userid = $b_player->{userid}; 260 if ($g_global_chat == 2) { 261 my $b_steamid = $b_player->{uniqueid}; 262 if ($g_servers{$server}->is_admin($b_steamid) == 1) { 263 if (($b_player->{display_events} == 1) && ($b_player->{display_chat} == 1)) { 264 push(@userlist, $b_player->{userid}); 265 } 266 } 267 } else { 268 if (($b_player->{display_events} == 1) && ($b_player->{display_chat} == 1)) { 269 push(@userlist, $b_player->{userid}); 270 } 271 } 272 } 273 $g_servers{$server}->messageMany($message, 0, @userlist); 274 } 275 } 276 } 277} 278 279# 280# void buildEventInsertData () 281# 282# Ran at startup to init event table queues, build initial queries, and set allowed-null columns 283# 284 285my %g_eventtable_data = (); 286 287sub buildEventInsertData 288{ 289 my $insertType = “”; 290 $insertType = ” DELAYED” if ($db_lowpriority); 291 while ( my ($table, $colsref) = each(%g_eventTables) ) 292 { 293 $g_eventtable_data{$table}{queue} = []; 294 $g_eventtable_data{$table}{nullallowed} = 0; 295 $g_eventtable_data{$table}{lastflush} = $ev_daemontime; 296 $g_eventtable_data{$table}{query} = ” 297 INSERT$insertType INTO 298 hlstats_Events_$table 299 ( 300 eventTime, 301 serverId, 302 map” 303 ; 304 my $j = 0; 305 foreach $i (@{$colsref}) 306 { 307 $g_eventtable_data{$table}{query} .= “,n$i”; 308 if (substr($i, 0, 4) eq ‘pos_’) { 309 $g_eventtable_data{$table}{nullallowed} |= (1 <{‘id’}.”,'”.quoteSQL($g_servers{$s_addr}->get_map()).”‘”; 330 $j = 0; 331 for $i (@coldata) { 332 if ($g_eventtable_data{$table}{nullallowed} & (1 < $g_event_queue_size) 346 { 347 flushEventTable($table); 348 } 349} 350 351sub flushEventTable 352{ 353 my ($table) = @_; 354 355 if (scalar(@{$g_eventtable_data{$table}{queue}}) == 0) 356 { 357 return; 358 } 359 360 my $query = $g_eventtable_data{$table}{query}; 361 foreach (@{$g_eventtable_data{$table}{queue}}) 362 { 363 $query .= $_.”,”; 364 } 365 $query =~ s/,$//; 366 execNonQuery($query); 367 $g_eventtable_data{$table}{lastflush} = $ev_daemontime; 368 $g_eventtable_data{$table}{queue} = []; 369} 370 371 372# 373# array calcSkill (int skill_mode, int killerSkill, int killerKills, int victimSkill, int victimKills, string weapon) 374# 375# Returns an array, where the first index contains the killer’s new skill, and 376# the second index contains the victim’s new skill. 377# 378 379sub calcSkill 380{ 381 my ($skill_mode, $killerSkill, $killerKills, $victimSkill, $victimKills, $weapon, $killerTeam) = @_; 382 my @newSkill; 383 384 # ignored bots never do a “comeback” 385 return ($g_skill_minchange, $victimSkill) if ($killerSkill < 1); 386 return ($killerSkill + $g_skill_minchange, $victimSkill) if ($victimSkill 2) { 389 &printNotice(“Begin calcSkill: killerSkill=$killerSkill”); 390 &printNotice(“Begin calcSkill: victimSkill=$victimSkill”); 391 } 392 393 my $modifier = 1.00; 394 # Look up the weapon’s skill modifier 395 if (defined($g_games{$g_servers{$s_addr}->{game}}{weapons}{$weapon})) { 396 $modifier = $g_games{$g_servers{$s_addr}->{game}}{weapons}{$weapon}{modifier}; 397 } 398 399 # Calculate the new skills 400 401 my $killerSkillChange = 0; 402 if ($g_skill_ratio_cap > 0) { 403 # SkillRatioCap, from *XYZ*SaYnt 404 # 405 # dgh…we want to cap the ratio between the victimkill and killerskill. For example, if the number 1 player 406 # kills a newbie, he gets 1000/5000 * 5 * 1 = 1 points. If gets killed by the newbie, he gets 5000/1000 * 5 *1 407 # = -25 points. Not exactly fair. To fix this, I’m going to cap the ratio to 1/2 and 2/1. 408 # these numbers are designed such that an excellent player will have to get about a 2:1 ratio against noobs to 409 # hold steady in points. 410 my $lowratio = 0.7; 411 my $highratio = 1.0 / $lowratio; 412 my $ratio = ($victimSkill / $killerSkill); 413 if ($ratio $highratio) { $ratio = $highratio; } 415 $killerSkillChange = $ratio * 5 * $modifier; 416 } else { 417 $killerSkillChange = ($victimSkill / $killerSkill) * 5 * $modifier; 418 } 419 420 if ($killerSkillChange > $g_skill_maxchange) { 421 &printNotice(“Capping killer skill change of $killerSkillChange to $g_skill_maxchange”) if ($g_debug > 2); 422 $killerSkillChange = $g_skill_maxchange; 423 } 424 425 my $victimSkillChange = $killerSkillChange; 426 427 if ($skill_mode == 1) 428 { 429 $victimSkillChange = $killerSkillChange * 0.75; 430 } 431 elsif ($skill_mode == 2) 432 { 433 $victimSkillChange = $killerSkillChange * 0.5; 434 } 435 elsif ($skill_mode == 3) 436 { 437 $victimSkillChange = $killerSkillChange * 0.25; 438 } 439 elsif ($skill_mode == 4) 440 { 441 $victimSkillChange = 0; 442 } 443 elsif ($skill_mode == 5) 444 { 445 #Zombie Panic: Source only 446 #Method suggested by heimer. Survivor’s lose half of killer’s gain when dying, but Zombie’s only lose a quarter. 447 if ($killerTeam eq “Undead”) 448 { 449 $victimSkillChange = $killerSkillChange * 0.5; 450 } 451 elsif ($killerTeam eq “Survivor”) 452 { 453 $victimSkillChange = $killerSkillChange * 0.25; 454 } 455 } 456 457 if ($victimSkillChange > $g_skill_maxchange) { 458 &printNotice(“Capping victim skill change of $victimSkillChange to $g_skill_maxchange”) if ($g_debug > 2); 459 $victimSkillChange = $g_skill_maxchange; 460 } 461 462 if ($g_skill_maxchange >= $g_skill_minchange) { 463 if ($killerSkillChange 2); 465 $killerSkillChange = $g_skill_minchange; 466 } 467 468 if (($victimSkillChange 2); 470 $victimSkillChange = $g_skill_minchange; 471 } 472 } 473 if (($killerKills < $g_player_minkills ) || ($victimKills 2) { 490 &printNotice(“End calcSkill: killerSkill=$killerSkill”); 491 &printNotice(“End calcSkill: victimSkill=$victimSkill”); 492 } 493 494 return ($killerSkill, $victimSkill); 495} 496 497sub calcL4DSkill 498{ 499 my ($killerSkill, $weapon, $difficulty) = @_; 500 501 # ignored bots never do a “comeback” 502 #return ($killerSkill, $victimSkill) if ($killerSkill < 1); 503 #return ($killerSkill, $victimSkill) if ($victimSkill 2) { 506 &printNotice(“Begin calcSkill: killerSkill=$killerSkill”); 507 &printNotice(“Begin calcSkill: victimSkill=$victimSkill”); 508 } 509 510 my $modifier = 1.00; 511 # Look up the weapon’s skill modifier 512 if (defined($g_games{$g_servers{$s_addr}->{game}}{weapons}{$weapon})) { 513 $modifier = $g_games{$g_servers{$s_addr}->{game}}{weapons}{$weapon}{modifier}; 514 } 515 516 # Calculate the new skills 517 518 $diffweight=0.5; 519 if ($difficulty > 0) { 520 $diffweight = $difficulty / 2; 521 } 522 523 my $killerSkillChange = $pointvalue * $diffweight; 524 525 if ($killerSkillChange > $g_skill_maxchange) { 526 &printNotice(“Capping killer skill change of $killerSkillChange to $g_skill_maxchange”) if ($g_debug > 2); 527 $killerSkillChange = $g_skill_maxchange; 528 } 529 530 if ($g_skill_maxchange >= $g_skill_minchange) { 531 if ($killerSkillChange 2); 533 $killerSkillChange = $g_skill_minchange; 534 } 535 } 536 537 $killerSkill += $killerSkillChange; 538 # we want int not float 539 $killerSkill = sprintf(“%d”, $killerSkill + 0.5); 540 541 if ($g_debug > 2) { 542 &printNotice(“End calcSkill: killerSkill=$killerSkill”); 543 } 544 545 return $killerSkill; 546} 547 548 549# Gives members of ‘team’ an extra ‘reward’ skill points. Members of the team 550# who have been inactive (no events) for more than 2 minutes are not rewarded. 551# 552 553sub rewardTeam 554{ 555 my ($team, $reward, $actionid, $actionname, $actioncode) = @_; 556 $rcmd = $g_servers{$s_addr}->{broadcasting_command}; 557 558 my $player; 559 560 &printNotice(“Rewarding team “$team” with “$reward” skill for action “$actionid” …”); 561 my @userlist; 562 foreach $player (values(%g_players)) { 563 my $player_team = $player->{team}; 564 my $player_timestamp = $player->{timestamp}; 565 if (($g_servers{$s_addr}->{ignore_bots} == 1) && (($player->{is_bot} == 1) || ($player->{userid} 2) { 570 &printNotice(“Rewarding ” . $player->getInfoString() . ” with “$reward” skill for action “$actionid””); 571 } 572 573 &recordEvent( 574 “TeamBonuses”, 0, 575 $player->{playerid}, 576 $actionid, 577 $reward 578 ); 579 $player->increment(“skill”, $reward, 1); 580 $player->increment(“session_skill”, $reward, 1); 581 $player->updateDB(); 582 } 583 if ($player->{is_bot} == 0 && $player->{userid} > 0 && $player->{display_events} == 1) { 584 push(@userlist, $player->{userid}); 585 } 586 } 587 } 588 if (($g_servers{$s_addr}->{broadcasting_events} == 1) && ($g_servers{$s_addr}->{broadcasting_player_actions} == 1)) { 589 my $coloraction = $g_servers{$s_addr}->{format_action}; 590 my $verb = “got”; 591 if ($reward messageMany($msg, 0, @userlist); 596 } 597} 598 599 600# 601# int getPlayerId (uniqueId) 602# 603# Looks up a player’s ID number, from their unique (WON) ID. Returns their PID. 604# 605 606sub getPlayerId 607{ 608 my ($uniqueId) = @_; 609 610 my $query = ” 611 SELECT 612 playerId 613 FROM 614 hlstats_PlayerUniqueIds 615 WHERE 616 uniqueId='” . &::quoteSQL($uniqueId) . “‘ AND 617 game='” . $g_servers{$s_addr}->{game} . “‘ 618 “; 619 my $result = &doQuery($query); 620 621 if ($result->rows > 0) { 622 my ($playerId) = $result->fetchrow_array; 623 $result->finish; 624 return $playerId; 625 } else { 626 $result->finish; 627 return 0; 628 } 629} 630 631 632# 633# int updatePlayerProfile (object player, string field, string value) 634# 635# Updates a player’s profile information in the database. 636# 637 638sub updatePlayerProfile 639{ 640 my ($player, $field, $value) = @_; 641 $rcmd = $g_servers{$s_addr}->{player_command}; 642 643 unless ($player) { 644 &printNotice(“updatePlayerInfo: Bad player”); 645 return 0; 646 } 647 648 $value = &quoteSQL($value); 649 if ($value eq “none” || $value eq ” “) { 650 $value = “”; 651 } 652 653 my $playerName = &abbreviate($player->{name}); 654 my $playerId = $player->{playerid}; 655 656 &execNonQuery(” 657 UPDATE 658 hlstats_Players 659 SET 660 $field=’$value’ 661 WHERE 662 playerId=$playerId 663 “); 664 665 if ($g_servers{$s_addr}->{player_events} == 1) { 666 my $p_userid = $g_servers{$s_addr}->format_userid($player->{userid}); 667 my $p_is_bot = $player->{is_bot}; 668 $cmd_str = $rcmd.” $p_userid “.$g_servers{$s_addr}->quoteparam(“SET command successful for ‘$playerName’.”); 669 $g_servers{$s_addr}->dorcon($cmd_str); 670 } 671 return 1; 672} 673 674 675# 676# mixed getClanId (string name) 677# 678# Looks up a player’s clan ID from their name. Compares the player’s name to tag 679# patterns in hlstats_ClanTags. Patterns look like: [AXXXXX] (matches 1 to 6 680# letters inside square braces, e.g. [ZOOM]Player) or =*AAXX*= (matches 681# 2 to 4 letters between an equals sign and an asterisk, e.g. =*RAGE*=Player). 682# 683# Special characters in the pattern: 684# A matches one character (i.e. a character is required) 685# X matches zero or one characters (i.e. a character is optional) 686# a matches literal A or a 687# x matches literal X or x 688# 689# If no clan exists for the tag, it will be created. Returns the clan’s ID, or 690# 0 if the player is not in a clan. 691# 692 693sub getClanId 694{ 695 my ($name) = @_; 696 my $clanTag = “”; 697 my $clanName = “”; 698 my $clanId = 0; 699 my $result = &doQuery(” 700 SELECT 701 pattern, 702 position, 703 LENGTH(pattern) AS pattern_length 704 FROM 705 hlstats_ClanTags 706 ORDER BY 707 pattern_length DESC, 708 id 709 “); 710 711 while ( my($pattern, $position) = $result->fetchrow_array) { 712 my $regpattern = quotemeta($pattern); 713 $regpattern =~ s/([A-Za-z0-9]+[A-Za-z0-9_-]*)/($1)/; # to find clan name from tag 714 $regpattern =~ s/A/./g; 715 $regpattern =~ s/X/.?/g; 716 717 if ($g_debug > 2) { 718 &printNotice(“regpattern=$regpattern”); 719 } 720 721 if ((($position eq “START” || $position eq “EITHER”) && $name =~ /^($regpattern).+/i) || 722 (($position eq “END” || $position eq “EITHER”) && $name =~ /.+($regpattern)$/i)) { 723 724 if ($g_debug > 2) { 725 &printNotice(“pattern “$regpattern” matches “$name”! 1=”$1″ 2=”$2″”); 726 } 727 728 $clanTag = $1; 729 $clanName = $2; 730 last; 731 } 732 } 733 734 unless ($clanTag) { 735 return 0; 736 } 737 738 my $query = ” 739 SELECT 740 clanId 741 FROM 742 hlstats_Clans 743 WHERE 744 tag='” . &quoteSQL($clanTag) . “‘ AND 745 game=’$g_servers{$s_addr}->{game}’ 746 “; 747 $result = &doQuery($query); 748 749 if ($result->rows) { 750 ($clanId) = $result->fetchrow_array; 751 $result->finish; 752 return $clanId; 753 } else { 754 # The clan doesn’t exist yet, so we create it. 755 $query = ” 756 REPLACE INTO 757 hlstats_Clans 758 ( 759 tag, 760 name, 761 game 762 ) 763 VALUES 764 ( 765 ‘” . &quoteSQL($clanTag) . “‘, 766 ‘” . &quoteSQL($clanName) . “‘, 767 ‘”.&quoteSQL($g_servers{$s_addr}->{game}).”‘ 768 ) 769 “; 770 &execNonQuery($query); 771 772 $clanId = $db_conn->{‘mysql_insertid’}; 773 774 &printNotice(“Created clan “$clanName” with tag ” 775 . “”$clanTag” for player “$name””); 776 return $clanId; 777 } 778} 779 780 781# 782# object getServer (string address, int port) 783# 784# Looks up a server’s ID number in the Servers table, by searching for a 785# matching IP address and port. NOTE you must specify IP addresses in the 786# Servers table, NOT hostnames. 787# 788# Returns a new “Server object”. 789# 790 791sub getServer 792{ 793 my ($address, $port) = @_; 794 795 my $query = ” 796 SELECT 797 a.serverId, 798 a.game, 799 a.name, 800 a.rcon_password, 801 a.publicaddress, 802 IFNULL(b.`value`,3) AS game_engine, 803 IFNULL(c.`realgame`, ‘hl2mp’) AS realgame, 804 IFNULL(a.max_players, 0) AS maxplayers 805 806 FROM 807 hlstats_Servers a LEFT JOIN hlstats_Servers_Config b on a.serverId = b.serverId AND b.`parameter` = ‘GameEngine’ LEFT JOIN `hlstats_Games` c ON a.game = c.code 808 WHERE 809 address=? AND 810 port=? LIMIT 1 811 “; 812 my @vals = ( 813 $address, 814 $port 815 ); 816 my $result = &execCached(“get_server_information”, $query, @vals); 817 818 if ($result->rows) { 819 my ($serverId, $game, $name, $rcon_pass, $publicaddress, $gameengine, $realgame, $maxplayers) = $result->fetchrow_array; 820 $result->finish; 821 if (!defined($g_games{$game})) { 822 $g_games{$game} = new HLstats_Game($game); 823 } 824 # l4d code should be reused for l4d2 825 # trying first using l4d as “realgame” code for l4d2 in db. if default server config settings won’t work, will leave as own “realgame” code in db but uncomment line. 826 #$realgame = “l4d” if $realgame eq “l4d2”; 827 828 return new HLstats_Server($serverId, $address, $port, $name, $rcon_pass, $game, $publicaddress, $gameengine, $realgame, $maxplayers); 829 } else { 830 $result->finish; 831 return 0; 832 } 833} 834 835# 836# 837# 838# 839# 840 841sub queryServer 842{ 843 my ($iaddr, $iport, @query) = @_; 844 my $game = “”; 845 my $timeout=2; 846 my $message = IO::Socket::INET->new(Proto=>”udp”,Timeout=>$timeout,PeerPort=>$iport,PeerAddr=>$iaddr) or die “Can’t make UDP socket: $@”; 847 $message->send(“xFFxFFxFFxFFTSource Engine Queryx00″); 848 my ($datagram,$flags); 849 my $end = time + $timeout; 850 my $rin = ”; 851 vec($rin, fileno($message), 1) = 1; 852 853 my %hash = (); 854 855 while (1) { 856 my $timeleft = $end – time; 857 last if ($timeleft recv($datagram,1024,$flags); 861 @hash{qw/key type netver hostname mapname gamedir gamename id numplayers maxplayers numbots dedicated os passreq secure gamever edf port/} = unpack(“LCCZ*Z*Z*Z*vCCCCCCCZ*Cv”,$datagram); 862 } 863 864 return @hash{@query}; 865} 866 867 868sub getServerMod 869{ 870 my ($address, $port) = @_; 871 my ($playgame); 872 873 &printEvent (“DETECT”, “Querying $address”.”:$port for gametype”); 874 875 my @query = ( 876 ‘gamename’, 877 ‘gamedir’, 878 ‘hostname’, 879 ‘numplayers’, 880 ‘maxplayers’, 881 ‘mapname’ 882 ); 883 884 my ($gamename, $gamedir, $hostname, $numplayers, $maxplayers, $mapname) = &queryServer($address, $port, @query); 885 886 if ($gamename =~ /^Counter-Strike$/i) { 887 $playgame = “cstrike”; 888 } elsif ($gamename =~ /^Counter-Strike/i) { 889 $playgame = “css”; 890 } elsif ($gamename =~ /^Team Fortress C/i) { 891 $playgame = “tfc”; 892 } elsif ($gamename =~ /^Team Fortress/i) { 893 $playgame = “tf”; 894 } elsif ($gamename =~ /^Day of Defeat$/i) { 895 $playgame = “dod”; 896 } elsif ($gamename =~ /^Day of Defeat/i) { 897 $playgame = “dods”; 898 } elsif ($gamename =~ /^Insurgency/i) { 899 $playgame = “insmod”; 900 } elsif ($gamename =~ /^Neotokyo/i) { 901 $playgame = “nts”; 902 } elsif ($gamename =~ /^Fortress Forever/i) { 903 $playgame = “ff”; 904 } elsif ($gamename =~ /^Age of Chivalry/i) { 905 $playgame = “aoc”; 906 } elsif ($gamename =~ /^Dystopia/i) { 907 $playgame = “dystopia”; 908 } elsif ($gamename =~ /^Stargate/i) { 909 $playgame = “sgtls”; 910 } elsif ($gamename =~ /^Battle Grounds/i) { 911 $playgame = “bg2”; 912 } elsif ($gamename =~ /^Hidden/i) { 913 $playgame = “hidden”; 914 } elsif ($gamename =~ /^L4D /i) { 915 $playgame = “l4d”; 916 } elsif ($gamename =~ /^Left 4 Dead 2/i) { 917 $playgame = “l4d2”; 918 } elsif ($gamename =~ /^ZPS /i) { 919 $playgame = “zps”; 920 } elsif ($gamename =~ /^NS /i) { 921 $playgame = “ns”; 922 } elsif ($gamename =~ /^pvkii/i) { 923 $playgame = “pvkii”; 924 } elsif ($gamename =~ /^CSPromod/i) { 925 $playgame = “csp”; 926 } elsif ($gamename eq “Half-Life”) { 927 $playgame = “valve”; 928 } elsif ($gamename eq “Nuclear Dawn”) { 929 $playgame = “nucleardawn”; 930 931 # We didn’t found our mod, trying secondary way. This is required for some games such as FOF and GES and is a fallback for others 932 } elsif ($gamedir =~ /^ges/i) { 933 $playgame = “ges”; 934 } elsif ($gamedir =~ /^fistful_of_frags/i || $gamedir =~ /^fof/i) { 935 $playgame = “fof”; 936 } elsif ($gamedir =~ /^hl2mp/i) { 937 $playgame = “hl2mp”; 938 } elsif ($gamedir =~ /^tfc/i) { 939 $playgame = “tfc”; 940 } elsif ($gamedir =~ /^tf/i) { 941 $playgame = “tf”; 942 } elsif ($gamedir =~ /^ins/i) { 943 $playgame = “insmod”; 944 } elsif ($gamedir =~ /^neotokyo/i) { 945 $playgame = “nts”; 946 } elsif ($gamedir =~ /^fortressforever/i) { 947 $playgame = “ff”; 948 } elsif ($gamedir =~ /^ageofchivalry/i) { 949 $playgame = “aoc”; 950 } elsif ($gamedir =~ /^dystopia/i) { 951 $playgame = “dystopia”; 952 } elsif ($gamedir =~ /^sgtls/i) { 953 $playgame = “sgtls”; 954 } elsif ($gamedir =~ /^hidden/i) { 955 $playgame = “hidden”; 956 } elsif ($gamedir =~ /^left4dead/i) { 957 $playgame = “l4d”; 958 } elsif ($gamedir =~ /^left4dead2/i) { 959 $playgame = “l4d2”; 960 } elsif ($gamedir =~ /^zps/i) { 961 $playgame = “zps”; 962 } elsif ($gamedir =~ /^ns/i) { 963 $playgame = “ns”; 964 } elsif ($gamedir =~ /^bg/i) { 965 $playgame = “bg2”; 966 } elsif ($gamedir =~ /^pvkii/i) { 967 $playgame = “pvkii”; 968 } elsif ($gamedir =~ /^cspromod/i) { 969 $playgame = “csp”; 970 } elsif ($gamedir =~ /^valve$/i) { 971 $playgame = “valve”; 972 } elsif ($gamedir =~ /^nucleardawn$/i) { 973 $playgame = “nucleardawn”; 974 } elsif ($gamedir =~ /^dinodday$/i) { 975 $playgame = “dinodday”; 976 } else { 977 # We didn’t found our mod, giving up. 978 &printEvent(“DETECT”, “Failed to get Server Mod”); 979 return 0; 980 } 981 &printEvent(“DETECT”, “Saving server ” . $address . “:” . $port . ” with gametype ” . $playgame); 982 &addServerToDB($address, $port, $hostname, $playgame, $numplayers, $maxplayers, $mapname); 983 return $playgame; 984} 985 986sub addServerToDB 987{ 988 my ($address, $port, $name, $game, $act_players, $max_players, $act_map) = @_; 989 my $sql = “INSERT INTO hlstats_Servers (address, port, name, game, act_players, max_players, act_map) VALUES (‘$address’, $port, ‘”.&quoteSQL($name).”‘, ‘”.&quoteSQL($game).”‘, $act_players, $max_players, ‘”.&quoteSQL($act_map).”‘)”; 990 &execNonQuery($sql); 991 992 my $last_id = $db_conn->{‘mysql_insertid’}; 993 &execNonQuery(“DELETE FROM `hlstats_Servers_Config` WHERE serverId = $last_id”); 994 &execNonQuery(“INSERT INTO `hlstats_Servers_Config` (`serverId`, `parameter`, `value`) 995 SELECT $last_id, `parameter`, `value` 996 FROM `hlstats_Mods_Defaults` WHERE `code` = ”;”); 997 &execNonQuery(“INSERT INTO `hlstats_Servers_Config` (`serverId`, `parameter`, `value`) VALUES 998 ($last_id, ‘Mod’, ”);”); 999 &execNonQuery(“INSERT INTO `hlstats_Servers_Config` (`serverId`, `parameter`, `value`) 1000 SELECT $last_id, `parameter`, `value` 1001 FROM `hlstats_Games_Defaults` WHERE `code` = ‘”.&quoteSQL($game).”‘ 1002 ON DUPLICATE KEY UPDATE `value` = VALUES(`value`);”); 1003 &readDatabaseConfig(); 1004 1005 return 1; 1006} 1007 1008# 1009# boolean sameTeam (string team1, string team2) 1010# 1011# This should be expanded later to allow for team alliances (e.g. TFC-hunted). 1012# 1013 1014sub sameTeam 1015{ 1016 my ($team1, $team2) = @_; 1017 1018 if (($team1 eq $team2) && (($team1 ne “Unassigned”) || ($team2 ne “Unassigned”))) { 1019 return 1; 1020 } else { 1021 return 0; 1022 } 1023} 1024 1025 1026# 1027# string getPlayerInfoString (object player, string ident) 1028# 1029 1030sub getPlayerInfoString 1031{ 1032 my ($player) = shift; 1033 my @ident = @_; 1034 1035 if ($player) { 1036 return $player->getInfoString(); 1037 } else { 1038 return “(” . join(“,”, @ident) . “)”; 1039 } 1040} 1041 1042 1043 1044# 1045# array getPlayerInfo (string player, string $ipAddr) 1046# 1047# Get a player’s name, uid, wonid and team from “Name”. 1048# 1049 1050sub getPlayerInfo 1051{ 1052 my ($player, $create_player, $ipAddr) = @_; 1053 1054 if ($player =~ /^(.*?)<([^]*)><([^]*)>(?:<([^]*)>)?.*$/) { 1055 my $name = $1; 1056 my $userid = $2; 1057 my $uniqueid = $3; 1058 my $team = $4; 1059 my $role = $5; 1060 my $bot = 0; 1061 my $haveplayer = 0; 1062 1063 $plainuniqueid = $uniqueid; 1064 $uniqueid =~ s/^STEAM_[0-9]+?://; 1065 1066 if (($uniqueid eq “Console”) && ($team eq “Console”)) { 1067 return 0; 1068 } 1069 if ($g_servers{$s_addr}->{play_game} == L4D()) { 1070 #for l4d, create meta player object for each role 1071 if ($uniqueid eq “”) { 1072 #infected & witch have blank steamid 1073 if ($name eq “infected”) { 1074 $uniqueid = “BOT-Horde”; 1075 $team = “Infected”; 1076 $userid = -9; 1077 } elsif ($name eq “witch”) { 1078 $uniqueid = “BOT-Witch”; 1079 $team = “Infected”; 1080 $userid = -10; 1081 } else { 1082 return 0; 1083 } 1084 } elsif ($uniqueid eq “BOT”) { 1085 #all other bots have BOT for steamid 1086 if ($team eq “Survivor”) { 1087 if ($name eq “Nick”) { 1088 $userid = -11; 1089 } elsif ($name eq “Ellis”) { 1090 $userid = -13; 1091 } elsif ($name eq “Rochelle”) { 1092 $userid = -14; 1093 } elsif ($name eq “Coach”) { 1094 $userid = -12; 1095 } elsif ($name eq “Louis”) { 1096 $userid = -4; 1097 } elsif ($name eq “Zoey”) { 1098 $userid = -1; 1099 } elsif ($name eq “Francis”) { 1100 $userid = -2; 1101 } elsif ($name eq “Bill”) { 1102 $userid = -3; 1103 } else { 1104 &printEvent(“ERROR”, “No survivor match for $name”,0,1); 1105 $userid = -4; 1106 } 1107 } else { 1108 if ($name eq “Smoker”) { 1109 $userid = -5; 1110 } elsif ($name eq “Boomer”) { 1111 $userid = -6; 1112 } elsif ($name eq “Hunter”) { 1113 $userid = -7; 1114 } elsif ($name eq “Spitter”) { 1115 $userid = -15; 1116 } elsif ($name eq “Jockey”) { 1117 $userid = -16; 1118 } elsif ($name eq “Charger”) { 1119 $userid = -17; 1120 } elsif ($name eq “Tank”) { 1121 $userid = -8; 1122 } else { 1123 &printEvent(“DEBUG”, “No infected match for $name”,0,1); 1124 $userid = -8; 1125 } 1126 } 1127 $uniqueid = “BOT-“.$name; 1128 $name = “BOT-“.$name; 1129 } 1130 } 1131 1132 if ($ipAddr eq “none”) { 1133 $ipAddr = “”; 1134 } 1135 1136 $bot = botidcheck($uniqueid); 1137 1138 if ($g_mode eq “NameTrack”) { 1139 $uniqueid = $name; 1140 } else { 1141 if ($g_mode eq “LAN” && !$bot && $userid > 0) { 1142 if ($ipAddr ne “”) { 1143 $g_lan_noplayerinfo->{“$s_addr/$userid/$name”} = { 1144 ipaddress => $ipAddr, 1145 userid => $userid, 1146 name => $name, 1147 server => $s_addr 1148 }; 1149 $uniqueid = $ipAddr; 1150 } else { 1151 while ( my($index, $player) = each(%g_players) ) { 1152 if (($player->{userid} eq $userid) && 1153 ($player->{name} eq $name)) { 1154 1155 $uniqueid = $player->{uniqueid}; 1156 $haveplayer = 1; 1157 last; 1158 } 1159 } 1160 if (!$haveplayer) { 1161 while ( my($index, $player) = each(%g_lan_noplayerinfo) ) { 1162 if (($player->{server} eq $s_addr) && 1163 ($player->{userid} eq $userid) && 1164 ($player->{name} eq $name)) { 1165 1166 $uniqueid = $player->{ipaddress}; 1167 $haveplayer = 1; 1168 } 1169 } 1170 } 1171 if (!$haveplayer) { 1172 $uniqueid = “UNKNOWN”; 1173 } 1174 } 1175 } else { 1176 # Normal (steamid) mode player and bot, as well as lan mode bots 1177 if ($bot) { 1178 $md5 = Digest::MD5->new; 1179 $md5->add($name); 1180 $md5->add($s_addr); 1181 $uniqueid = “BOT:” . $md5->hexdigest; 1182 $unique_id = $uniqueid if ($g_mode eq “LAN”); 1183 } 1184 1185 if ($uniqueid eq “UNKNOWN” 1186 || $uniqueid eq “STEAM_ID_PENDING” || $uniqueid eq “STEAM_ID_LAN” 1187 || $uniqueid eq “VALVE_ID_PENDING” || $uniqueid eq “VALVE_ID_LAN” 1188 ) { 1189 return { 1190 name => $name, 1191 userid => $userid, 1192 uniqueid => $uniqueid, 1193 team => $team 1194 }; 1195 } 1196 } 1197 } 1198 1199 if (!$haveplayer) 1200 { 1201 while ( my ($index, $player) = each(%g_players) ) { 1202 # Cannot exit loop early as more than one player can exist with same uniqueid 1203 # (bug? or just bad logging) 1204 # Either way, we disconnect any that don’t match the current line 1205 if ($player->{uniqueid} eq $uniqueid) { 1206 $haveplayer = 1; 1207 # Catch players reconnecting without first disconnecting 1208 if ($player->{userid} != $userid) { 1209 1210 &doEvent_Disconnect( 1211 $player->{“userid”}, 1212 $uniqueid, 1213 “” 1214 ); 1215 $haveplayer = 0; 1216 } 1217 } 1218 } 1219 } 1220 1221 if ($haveplayer) { 1222 my $player = lookupPlayer($s_addr, $userid, $uniqueid); 1223 if ($player) { 1224 # The only time team should go /back/ to unassigned (“”) is on mapchange 1225 # (which is already handled in the ChangeMap handler) 1226 # So ignore when team is blank () from lazy log lines 1227 if ($team ne “” && $player->{team} ne $team) { 1228 &doEvent_TeamSelection( 1229 $userid, 1230 $uniqueid, 1231 $team 1232 ); 1233 } 1234 if ($role ne “” && $role ne $player->{role}) { 1235 &doEvent_RoleSelection( 1236 $player->{“userid”}, 1237 $player->{“uniqueid”}, 1238 $role 1239 ); 1240 } 1241 1242 $player->updateTimestamp(); 1243 } 1244 } else { 1245 if ($userid != 0) { 1246 if ($create_player > 0) { 1247 my $preIpAddr = “”; 1248 if ($g_preconnect->{“$s_addr/$userid/$name”}) { 1249 $preIpAddr = $g_preconnect->{“$s_addr/$userid/$name”}->{“ipaddress”}; 1250 } 1251 # Add the player to our hash of player objects 1252 $g_servers{$s_addr}->{“srv_players”}->{“$userid/$uniqueid”} = new HLstats_Player( 1253 server => $s_addr, 1254 server_id => $g_servers{$s_addr}->{id}, 1255 userid => $userid, 1256 uniqueid => $uniqueid, 1257 plain_uniqueid => $plainuniqueid, 1258 game => $g_servers{$s_addr}->{game}, 1259 name => $name, 1260 team => $team, 1261 role => $role, 1262 is_bot => $bot, 1263 display_events => $g_servers{$s_addr}->{default_display_events}, 1264 address => (($preIpAddr ne “”) ? $preIpAddr : $ipAddr) 1265 ); 1266 1267 if ($preIpAddr ne “”) { 1268 &printEvent(“SERVER”, “LATE CONNECT [$name/$userid] – steam userid validated”); 1269 &doEvent_Connect($userid, $uniqueid, $preIpAddr); 1270 delete($g_preconnect->{“$s_addr/$userid/$name”}); 1271 } 1272 # Increment number of players on server 1273 $g_servers{$s_addr}->updatePlayerCount(); 1274 } 1275 } elsif (($g_mode eq “LAN”) && (defined($g_lan_noplayerinfo{“$s_addr/$userid/$name”}))) { 1276 if ((!$haveplayer) && ($uniqueid ne “UNKNOWN”) && ($create_player > 0)) { 1277 $g_servers{$s_addr}->{srv_players}->{“$userid/$uniqueid”} = new HLstats_Player( 1278 server => $s_addr, 1279 server_id => $g_servers{$s_addr}->{id}, 1280 userid => $userid, 1281 uniqueid => $uniqueid, 1282 plain_uniqueid => $plainuniqueid, 1283 game => $g_servers{$s_addr}->{game}, 1284 name => $name, 1285 team => $team, 1286 role => $role, 1287 is_bot => $bot 1288 ); 1289 delete($g_lan_noplayerinfo{“$s_addr/$userid/$name”}); 1290 # Increment number of players on server 1291 1292 $g_servers{$s_addr}->updatePlayerCount(); 1293 } 1294 } else { 1295 &printNotice(“No player object available for player “$name” “); 1296 } 1297 } 1298 1299 return { 1300 name => $name, 1301 userid => $userid, 1302 uniqueid => $uniqueid, 1303 team => $team, 1304 is_bot => $bot 1305 }; 1306 } elsif ($player =~ /^(.+)<([^]+)>$/) { 1307 my $name = $1; 1308 my $uniqueid = $2; 1309 my $bot = 0; 1310 1311 if (&botidcheck($uniqueid)) { 1312 $md5 = Digest::MD5->new; 1313 $md5->add($ev_daemontime); 1314 $md5->add($s_addr); 1315 $uniqueid = “BOT:” . $md5->hexdigest; 1316 $bot = 1; 1317 } 1318 return { 1319 name => $name, 1320 uniqueid => $uniqueid, 1321 is_bot => $bot 1322 }; 1323 } elsif ($player =~ /^<([^]+)>$/) { 1324 my $uniqueid = $1; 1325 my $bot = 0; 1326 if (&botidcheck($uniqueid)) { 1327 $md5 = Digest::MD5->new; 1328 $md5->add($ev_daemontime); 1329 $md5->add($s_addr); 1330 $uniqueid = “BOT:” . $md5->hexdigest; 1331 $bot = 1; 1332 } 1333 return { 1334 uniqueid => $uniqueid, 1335 is_bot => $bot 1336 }; 1337 } else { 1338 return 0; 1339 } 1340} 1341 1342 1343# 1344# hash getProperties (string propstring) 1345# 1346# Parse (key “value”) properties into a hash. 1347# 1348 1349sub getProperties 1350{ 1351 my ($propstring) = @_; 1352 my %properties; 1353 my $dods_flag = 0; 1354 1355 while ($propstring =~ s/^s*((S+)(?:(?: “(.+?)”)|(?: ([^)]+)))?)//) { 1356 my $key = $1; 1357 if (defined($2)) { 1358 if ($key eq “player”) { 1359 if ($dods_flag == 1) { 1360 $key = “player_a”; 1361 $dods_flag++; 1362 } elsif ($dods_flag == 2) { 1363 $key = “player_b”; 1364 } 1365 } 1366 $properties{$key} = $2; 1367 } elsif (defined($3)) { 1368 $properties{$key} = $3; 1369 } else { 1370 $properties{$key} = 1; # boolean property 1371 } 1372 if ($key eq “flagindex”) { 1373 $dods_flag++; 1374 } 1375 } 1376 1377 return %properties; 1378} 1379 1380 1381# 1382# boolean like (string subject, string compare) 1383# 1384# Returns true if ‘subject’ equals ‘compare’ with optional whitespace. 1385# 1386 1387sub like 1388{ 1389 my ($subject, $compare) = @_; 1390 1391 if ($subject =~ /^s*Q$compareEs*$/) { 1392 return 1; 1393 } else { 1394 return 0; 1395 } 1396} 1397 1398 1399# 1400# boolean botidcheck (string uniqueid) 1401# 1402# Returns true if ‘uniqueid’ is that of a bot. 1403# 1404 1405sub botidcheck 1406{ 1407 # needs cleaned up 1408 # added /^00000000:d+:0$/ check for “whichbot” 1409 my ($uniqueid) = @_; 1410 if ($uniqueid eq “BOT” || $uniqueid eq “0” || $uniqueid =~ /^00000000:d+:0$/) { 1411 return 1 1412 } 1413 return 0; 1414} 1415 1416sub isTrackableTeam 1417{ 1418 my ($team) = @_; 1419 #if ($team =~ /spectator/i || $team =~ /unassigned/i || $team eq “”) { 1420 if ($team =~ /spectator/i || $team eq “”) { 1421 return 0; 1422 } 1423 return 1; 1424} 1425 1426sub reloadConfiguration 1427{ 1428 &flushAll; 1429 &readDatabaseConfig; 1430} 1431 1432 1433sub flushAll 1434{ 1435 # we only need to flush events if we’re about to shut down. they are unaffected by server/player deletion 1436 my ($flushevents) = @_; 1437 if ($flushevents) 1438 { 1439 while ( my ($table, $colsref) = each(%g_eventTables) ) 1440 { 1441 flushEventTable($table); 1442 } 1443 } 1444 1445 while( my($se, $server) = each(%g_servers)) 1446 { 1447 while ( my($pl, $player) = each(%{$server->{“srv_players”}}) ) 1448 { 1449 if ($player) 1450 { 1451 $player->playerCleanup(); 1452 } 1453 } 1454 $server->flushDB(); 1455 } 1456} 1457 1458 1459## 1460## MAIN 1461## 1462 1463# Options 1464 1465$opt_help = 0; 1466$opt_version = 0; 1467 1468$db_host = “localhost”; 1469$db_user = “”; 1470$db_pass = “”; 1471$db_name = “hlstats”; 1472$db_lowpriority = 1; 1473 1474$s_ip = “”; 1475$s_port = “27500”; 1476 1477$g_mailto = “”; 1478$g_mailpath = “/bin/mail”; 1479$g_mode = “Normal”; 1480$g_deletedays = 5; 1481$g_requiremap = 0; 1482$g_debug = 1; 1483$g_nodebug = 0; 1484$g_rcon = 1; 1485$g_rcon_ignoreself = 0; 1486$g_rcon_record = 1; 1487$g_stdin = 0; 1488$g_server_ip = “”; 1489$g_server_port = 27015; 1490$g_timestamp = 0; 1491$g_cpanelhack = 0; 1492$g_event_queue_size = 10; 1493$g_dns_resolveip = 1; 1494$g_dns_timeout = 5; 1495$g_skill_maxchange = 100; 1496$g_skill_minchange = 2; 1497$g_skill_ratio_cap = 0; 1498$g_geoip_binary = 0; 1499$g_player_minkills = 50; 1500$g_onlyconfig_servers = 1; 1501$g_track_stats_trend = 0; 1502%g_lan_noplayerinfo = (); 1503%g_preconnect = (); 1504$g_global_banning = 0; 1505$g_log_chat = 0; 1506$g_log_chat_admins = 0; 1507$g_global_chat = 0; 1508$g_ranktype = “skill”; 1509$g_gi = undef; 1510 1511my %dysweaponcodes = ( 1512 “1” => “Light Katana”, 1513 “2” => “Medium Katana”, 1514 “3” => “Fatman Fist”, 1515 “4” => “Machine Pistol”, 1516 “5” => “Shotgun”, 1517 “6” => “Laser Rifle”, 1518 “7” => “BoltGun”, 1519 “8” => “SmartLock Pistols”, 1520 “9” => “Assault Rifle”, 1521 “10” => “Grenade Launcher”, 1522 “11” => “MK-808 Rifle”, 1523 “12” => “Tesla Rifle”, 1524 “13” => “Rocket Launcher”, 1525 “14” => “Minigun”, 1526 “15” => “Ion Cannon”, 1527 “16” => “Basilisk”, 1528 “17” => “Frag Grenade”, 1529 “18” => “EMP Grenade”, 1530 “19” => “Spider Grenade”, 1531 “22” => “Cortex Bomb” 1532); 1533 1534# Usage message 1535 1536$usage = <fetchrow_array) { 1601 $g_config_servers{$addr} = (); 1602 my $serverConfig = &doQuery(“SELECT parameter,value FROM hlstats_Servers_Config WHERE serverId=$serverId”); 1603 while ( my($p,$v) = $serverConfig->fetchrow_array) { 1604 $g_config_servers{$addr}{$p} = $v; 1605 } 1606 } 1607 $srv_id->finish; 1608 # hlxce: read the global settings from the database! 1609 my $gsettings = &doQuery(“SELECT keyname,value FROM hlstats_Options WHERE opttype fetchrow_array) { 1611 if ($g_debug > 1) { 1612 print “Config parameter ‘$p’ = ‘$v’n”; 1613 } 1614 $tmp = “$”.$directives_mysql{$p}.” = ‘$v'”; 1615 #print ” -> setting “.$tmp.”n”; 1616 eval $tmp; 1617 } 1618 $gsettings->finish; 1619 # setting defaults 1620 1621 &printEvent(“DAEMON”, “Proxy_Key DISABLED”, 1) if ($proxy_key eq “”); 1622 while (my($addr, $server) = each(%g_config_servers)) { 1623 1624 if (!defined($g_config_servers{$addr}{“MinPlayers”})) { 1625 $g_config_servers{$addr}{“MinPlayers”} = 6; 1626 } 1627 if (!defined($g_config_servers{$addr}{“DisplayResultsInBrowser”})) { 1628 $g_config_servers{$addr}{“DisplayResultsInBrowser”} = 0; 1629 } 1630 if (!defined($g_config_servers{$addr}{“BroadCastEvents”})) { 1631 $g_config_servers{$addr}{“BroadCastEvents”} = 0; 1632 } 1633 if (!defined($g_config_servers{$addr}{“BroadCastPlayerActions”})) { 1634 $g_config_servers{$addr}{“BroadCastPlayerActions”} = 0; 1635 } 1636 if (!defined($g_config_servers{$addr}{“BroadCastEventsCommand”})) { 1637 $g_config_servers{$addr}{“BroadCastEventsCommand”} = “say”; 1638 } 1639 if (!defined($g_config_servers{$addr}{“BroadCastEventsCommandAnnounce”})) { 1640 $g_config_servers{$addr}{“BroadCastEventsCommandAnnounce”} = “say”; 1641 } 1642 if (!defined($g_config_servers{$addr}{“PlayerEvents”})) { 1643 $g_config_servers{$addr}{“PlayerEvents”} = 1; 1644 } 1645 if (!defined($g_config_servers{$addr}{“PlayerEventsCommand”})) { 1646 $g_config_servers{$addr}{“PlayerEventsCommand”} = “say”; 1647 } 1648 if (!defined($g_config_servers{$addr}{“PlayerEventsCommandOSD”})) { 1649 $g_config_servers{$addr}{“PlayerEventsCommandOSD”} = “”; 1650 } 1651 if (!defined($g_config_servers{$addr}{“PlayerEventsCommandHint”})) { 1652 $g_config_servers{$addr}{“PlayerEventsCommandHint”} = “”; 1653 } 1654 if (!defined($g_config_servers{$addr}{“PlayerEventsAdminCommand”})) { 1655 $g_config_servers{$addr}{“PlayerEventsAdminCommand”} = “”; 1656 } 1657 if (!defined($g_config_servers{$addr}{“ShowStats”})) { 1658 $g_config_servers{$addr}{“ShowStats”} = 1; 1659 } 1660 if (!defined($g_config_servers{$addr}{“AutoTeamBalance”})) { 1661 $g_config_servers{$addr}{“AutoTeamBalance”} = 0; 1662 } 1663 if (!defined($g_config_servers{$addr}{“AutoBanRetry”})) { 1664 $g_config_servers{$addr}{“AutoBanRetry”} = 0; 1665 } 1666 if (!defined($g_config_servers{$addr}{“TrackServerLoad”})) { 1667 $g_config_servers{$addr}{“TrackServerLoad”} = 0; 1668 } 1669 if (!defined($g_config_servers{$addr}{“MinimumPlayersRank”})) { 1670 $g_config_servers{$addr}{“MinimumPlayersRank”} = 0; 1671 } 1672 if (!defined($g_config_servers{$addr}{“Admins”})) { 1673 $g_config_servers{$addr}{“Admins”} = “”; 1674 } 1675 if (!defined($g_config_servers{$addr}{“SwitchAdmins”})) { 1676 $g_config_servers{$addr}{“SwitchAdmins”} = 0; 1677 } 1678 if (!defined($g_config_servers{$addr}{“IgnoreBots”})) { 1679 $g_config_servers{$addr}{“IgnoreBots”} = 1; 1680 } 1681 if (!defined($g_config_servers{$addr}{“SkillMode”})) { 1682 $g_config_servers{$addr}{“SkillMode”} = 0; 1683 } 1684 if (!defined($g_config_servers{$addr}{“GameType”})) { 1685 $g_config_servers{$addr}{“GameType”} = 0; 1686 } 1687 if (!defined($g_config_servers{$addr}{“BonusRoundTime”})) { 1688 $g_config_servers{$addr}{“BonusRoundTime”} = 0; 1689 } 1690 if (!defined($g_config_servers{$addr}{“BonusRoundIgnore”})) { 1691 $g_config_servers{$addr}{“BonusRoundIgnore”} = 0; 1692 } 1693 if (!defined($g_config_servers{$addr}{“Mod”})) { 1694 $g_config_servers{$addr}{“Mod”} = “”; 1695 } 1696 if (!defined($g_config_servers{$addr}{“EnablePublicCommands”})) { 1697 $g_config_servers{$addr}{“EnablePublicCommands”} = 1; 1698 } 1699 if (!defined($g_config_servers{$addr}{“ConnectAnnounce”})) { 1700 $g_config_servers{$addr}{“ConnectAnnounce”} = 1; 1701 } 1702 if (!defined($g_config_servers{$addr}{“UpdateHostname”})) { 1703 $g_config_servers{$addr}{“UpdateHostname”} = 0; 1704 } 1705 if (!defined($g_config_servers{$addr}{“DefaultDisplayEvents”})) { 1706 $g_config_servers{$addr}{“DefaultDisplayEvents”} = 1; 1707 } 1708 } 1709 1710 &printEvent(“CONFIG”, “I have found the following server configs in database:”, 1); 1711 while (my($addr, $server) = each(%g_config_servers)) { 1712 &printEvent(“S_CONFIG”, $addr, 1); 1713 } 1714 1715 my $geotell = ((!defined($g_gi)) ? -1 : tell $g_gi{fh}); 1716 1717 if ($g_geoip_binary > 0 && $geotell == -1) { 1718 my $geoipfile = “$opt_libdir/GeoLiteCity/GeoLiteCity.dat”; 1719 if (-r $geoipfile) { 1720 eval “use Geo::IP::PurePerl”; my $hasGeoIP = $@ ? 0 : 1; 1721 if ($hasGeoIP) { 1722 $g_gi = Geo::IP::PurePerl->open($geoipfile, “GEOIP_STANDARD”); 1723 } else { 1724 &printEvent(“ERROR”, “GeoIP method set to binary file lookup but Geo::IP::PurePerl module NOT FOUND”, 1); 1725 $g_gi = undef; 1726 } 1727 } else { 1728 &printEvent(“ERROR”, “GeoIP method set to binary file lookup but $geoipfile NOT FOUND”, 1); 1729 $g_gi = undef; 1730 } 1731 } elsif ($g_geoip_binary == 0 && $geotell > -1) { 1732 close($g_gi{fh}); 1733 $g_gi = undef; 1734 } 1735} 1736 1737# Read Config File 1738 1739if ($opt_configfile && -r $opt_configfile) { 1740 $conf = ConfigReaderSimple->new($opt_configfile); 1741 $conf->parse(); 1742 %directives = ( 1743 “DBHost”, “db_host”, 1744 “DBUsername”, “db_user”, 1745 “DBPassword”, “db_pass”, 1746 “DBName”, “db_name”, 1747 “DBLowPriority”, “db_lowpriority”, 1748 “BindIP”, “s_ip”, 1749 “Port”, “s_port”, 1750 “DebugLevel”, “g_debug”, 1751 “CpanelHack”, “g_cpanelhack”, 1752 “EventQueueSize”, “g_event_queue_size” 1753 ); 1754 1755 %directives_mysql = ( 1756 “version”, “g_version”, 1757 “MailTo”, “g_mailto”, 1758 “MailPath”, “g_mailpath”, 1759 “Mode”, “g_mode”, 1760 “DeleteDays”, “g_deletedays”, 1761 “UseTimestamp”, “g_timestamp”, 1762 “DNSResolveIP”, “g_dns_resolveip”, 1763 “DNSTimeout”, “g_dns_timeout”, 1764 “RconIgnoreSelf”, “g_rcon_ignoreself”, 1765 “Rcon”, “g_rcon”, 1766 “RconRecord”, “g_rcon_record”, 1767 “MinPlayers”, “g_minplayers”, 1768 “SkillMaxChange”, “g_skill_maxchange”, 1769 “SkillMinChange”, “g_skill_minchange”, 1770 “PlayerMinKills”, “g_player_minkills”, 1771 “AllowOnlyConfigServers”, “g_onlyconfig_servers”, 1772 “TrackStatsTrend”, “g_track_stats_trend”, 1773 “GlobalBanning”, “g_global_banning”, 1774 “LogChat”, “g_log_chat”, 1775 “LogChatAdmins”, “g_log_chat_admins”, 1776 “GlobalChat”, “g_global_chat”, 1777 “SkillRatioCap”, “g_skill_ratio_cap”, 1778 “rankingtype”, “g_ranktype”, 1779 “UseGeoIPBinary”, “g_geoip_binary”, 1780 “Proxy_Key”, “proxy_key” 1781 ); 1782 1783# “Servers”, “g_config_servers” 1784 &doConf($conf, %directives); 1785 1786} else { 1787 print “– Warning: unable to open configuration file ‘$opt_configfile’n”; 1788} 1789 1790# Read Command Line Arguments 1791 1792%copts = (); 1793 1794GetOptions( 1795 “help|h” => $copts{opt_help}, 1796 “version|v” => $copts{opt_version}, 1797 “debug|d+” => $copts{g_debug}, 1798 “nodebug|n+” => $copts{g_nodebug}, 1799 “mode|m=s” => $copts{g_mode}, 1800 “configfile|c=s” => $copts{configfile}, 1801 “db-host=s” => $copts{db_host}, 1802 “db-name=s” => $copts{db_name}, 1803 “db-password=s” => $copts{db_pass}, 1804 “db-username=s” => $copts{db_user}, 1805 “dns-resolveip!” => $copts{g_dns_resolveip}, 1806 “dns-timeout=i” => $copts{g_…

Large files files are truncated, but you can click here to view the full file

Source

×