2015-03-08 17:20:10 -04:00
using System ;
using System.Collections.Generic ;
2015-03-13 19:40:16 -04:00
using System.Collections ;
2015-03-08 17:20:10 -04:00
using System.Text ;
using System.Threading ; //SLEEP
using System.IO ;
namespace IW4MAdmin
{
class Server
{
const int FLOOD_TIMEOUT = 300 ;
public Server ( string address , int port , string password )
{
IP = address ;
Port = port ;
rcon_pass = password ;
clientnum = 0 ;
RCON = new RCON ( this ) ;
2015-03-09 00:28:57 -04:00
logFile = new file ( "admin_" + port + ".log" , true ) ;
2015-03-13 19:40:16 -04:00
#if DEBUG
Log = new Log ( logFile , Log . Level . Debug ) ;
#else
2015-03-08 17:20:10 -04:00
Log = new Log ( logFile , Log . Level . Production ) ;
2015-03-13 19:40:16 -04:00
#endif
2015-03-08 17:20:10 -04:00
players = new List < Player > ( new Player [ 18 ] ) ;
2015-03-13 19:40:16 -04:00
clientDB = new ClientsDB ( "clients.rm" ) ;
statDB = new StatsDB ( "stats_" + port + ".rm" ) ;
aliasDB = new AliasesDB ( "aliases.rm" ) ;
Bans = clientDB . getBans ( ) ;
owner = clientDB . getOwner ( ) ;
2015-03-08 17:20:10 -04:00
events = new Queue < Event > ( ) ;
2015-03-10 16:45:20 -04:00
HB = new Heartbeat ( this ) ;
2015-03-13 19:40:16 -04:00
Macros = new Dictionary < String , Object > ( ) ;
2015-03-08 17:20:10 -04:00
nextMessage = 0 ;
initCommands ( ) ;
2015-03-13 19:40:16 -04:00
initMacros ( ) ;
2015-03-08 17:20:10 -04:00
initMessages ( ) ;
initMaps ( ) ;
initRules ( ) ;
}
//Returns the current server name -- *STRING*
public String getName ( )
{
return hostname ;
}
2015-03-10 16:45:20 -04:00
public String getMap ( )
{
return mapname ;
}
2015-03-08 17:20:10 -04:00
//Returns current server IP set by `net_ip` -- *STRING*
public String getIP ( )
{
return IP ;
}
//Returns current server port set by `net_port` -- *INT*
public int getPort ( )
{
return Port ;
}
//Returns number of active clients on server -- *INT*
public int getNumPlayers ( )
{
return clientnum ;
}
//Returns the list of commands
public List < Command > getCommands ( )
{
return commands ;
}
2015-03-09 00:28:57 -04:00
//Returns list of all current players
2015-03-08 17:20:10 -04:00
public List < Player > getPlayers ( )
{
return players ;
}
2015-03-10 16:45:20 -04:00
public int getClientNum ( )
{
return clientnum ;
}
2015-03-11 21:25:14 -04:00
public int getMaxClients ( )
{
return maxClients ;
}
2015-03-09 00:28:57 -04:00
//Returns list of all active bans (loaded at runtime)
2015-03-08 17:20:10 -04:00
public List < Ban > getBans ( )
{
return Bans ;
}
2015-03-14 12:42:36 -04:00
public void threadedConnect ( Player P , Player NewPlayer )
{
bool updated = false ;
while ( ! updated )
{
try
{
P . updateIP ( IPS [ P . getID ( ) ] . Trim ( ) ) ;
updated = true ;
Log . Write ( "Sucessfully updated " + NewPlayer . getName ( ) + "'s IP to " + P . getIP ( ) , Log . Level . Debug ) ;
}
catch
{
//Log.Write("Looks like the connecting player doesn't have an IP location assigned yet. Let's wait for next poll", Log.Level.Debug);
Utilities . Wait ( 1 ) ;
}
}
if ( NewPlayer . Alias = = null )
{
aliasDB . addPlayer ( new Aliases ( NewPlayer . getDBID ( ) , NewPlayer . getName ( ) , P . getIP ( ) ) ) ;
}
if ( P . getName ( ) ! = NewPlayer . getName ( ) )
{
NewPlayer . updateName ( P . getName ( ) ) ;
NewPlayer . Alias . addName ( P . getName ( ) ) ;
aliasDB . updatePlayer ( NewPlayer . Alias ) ;
}
if ( P . getIP ( ) ! = NewPlayer . getIP ( ) )
{
NewPlayer . updateIP ( P . getIP ( ) ) ;
NewPlayer . Alias . addIP ( P . getIP ( ) ) ;
aliasDB . updatePlayer ( NewPlayer . Alias ) ;
}
clientDB . updatePlayer ( NewPlayer ) ;
Ban B = isBanned ( NewPlayer ) ;
if ( B ! = null | | NewPlayer . getLevel ( ) = = Player . Permission . Banned )
{
Log . Write ( "Banned client " + P . getName ( ) + " trying to connect..." , Log . Level . Debug ) ;
string Reason = String . Empty ;
if ( B ! = null )
Reason = B . getReason ( ) ;
else
Reason = P . LastOffense ;
String Message = "^1Player Kicked: ^7Previously Banned for ^5" + Reason ;
P . Kick ( Message ) ;
}
players [ NewPlayer . getClientNum ( ) ] = null ;
players [ NewPlayer . getClientNum ( ) ] = NewPlayer ;
}
2015-03-08 17:20:10 -04:00
//Add player object p to `players` list
public bool addPlayer ( Player P )
{
2015-03-14 12:42:36 -04:00
#if DEBUG = = false
2015-03-08 17:20:10 -04:00
try
2015-03-14 12:42:36 -04:00
#endif
2015-03-08 17:20:10 -04:00
{
2015-03-13 19:40:16 -04:00
if ( clientDB . getPlayer ( P . getID ( ) , P . getClientNum ( ) ) = = null )
2015-03-08 17:20:10 -04:00
{
2015-03-13 19:40:16 -04:00
clientDB . addPlayer ( P ) ;
Player New = clientDB . getPlayer ( P . getID ( ) , P . getClientNum ( ) ) ;
statDB . addPlayer ( New ) ;
aliasDB . addPlayer ( new Aliases ( New . getDBID ( ) , New . getName ( ) , New . getIP ( ) ) ) ;
2015-03-08 17:20:10 -04:00
}
2015-03-13 19:40:16 -04:00
//messy way to prevent loss of last event
Player NewPlayer = clientDB . getPlayer ( P . getID ( ) , P . getClientNum ( ) ) ;
NewPlayer . stats = statDB . getStats ( NewPlayer . getDBID ( ) ) ;
2015-03-14 12:42:36 -04:00
NewPlayer . Alias = aliasDB . getPlayer ( NewPlayer . getDBID ( ) ) ;
if ( NewPlayer . stats = = null ) //For safety
2015-03-09 21:28:37 -04:00
{
2015-03-13 19:40:16 -04:00
statDB . addPlayer ( NewPlayer ) ;
NewPlayer . stats = statDB . getStats ( NewPlayer . getDBID ( ) ) ;
2015-03-09 21:28:37 -04:00
}
2015-03-10 17:56:01 -04:00
2015-03-14 12:42:36 -04:00
if ( P . lastEvent = = null )
NewPlayer . lastEvent = new Event ( Event . GType . Say , null , NewPlayer , null , this ) ; // this is messy but its throwing an error when they've started it too late
else
NewPlayer . lastEvent = P . lastEvent ;
2015-03-08 17:20:10 -04:00
2015-03-14 12:42:36 -04:00
if ( players [ NewPlayer . getClientNum ( ) ] = = null )
2015-03-08 17:20:10 -04:00
{
2015-03-14 12:42:36 -04:00
Thread connectThread = new Thread ( ( ) = > threadedConnect ( P , NewPlayer ) ) ;
connectThread . Start ( ) ; // We don't want events to get behind
2015-03-08 17:20:10 -04:00
2015-03-14 12:42:36 -04:00
NewPlayer . Tell ( "Welcome ^5" + NewPlayer . getName ( ) + " ^7this is your ^5" + Utilities . timesConnected ( NewPlayer . getConnections ( ) ) + " ^7time connecting!" ) ;
2015-03-13 19:40:16 -04:00
Log . Write ( "Client " + NewPlayer . getName ( ) + " connecting..." , Log . Level . Debug ) ;
2015-03-14 12:42:36 -04:00
clientnum + + ;
}
2015-03-08 17:20:10 -04:00
return true ;
}
2015-03-14 12:42:36 -04:00
#if DEBUG = = false
2015-03-08 17:20:10 -04:00
catch ( Exception E )
{
2015-03-09 16:11:09 -04:00
Log . Write ( "Unable to add player " + P . getName ( ) + " - " + E . Message , Log . Level . Debug ) ;
2015-03-08 17:20:10 -04:00
return false ;
}
2015-03-14 12:42:36 -04:00
#endif
2015-03-08 17:20:10 -04:00
}
//Remove player by CLIENT NUMBER
public bool removePlayer ( int cNum )
{
2015-03-13 19:40:16 -04:00
Log . Write ( "Updating stats for " + players [ cNum ] . getName ( ) , Log . Level . Debug ) ;
statDB . updatePlayer ( players [ cNum ] ) ;
2015-03-09 21:28:37 -04:00
Log . Write ( "Client at " + cNum + " disconnecting..." , Log . Level . Debug ) ;
2015-03-08 17:20:10 -04:00
players [ cNum ] = null ;
clientnum - - ;
return true ;
}
2015-03-09 00:28:57 -04:00
//Get a client from players list by by log line. If create = true, it will return a new player object
2015-03-08 17:20:10 -04:00
public Player clientFromLine ( String [ ] line , int name_pos , bool create )
{
string Name = line [ name_pos ] . ToString ( ) . Trim ( ) ;
if ( create )
{
Player C = new Player ( Name , line [ 1 ] . ToString ( ) , Convert . ToInt16 ( line [ 2 ] ) , 0 ) ;
return C ;
}
else
{
foreach ( Player P in players )
{
if ( P = = null )
continue ;
if ( line [ 1 ] . Trim ( ) = = P . getID ( ) )
return P ;
}
Log . Write ( "Could not find player but player is in server. Lets try to manually add (looks like you didn't start me on an empty server)" , Log . Level . All ) ;
2015-03-14 12:42:36 -04:00
players [ Convert . ToInt16 ( line [ 2 ] ) ] = null ;
addPlayer ( new Player ( Name , line [ 1 ] . ToString ( ) . Trim ( ) , Convert . ToInt16 ( line [ 2 ] ) , 0 ) ) ;
2015-03-08 17:20:10 -04:00
return players [ Convert . ToInt16 ( line [ 2 ] ) ] ;
}
}
2015-03-09 00:28:57 -04:00
//Should be client from Name ( returns client in players list by name )
2015-03-08 17:20:10 -04:00
public Player clientFromLine ( String Name )
{
foreach ( Player P in players )
{
if ( P = = null )
continue ;
if ( P . getName ( ) . ToLower ( ) . Contains ( Name . ToLower ( ) ) )
return P ;
}
return null ;
}
public Ban isBanned ( Player C )
{
foreach ( Ban B in Bans )
{
2015-03-13 19:40:16 -04:00
2015-03-08 17:20:10 -04:00
if ( B . getID ( ) = = C . getID ( ) )
return B ;
2015-03-13 19:40:16 -04:00
if ( B . getIP ( ) = = null )
continue ;
if ( C . Alias . getIPS ( ) . Find ( f = > f . Contains ( B . getIP ( ) ) ) ! = null )
return B ;
if ( C . getIP ( ) = = B . getIP ( ) )
return B ;
2015-03-08 17:20:10 -04:00
}
return null ;
}
2015-03-13 19:40:16 -04:00
public String getPlayerIP ( String GUID )
{
Dictionary < string , string > dict ;
int count = 0 ;
do
{
//because rcon can be weird
dict = Utilities . IPFromStatus ( RCON . addRCON ( "status" ) ) ;
count + + ;
} while ( dict . Count < clientnum | | count < 5 ) ;
return dict [ GUID ] ;
}
2015-03-08 17:20:10 -04:00
public Command processCommand ( Event E , Command C )
{
E . Data = Utilities . removeWords ( E . Data , 1 ) ;
String [ ] Args = E . Data . Trim ( ) . Split ( ' ' ) ;
if ( Args . Length < ( C . getNumArgs ( ) ) )
{
E . Origin . Tell ( "Not enough arguments supplied!" ) ;
return null ;
}
if ( E . Origin . getLevel ( ) < C . getNeededPerm ( ) )
{
E . Origin . Tell ( "You do not have access to that command!" ) ;
return null ;
}
if ( C . needsTarget ( ) )
{
int cNum = - 1 ;
int . TryParse ( Args [ 0 ] , out cNum ) ;
2015-03-09 21:28:37 -04:00
if ( Args [ 0 ] = = String . Empty )
return C ;
2015-03-08 17:20:10 -04:00
if ( Args [ 0 ] [ 0 ] = = '@' )
{
int dbID = - 1 ;
int . TryParse ( Args [ 0 ] . Substring ( 1 , Args [ 0 ] . Length - 1 ) , out dbID ) ;
2015-03-13 19:40:16 -04:00
Player found = E . Owner . clientDB . getPlayer ( dbID ) ;
2015-03-08 17:20:10 -04:00
if ( found ! = null )
E . Target = found ;
}
else if ( Args [ 0 ] . Length < 3 & & cNum > - 1 & & cNum < 18 )
{
if ( players [ cNum ] ! = null )
E . Target = players [ cNum ] ;
}
else
E . Target = clientFromLine ( Args [ 0 ] ) ;
if ( E . Target = = null )
{
E . Origin . Tell ( "Unable to find specified player." ) ;
return null ;
}
}
return C ;
}
private void addEvent ( Event E )
{
events . Enqueue ( E ) ;
}
private void manageEventQueue ( )
{
2015-03-14 12:42:36 -04:00
while ( isRunning )
2015-03-08 17:20:10 -04:00
{
if ( events . Count > 0 )
{
processEvent ( events . Peek ( ) ) ;
events . Dequeue ( ) ;
}
Utilities . Wait ( 0.1 ) ;
}
}
//Starts the monitoring process
public void Monitor ( )
{
2015-03-14 12:42:36 -04:00
isRunning = true ;
2015-03-13 19:40:16 -04:00
//Handles new rcon requests in a fashionable manner
Thread RCONQueue = new Thread ( new ThreadStart ( RCON . ManageRCONQueue ) ) ;
RCONQueue . Start ( ) ;
2015-03-08 17:20:10 -04:00
if ( ! intializeBasics ( ) )
{
2015-03-13 19:40:16 -04:00
Log . Write ( "Stopping " + Port + " due to uncorrectable errors (check log)" + logPath , Log . Level . Production ) ;
2015-03-14 12:42:36 -04:00
isRunning = false ;
Utilities . Wait ( 10 ) ;
2015-03-09 16:11:09 -04:00
return ;
2015-03-08 17:20:10 -04:00
}
2015-03-14 12:42:36 -04:00
Thread statusUpdate = new Thread ( new ThreadStart ( pollServer ) ) ;
statusUpdate . Start ( ) ;
2015-03-08 17:20:10 -04:00
//Handles new events in a fashionable manner
Thread eventQueue = new Thread ( new ThreadStart ( manageEventQueue ) ) ;
eventQueue . Start ( ) ;
2015-03-13 19:40:16 -04:00
int timesFailed = 0 ;
2015-03-08 17:20:10 -04:00
long l_size = - 1 ;
2015-03-14 12:42:36 -04:00
bool checkedForOutdate = false ;
2015-03-08 17:20:10 -04:00
String [ ] lines = new String [ 8 ] ;
String [ ] oldLines = new String [ 8 ] ;
DateTime start = DateTime . Now ;
2015-03-10 17:56:01 -04:00
Utilities . Wait ( 1 ) ;
2015-03-14 12:42:36 -04:00
#if DEBUG = = false
2015-03-10 17:56:01 -04:00
Broadcast ( "IW4M Admin is now ^2ONLINE" ) ;
2015-03-14 12:42:36 -04:00
#endif
2015-03-08 17:20:10 -04:00
while ( errors < = 5 )
{
2015-03-14 12:42:36 -04:00
#if DEBUG = = false
try
#endif
2015-03-08 17:20:10 -04:00
{
lastMessage = DateTime . Now - start ;
if ( lastMessage . TotalSeconds > messageTime & & messages . Count > 0 )
{
2015-03-13 19:40:16 -04:00
2015-03-14 12:42:36 -04:00
if ( RCON . addRCON ( "sv_online" ) = = null )
2015-03-13 19:40:16 -04:00
{
timesFailed + + ;
Log . Write ( "Server appears to be offline - " + timesFailed , Log . Level . Debug ) ;
}
else
timesFailed = 0 ;
Thread . Sleep ( 300 ) ;
2015-03-14 12:42:36 -04:00
initMacros ( ) ; // somethings dynamically change so we have to re-init the dictionary
2015-03-13 19:40:16 -04:00
Broadcast ( Utilities . processMacro ( Macros , messages [ nextMessage ] ) ) ;
2015-03-08 17:20:10 -04:00
if ( nextMessage = = ( messages . Count - 1 ) )
nextMessage = 0 ;
else
nextMessage + + ;
start = DateTime . Now ;
2015-03-13 19:40:16 -04:00
if ( timesFailed < = 3 )
HB . Send ( ) ;
2015-03-14 12:42:36 -04:00
String checkVer = new Connection ( "http://raidmax.org/IW4M/Admin/version.php" ) . Read ( ) ;
double checkVerNum ;
double . TryParse ( checkVer , out checkVerNum ) ;
if ( checkVerNum ! = Program . Version & & checkVerNum ! = 0 & & ! checkedForOutdate )
{
messages . Add ( "^5IW4M Admin ^7is outdated. Please ^5update ^7to version " + checkVerNum ) ;
checkedForOutdate = true ;
}
2015-03-08 17:20:10 -04:00
}
if ( l_size ! = logFile . getSize ( ) )
{
lines = logFile . Tail ( 8 ) ;
if ( lines ! = oldLines )
{
l_size = logFile . getSize ( ) ;
int end ;
if ( lines . Length = = oldLines . Length )
end = lines . Length - 1 ;
else
end = Math . Abs ( ( lines . Length - oldLines . Length ) ) - 1 ;
for ( int count = 0 ; count < lines . Length ; count + + )
{
if ( lines . Length < 1 & & oldLines . Length < 1 )
continue ;
if ( lines [ count ] = = oldLines [ oldLines . Length - 1 ] )
continue ;
if ( lines [ count ] . Length < 10 ) //Not a needed line
continue ;
else
{
string [ ] game_event = lines [ count ] . Split ( ';' ) ;
Event event_ = Event . requestEvent ( game_event , this ) ;
if ( event_ ! = null )
{
if ( event_ . Origin = = null )
event_ . Origin = new Player ( "WORLD" , "-1" , - 1 , 0 ) ;
event_ . Origin . lastEvent = event_ ;
event_ . Origin . lastEvent . Owner = this ;
addEvent ( event_ ) ;
}
}
}
}
}
oldLines = lines ;
l_size = logFile . getSize ( ) ;
Thread . Sleep ( 1 ) ;
}
2015-03-14 12:42:36 -04:00
#if DEBUG = = false
2015-03-08 17:20:10 -04:00
catch ( Exception E )
{
Log . Write ( "Something unexpected occured. Hopefully we can ignore it - " + E . Message + " @" + Utilities . GetLineNumber ( E ) , Log . Level . All ) ;
errors + + ;
continue ;
}
2015-03-14 12:42:36 -04:00
#endif
2015-03-08 17:20:10 -04:00
}
2015-03-14 12:42:36 -04:00
isRunning = false ;
2015-03-08 17:20:10 -04:00
RCONQueue . Abort ( ) ;
eventQueue . Abort ( ) ;
}
2015-03-14 12:42:36 -04:00
private void pollServer ( )
{
while ( isRunning )
{
IPS = Utilities . IPFromStatus ( RCON . addRCON ( "status" ) ) ;
while ( IPS = = null )
{
IPS = Utilities . IPFromStatus ( RCON . addRCON ( "status" ) ) ;
Utilities . Wait ( 1 ) ;
}
lastPoll = DateTime . Now ;
Utilities . Wait ( 15 ) ;
}
}
2015-03-09 00:28:57 -04:00
//Vital RCON commands to establish log file and server name. May need to cleanup in the future
2015-03-08 17:20:10 -04:00
private bool intializeBasics ( )
{
2015-03-13 19:40:16 -04:00
try
2015-03-08 17:20:10 -04:00
{
2015-03-13 19:40:16 -04:00
String [ ] infoResponse = RCON . addRCON ( "getstatus" ) ;
2015-03-11 21:25:14 -04:00
if ( infoResponse = = null | | infoResponse . Length < 2 )
2015-03-10 16:45:20 -04:00
{
2015-03-11 21:25:14 -04:00
Log . Write ( "Could not get server status!" , Log . Level . All ) ;
2015-03-10 16:45:20 -04:00
return false ;
}
2015-03-11 21:25:14 -04:00
infoResponse = infoResponse [ 1 ] . Split ( '\\' ) ;
2015-03-13 19:40:16 -04:00
Dictionary < String , String > infoResponseDict = new Dictionary < string , string > ( ) ;
2015-03-10 16:45:20 -04:00
2015-03-13 19:40:16 -04:00
for ( int i = 0 ; i < infoResponse . Length ; i + + )
{
if ( i % 2 = = 0 | | infoResponse [ i ] = = String . Empty )
continue ;
infoResponseDict . Add ( infoResponse [ i ] , infoResponse [ i + 1 ] ) ;
}
2015-03-11 00:47:34 -04:00
2015-03-13 19:40:16 -04:00
mapname = infoResponseDict [ "mapname" ] ;
try
2015-03-11 00:47:34 -04:00
{
2015-03-13 19:40:16 -04:00
mapname = maps . Find ( m = > m . Name . Equals ( mapname ) ) . Alias ;
2015-03-11 00:47:34 -04:00
}
2015-03-13 19:40:16 -04:00
catch ( Exception )
{
Log . Write ( mapname + " doesn't appear to be in the maps.cfg" , Log . Level . Debug ) ;
}
2015-03-11 00:47:34 -04:00
2015-03-13 19:40:16 -04:00
hostname = Utilities . stripColors ( infoResponseDict [ "sv_hostname" ] ) ;
IW_Ver = infoResponseDict [ "shortversion" ] ;
maxClients = Convert . ToInt32 ( infoResponseDict [ "sv_maxclients" ] ) ;
Gametype = infoResponseDict [ "g_gametype" ] ;
try
{
Website = infoResponseDict [ "_Website" ] ;
}
catch ( Exception E )
{
Log . Write ( "Seems not to have website specified" , Log . Level . Debug ) ;
}
2015-03-11 00:47:34 -04:00
2015-03-13 19:40:16 -04:00
String [ ] p = RCON . addRCON ( "fs_basepath" ) ;
2015-03-08 17:20:10 -04:00
if ( p = = null )
{
Log . Write ( "Could not obtain basepath!" , Log . Level . All ) ;
return false ;
}
p = p [ 1 ] . Split ( '"' ) ;
Basepath = p [ 3 ] . Substring ( 0 , p [ 3 ] . Length - 2 ) . Trim ( ) ;
p = null ;
//END
//get fs_game
2015-03-14 12:42:36 -04:00
p = RCON . addRCON ( "fs_game" ) ;
2015-03-08 17:20:10 -04:00
if ( p = = null )
{
Log . Write ( "Could not obtain mod path!" , Log . Level . All ) ;
return false ;
}
p = p [ 1 ] . Split ( '"' ) ;
Mod = p [ 3 ] . Substring ( 0 , p [ 3 ] . Length - 2 ) . Trim ( ) . Replace ( '/' , '\\' ) ;
p = null ;
//END
//get g_log
2015-03-13 19:40:16 -04:00
p = RCON . addRCON ( "g_log" ) ;
2015-03-08 17:20:10 -04:00
if ( p = = null )
{
Log . Write ( "Could not obtain log path!" , Log . Level . All ) ;
return false ;
}
if ( p . Length < 4 )
{
Thread . Sleep ( FLOOD_TIMEOUT ) ;
Log . Write ( "Server does not appear to have map loaded. Please map_rotate" , Log . Level . All ) ;
return false ;
}
p = p [ 1 ] . Split ( '"' ) ;
string log = p [ 3 ] . Substring ( 0 , p [ 3 ] . Length - 2 ) . Trim ( ) ;
p = null ;
//END
//get g_logsync
2015-03-14 12:42:36 -04:00
p = RCON . addRCON ( "g_logsync" ) ;
2015-03-08 17:20:10 -04:00
if ( p = = null )
{
Log . Write ( "Could not obtain log sync status!" , Log . Level . All ) ;
return false ;
}
p = p [ 1 ] . Split ( '"' ) ;
int logsync = Convert . ToInt32 ( p [ 3 ] . Substring ( 0 , p [ 3 ] . Length - 2 ) . Trim ( ) ) ;
p = null ;
if ( logsync ! = 1 )
2015-03-13 19:40:16 -04:00
RCON . addRCON ( "g_logsync 1" ) ;
2015-03-08 17:20:10 -04:00
//END
//get iw4m_onelog
2015-03-13 19:40:16 -04:00
p = RCON . addRCON ( "iw4m_onelog" ) ;
2015-03-08 17:20:10 -04:00
if ( p [ 0 ] = = String . Empty | | p [ 1 ] . Length < 15 )
{
Log . Write ( "Could not obtain iw4m_onelog value!" , Log . Level . All ) ;
return false ;
}
p = p [ 1 ] . Split ( '"' ) ;
string onelog = p [ 3 ] . Substring ( 0 , p [ 3 ] . Length - 2 ) . Trim ( ) ;
p = null ;
//END
if ( Mod = = String . Empty | | onelog = = "1" )
logPath = Basepath + '\\' + "m2demo" + '\\' + log ;
else
logPath = Basepath + '\\' + Mod + '\\' + log ;
if ( ! File . Exists ( logPath ) )
{
Log . Write ( "Gamelog does not exist!" , Log . Level . All ) ;
return false ;
}
logFile = new file ( logPath ) ;
Log . Write ( "Log file is " + logPath , Log . Level . Debug ) ;
2015-03-14 12:42:36 -04:00
//get players ip's
p = RCON . addRCON ( "status" ) ;
2015-03-13 19:40:16 -04:00
if ( p = = null )
{
Log . Write ( "Unable to get initial player list!" , Log . Level . Debug ) ;
return false ;
}
IPS = Utilities . IPFromStatus ( p ) ;
2015-03-14 12:42:36 -04:00
lastPoll = DateTime . Now ;
2015-03-13 19:40:16 -04:00
#if DEBUG
/ * System . Net . FtpWebRequest tmp = ( System . Net . FtpWebRequest ) System . Net . FtpWebRequest . Create ( "ftp://raidmax.org/logs/games_old.log" ) ;
tmp . Credentials = new System . Net . NetworkCredential ( "*" , "*" ) ;
System . IO . Stream ftpStream = tmp . GetResponse ( ) . GetResponseStream ( ) ;
String ftpLog = new StreamReader ( ftpStream ) . ReadToEnd ( ) ; * /
logPath = "games_old.log" ;
#endif
2015-03-08 17:20:10 -04:00
return true ;
}
catch ( Exception E )
{
Log . Write ( "Error during initialization - " + E . Message , Log . Level . All ) ;
return false ;
}
}
//Process any server event
public bool processEvent ( Event E )
{
if ( E . Type = = Event . GType . Connect )
{
2015-03-10 16:45:20 -04:00
addPlayer ( E . Origin ) ;
2015-03-08 17:20:10 -04:00
return true ;
}
2015-03-13 19:40:16 -04:00
if ( E . Type = = Event . GType . Disconnect & & E . Origin . getClientNum ( ) > 0 )
2015-03-08 17:20:10 -04:00
{
2015-03-13 19:40:16 -04:00
if ( getNumPlayers ( ) > 0 & & E . Origin ! = null & & players [ E . Origin . getClientNum ( ) ] ! = null )
2015-03-09 21:28:37 -04:00
{
2015-03-13 19:40:16 -04:00
clientDB . updatePlayer ( E . Origin ) ;
2015-03-08 17:20:10 -04:00
removePlayer ( E . Origin . getClientNum ( ) ) ;
2015-03-09 21:28:37 -04:00
}
2015-03-08 17:20:10 -04:00
return true ;
}
2015-03-09 21:28:37 -04:00
if ( E . Type = = Event . GType . Kill )
{
2015-03-10 16:45:20 -04:00
if ( E . Origin ! = null & & E . Target ! = null & & E . Origin . stats ! = null )
2015-03-09 21:28:37 -04:00
{
E . Origin . stats . Kills + + ;
2015-03-11 21:25:14 -04:00
E . Origin . stats . updateKDR ( ) ;
E . Origin . stats . updateSkill ( E . Target . stats . Skill ) ;
2015-03-09 21:28:37 -04:00
E . Target . stats . Deaths + + ;
2015-03-11 21:25:14 -04:00
E . Target . stats . updateKDR ( ) ;
2015-03-13 19:40:16 -04:00
//E.Target.stats.updateSkill(E.Origin.stats.Skill);
2015-03-09 21:28:37 -04:00
}
}
2015-03-10 16:45:20 -04:00
if ( E . Type = = Event . GType . Say & & E . Origin ! = null )
2015-03-08 17:20:10 -04:00
{
2015-03-09 21:28:37 -04:00
if ( E . Data . Length < 2 )
return false ;
2015-03-08 17:20:10 -04:00
Log . Write ( "Message from " + E . Origin . getName ( ) + ": " + E . Data , Log . Level . Debug ) ;
if ( E . Data . Substring ( 0 , 1 ) ! = "!" )
return true ;
Command C = E . isValidCMD ( commands ) ;
if ( C ! = null )
{
C = processCommand ( E , C ) ;
if ( C ! = null )
{
C . Execute ( E ) ;
return true ;
}
else
{
Log . Write ( "Error processing command by " + E . Origin . getName ( ) , Log . Level . Debug ) ;
return true ;
}
}
else
E . Origin . Tell ( "You entered an invalid command!" ) ;
return true ;
}
if ( E . Type = = Event . GType . MapChange )
{
2015-03-10 16:45:20 -04:00
Log . Write ( "New map loaded" , Log . Level . Debug ) ;
String [ ] statusResponse = E . Data . Split ( '\\' ) ;
if ( statusResponse . Length > = 15 & & statusResponse [ 13 ] = = "mapname" )
mapname = maps . Find ( m = > m . Name . Equals ( statusResponse [ 14 ] ) ) . Alias ; //update map for heartbeat
2015-03-08 17:20:10 -04:00
}
if ( E . Type = = Event . GType . MapEnd )
{
2015-03-10 16:45:20 -04:00
Log . Write ( "Game ending..." , Log . Level . Debug ) ;
2015-03-09 21:28:37 -04:00
foreach ( Player P in players )
{
2015-03-10 16:45:20 -04:00
if ( P = = null | | P . stats = = null )
2015-03-09 21:28:37 -04:00
continue ;
2015-03-13 19:40:16 -04:00
statDB . updatePlayer ( P ) ;
2015-03-09 21:28:37 -04:00
Log . Write ( "Updated stats for client " + P . getDBID ( ) , Log . Level . Debug ) ;
}
2015-03-08 17:20:10 -04:00
return true ;
}
return false ;
}
2015-03-13 19:40:16 -04:00
public bool Reload ( )
{
try
{
messages = null ;
maps = null ;
rules = null ;
initMaps ( ) ;
initMessages ( ) ;
initRules ( ) ;
return true ;
}
catch ( Exception E )
{
Log . Write ( "Unable to reload configs! - " + E . Message , Log . Level . Debug ) ;
messages = new List < String > ( ) ;
maps = new List < Map > ( ) ;
rules = new List < String > ( ) ;
return false ;
}
}
2015-03-08 17:20:10 -04:00
//THESE MAY NEED TO BE MOVED
public void Broadcast ( String Message )
{
2015-03-13 19:40:16 -04:00
RCON . addRCON ( "sayraw " + Message ) ;
2015-03-08 17:20:10 -04:00
}
public void Tell ( String Message , Player Target )
{
2015-03-13 19:40:16 -04:00
RCON . addRCON ( "tell " + Target . getClientNum ( ) + " " + Message + "^7" ) ;
2015-03-08 17:20:10 -04:00
}
public void Kick ( String Message , Player Target )
{
2015-03-13 19:40:16 -04:00
RCON . addRCON ( "clientkick " + Target . getClientNum ( ) + " \"" + Message + "^7\"" ) ;
2015-03-08 17:20:10 -04:00
}
public void Ban ( String Message , Player Target , Player Origin )
{
2015-03-13 19:40:16 -04:00
RCON . addRCON ( "tempbanclient " + Target . getClientNum ( ) + " \"" + Message + "^7\"" ) ;
2015-03-08 17:20:10 -04:00
if ( Origin ! = null )
{
Target . setLevel ( Player . Permission . Banned ) ;
2015-03-13 19:40:16 -04:00
Ban newBan = new Ban ( Target . getLastO ( ) , Target . getID ( ) , Origin . getID ( ) , DateTime . Now , Target . getIP ( ) ) ;
2015-03-08 17:20:10 -04:00
Bans . Add ( newBan ) ;
2015-03-13 19:40:16 -04:00
clientDB . addBan ( newBan ) ;
clientDB . updatePlayer ( Target ) ;
2015-03-08 17:20:10 -04:00
}
}
2015-03-09 00:28:57 -04:00
public bool Unban ( String GUID , Player Target )
2015-03-08 17:20:10 -04:00
{
foreach ( Ban B in Bans )
{
2015-03-09 21:28:37 -04:00
if ( B . getID ( ) = = Target . getID ( ) )
2015-03-08 17:20:10 -04:00
{
2015-03-13 19:40:16 -04:00
clientDB . removeBan ( GUID ) ;
2015-03-08 17:20:10 -04:00
Bans . Remove ( B ) ;
2015-03-13 19:40:16 -04:00
Player P = clientDB . getPlayer ( Target . getID ( ) , 0 ) ;
2015-03-08 17:20:10 -04:00
P . setLevel ( Player . Permission . User ) ;
2015-03-13 19:40:16 -04:00
clientDB . updatePlayer ( P ) ;
2015-03-08 17:20:10 -04:00
return true ;
}
}
return false ;
}
public void fastRestart ( int delay )
{
Utilities . Wait ( delay ) ;
2015-03-13 19:40:16 -04:00
RCON . addRCON ( "fast_restart" ) ;
2015-03-08 17:20:10 -04:00
}
public void mapRotate ( int delay )
{
Utilities . Wait ( delay ) ;
2015-03-13 19:40:16 -04:00
RCON . addRCON ( "map_rotate" ) ;
2015-03-08 17:20:10 -04:00
}
public void tempBan ( String Message , Player Target )
{
2015-03-13 19:40:16 -04:00
RCON . addRCON ( "tempbanclient " + Target . getClientNum ( ) + " \"" + Message + "\"" ) ;
2015-03-08 17:20:10 -04:00
}
public void mapRotate ( )
{
2015-03-13 19:40:16 -04:00
RCON . addRCON ( "map_rotate" ) ;
2015-03-08 17:20:10 -04:00
}
public void Map ( String map )
{
2015-03-13 19:40:16 -04:00
RCON . addRCON ( "map " + map ) ;
}
public String Wisdom ( )
{
String Quote = new Connection ( "http://www.iheartquotes.com/api/v1/random?max_lines=1&max_characters=200" ) . Read ( ) ;
return Utilities . removeNastyChars ( Quote ) ;
2015-03-08 17:20:10 -04:00
}
2015-03-13 19:40:16 -04:00
2015-03-08 17:20:10 -04:00
//END
//THIS IS BAD BECAUSE WE DON"T WANT EVERYONE TO HAVE ACCESS :/
public String getPassword ( )
{
return rcon_pass ;
}
2015-03-13 19:40:16 -04:00
private void initMacros ( )
{
Macros = new Dictionary < String , Object > ( ) ;
Macros . Add ( "WISDOM" , Wisdom ( ) ) ;
Macros . Add ( "TOTALPLAYERS" , clientDB . totalPlayers ( ) ) ;
}
2015-03-08 17:20:10 -04:00
private void initMaps ( )
{
2015-03-13 19:40:16 -04:00
maps = new List < Map > ( ) ;
2015-03-08 17:20:10 -04:00
file mapfile = new file ( "config\\maps.cfg" ) ;
String [ ] _maps = mapfile . readAll ( ) ;
2015-03-13 19:40:16 -04:00
mapfile . Close ( ) ;
2015-03-08 17:20:10 -04:00
if ( _maps . Length > 2 ) // readAll returns minimum one empty string
{
foreach ( String m in _maps )
{
String [ ] m2 = m . Split ( ':' ) ;
if ( m2 . Length > 1 )
{
Map map = new Map ( m2 [ 0 ] . Trim ( ) , m2 [ 1 ] . Trim ( ) ) ;
maps . Add ( map ) ;
}
}
2015-03-11 21:25:14 -04:00
}
2015-03-08 17:20:10 -04:00
else
Log . Write ( "Maps configuration appears to be empty - skipping..." , Log . Level . All ) ;
}
private void initMessages ( )
{
2015-03-13 19:40:16 -04:00
messages = new List < String > ( ) ;
2015-03-08 17:20:10 -04:00
file messageCFG = new file ( "config\\messages.cfg" ) ;
String [ ] lines = messageCFG . readAll ( ) ;
2015-03-13 19:40:16 -04:00
messageCFG . Close ( ) ;
2015-03-08 17:20:10 -04:00
if ( lines . Length < 2 ) //readAll returns minimum one empty string
{
Log . Write ( "Messages configuration appears empty - skipping..." , Log . Level . All ) ;
return ;
}
int mTime = - 1 ;
int . TryParse ( lines [ 0 ] , out mTime ) ;
if ( messageTime = = - 1 )
messageTime = 60 ;
else
messageTime = mTime ;
foreach ( String l in lines )
{
if ( lines [ 0 ] ! = l & & l . Length > 1 )
messages . Add ( l ) ;
}
2015-03-10 16:45:20 -04:00
if ( Program . Version ! = Program . latestVersion & & Program . latestVersion ! = 0 )
messages . Add ( "^5IW4M Admin ^7is outdated. Please ^5update ^7to version " + Program . latestVersion ) ;
2015-03-08 17:20:10 -04:00
}
private void initRules ( )
{
2015-03-13 19:40:16 -04:00
rules = new List < String > ( ) ;
2015-03-08 17:20:10 -04:00
file ruleFile = new file ( "config\\rules.cfg" ) ;
String [ ] _rules = ruleFile . readAll ( ) ;
2015-03-13 19:40:16 -04:00
ruleFile . Close ( ) ;
2015-03-08 17:20:10 -04:00
if ( _rules . Length > 2 ) // readAll returns minimum one empty string
{
foreach ( String r in _rules )
{
if ( r . Length > 1 )
rules . Add ( r ) ;
}
}
else
Log . Write ( "Rules configuration appears empty - skipping..." , Log . Level . All ) ;
}
private void initCommands ( )
{
// Something like *COMMAND* | NAME | HELP MSG | ALIAS | NEEDED PERMISSION | # OF REQUIRED ARGS | HAS TARGET |
commands = new List < Command > ( ) ;
if ( owner = = null )
commands . Add ( new Owner ( "owner" , "claim ownership of the server" , "owner" , Player . Permission . User , 0 , false ) ) ;
commands . Add ( new Kick ( "kick" , "kick a player by name. syntax: !kick <player> <reason>." , "k" , Player . Permission . Moderator , 2 , true ) ) ;
commands . Add ( new Say ( "say" , "broadcast message to all players. syntax: !say <message>." , "s" , Player . Permission . Moderator , 1 , false ) ) ;
commands . Add ( new TempBan ( "tempban" , "temporarily ban a player for 1 hour. syntax: !tempban <player> <reason>." , "tb" , Player . Permission . Moderator , 2 , true ) ) ;
commands . Add ( new SBan ( "ban" , "permanently ban a player from the server. syntax: !ban <player> <reason>" , "b" , Player . Permission . SeniorAdmin , 2 , true ) ) ;
commands . Add ( new WhoAmI ( "whoami" , "give information about yourself. syntax: !whoami." , "who" , Player . Permission . User , 0 , false ) ) ;
commands . Add ( new List ( "list" , "list active clients syntax: !list." , "l" , Player . Permission . Moderator , 0 , false ) ) ;
2015-03-10 16:45:20 -04:00
commands . Add ( new Help ( "help" , "list all available commands. syntax: !help." , "h" , Player . Permission . User , 0 , false ) ) ;
2015-03-08 17:20:10 -04:00
commands . Add ( new FastRestart ( "fastrestart" , "fast restart current map. syntax: !fastrestart." , "fr" , Player . Permission . Moderator , 0 , false ) ) ;
commands . Add ( new MapRotate ( "maprotate" , "cycle to the next map in rotation. syntax: !maprotate." , "mr" , Player . Permission . Administrator , 0 , false ) ) ;
commands . Add ( new SetLevel ( "setlevel" , "set player to specified administration level. syntax: !setlevel <player> <level>." , "sl" , Player . Permission . Owner , 2 , true ) ) ;
2015-03-10 16:45:20 -04:00
commands . Add ( new Usage ( "usage" , "get current application memory usage. syntax: !usage." , "us" , Player . Permission . Moderator , 0 , false ) ) ;
2015-03-08 17:20:10 -04:00
commands . Add ( new Uptime ( "uptime" , "get current application running time. syntax: !uptime." , "up" , Player . Permission . Moderator , 0 , false ) ) ;
commands . Add ( new Warn ( "warn" , "warn player for infringing rules syntax: !warn <player> <reason>." , "w" , Player . Permission . Moderator , 2 , true ) ) ;
commands . Add ( new WarnClear ( "warnclear" , "remove all warning for a player syntax: !warnclear <player>." , "wc" , Player . Permission . Administrator , 1 , true ) ) ;
2015-03-13 19:40:16 -04:00
commands . Add ( new Unban ( "unban" , "unban player by guid. syntax: !unban <guid>." , "ub" , Player . Permission . SeniorAdmin , 1 , true ) ) ;
2015-03-08 17:20:10 -04:00
commands . Add ( new Admins ( "admins" , "list currently connected admins. syntax: !admins." , "a" , Player . Permission . User , 0 , false ) ) ;
commands . Add ( new Wisdom ( "wisdom" , "get a random wisdom quote. syntax: !wisdom" , "w" , Player . Permission . Administrator , 0 , false ) ) ;
commands . Add ( new MapCMD ( "map" , "change to specified map. syntax: !map" , "m" , Player . Permission . Administrator , 1 , false ) ) ;
2015-03-13 19:40:16 -04:00
commands . Add ( new Find ( "find" , "find player in database. syntax: !find <player>" , "f" , Player . Permission . SeniorAdmin , 1 , false ) ) ;
2015-03-08 17:20:10 -04:00
commands . Add ( new Rules ( "rules" , "list server rules. syntax: !rules" , "r" , Player . Permission . User , 0 , false ) ) ;
2015-03-09 16:11:09 -04:00
commands . Add ( new PrivateMessage ( "privatemessage" , "send message to other player. syntax: !pm <player> <message>" , "pm" , Player . Permission . User , 2 , true ) ) ;
2015-03-09 21:28:37 -04:00
commands . Add ( new _Stats ( "stats" , "view your stats or another player's. syntax: !stats" , "xlrstats" , Player . Permission . User , 0 , true ) ) ;
2015-03-13 19:40:16 -04:00
commands . Add ( new TopStats ( "topstats" , "view the top 4 players on this server. syntax: !topstats" , "xlrtopstats" , Player . Permission . User , 0 , false ) ) ;
commands . Add ( new Reload ( "reload" , "reload configurations. syntax: !reload" , "reload" , Player . Permission . Owner , 0 , false ) ) ;
2015-03-08 17:20:10 -04:00
/ *
commands . Add ( new commands { command = "stats" , desc = "view your server stats." , requiredPer = 0 } ) ;
commands . Add ( new commands { command = "speed" , desc = "change player speed. syntax: !speed <number>" , requiredPer = 3 } ) ;
commands . Add ( new commands { command = "gravity" , desc = "change game gravity. syntax: !gravity <number>" , requiredPer = 3 } ) ;
commands . Add ( new commands { command = "version" , desc = "view current app version." , requiredPer = 0 } ) ; * /
}
//Objects
public Log Log ;
public RCON RCON ;
2015-03-13 19:40:16 -04:00
public ClientsDB clientDB ;
public AliasesDB aliasDB ;
public StatsDB statDB ;
2015-03-08 17:20:10 -04:00
public List < Ban > Bans ;
public Player owner ;
public List < Map > maps ;
public List < String > rules ;
public Queue < Event > events ;
2015-03-10 16:45:20 -04:00
public Heartbeat HB ;
2015-03-11 00:47:34 -04:00
public String Website ;
2015-03-11 21:25:14 -04:00
public String Gametype ;
2015-03-08 17:20:10 -04:00
//Info
private String IP ;
private int Port ;
private String hostname ;
2015-03-10 16:45:20 -04:00
private String mapname ;
2015-03-08 17:20:10 -04:00
private int clientnum ;
private string rcon_pass ;
private List < Player > players ;
private List < Command > commands ;
private List < String > messages ;
private int messageTime ;
private TimeSpan lastMessage ;
private int nextMessage ;
private int errors = 0 ;
2015-03-11 21:25:14 -04:00
private String IW_Ver ;
private int maxClients ;
2015-03-13 19:40:16 -04:00
private Dictionary < String , Object > Macros ;
//Will probably move this later
private Dictionary < String , String > IPS ;
2015-03-14 12:42:36 -04:00
public bool isRunning ;
private DateTime lastPoll ;
2015-03-10 17:56:01 -04:00
2015-03-08 17:20:10 -04:00
//Log stuff
private String Basepath ;
private String Mod ;
private String logPath ;
private file logFile ;
}
}