2015-07-03 00:10:01 -04:00
using System ;
using System.Collections.Generic ;
using System.Linq ;
using System.Threading ;
2017-05-26 18:49:27 -04:00
using System.IO ;
using System.Threading.Tasks ;
2015-07-03 00:10:01 -04:00
2017-06-19 13:58:01 -04:00
using SharedLibrary ;
using SharedLibrary.Interfaces ;
using SharedLibrary.Commands ;
using SharedLibrary.Helpers ;
2017-06-19 16:46:31 -04:00
using SharedLibrary.Exceptions ;
2017-06-19 13:58:01 -04:00
2015-07-03 00:10:01 -04:00
namespace IW4MAdmin
{
2017-06-19 13:58:01 -04:00
class ApplicationManager : IManager
2015-07-03 00:10:01 -04:00
{
2017-10-04 19:01:04 -04:00
private List < Server > _servers ;
public List < Server > Servers = > _servers . OrderByDescending ( s = > s . ClientNum ) . ToList ( ) ;
2017-06-19 13:58:01 -04:00
public ILogger Logger { get ; private set ; }
public bool Running { get ; private set ; }
static ApplicationManager Instance ;
List < AsyncStatus > TaskStatuses ;
2017-05-27 18:08:04 -04:00
Database ClientDatabase ;
2017-05-28 21:54:46 -04:00
Database AliasesDatabase ;
2017-06-19 13:58:01 -04:00
IPenaltyList ClientPenalties ;
2017-05-26 18:49:27 -04:00
List < Command > Commands ;
2017-06-19 13:58:01 -04:00
List < MessageToken > MessageTokens ;
2017-05-26 18:49:27 -04:00
Kayak . IScheduler webServiceTask ;
Thread WebThread ;
2017-09-27 16:07:43 -04:00
List < Player > PrivilegedClients ;
2017-05-26 18:49:27 -04:00
#if FTP_LOG
2017-05-28 16:47:21 -04:00
const int UPDATE_FREQUENCY = 15000 ;
2017-05-26 18:49:27 -04:00
#else
2017-05-28 16:47:21 -04:00
const int UPDATE_FREQUENCY = 300 ;
2017-05-26 18:49:27 -04:00
#endif
2017-06-19 13:58:01 -04:00
private ApplicationManager ( )
2015-07-03 00:10:01 -04:00
{
2017-05-27 19:29:20 -04:00
Logger = new Logger ( "Logs/IW4MAdmin.log" ) ;
2017-10-04 19:01:04 -04:00
_servers = new List < Server > ( ) ;
2017-05-26 18:49:27 -04:00
Commands = new List < Command > ( ) ;
2017-06-19 13:58:01 -04:00
TaskStatuses = new List < AsyncStatus > ( ) ;
MessageTokens = new List < MessageToken > ( ) ;
2017-05-28 16:47:21 -04:00
2017-11-14 16:36:55 -05:00
ClientDatabase = new ClientsDB ( "Database/clients.rm" , Logger ) ;
AliasesDatabase = new AliasesDB ( "Database/aliases.rm" , Logger ) ;
2017-05-27 18:08:04 -04:00
ClientPenalties = new PenaltyList ( ) ;
2015-07-03 00:10:01 -04:00
}
2017-09-29 22:42:24 -04:00
public IList < Server > GetServers ( )
2015-07-03 00:10:01 -04:00
{
2017-05-26 18:49:27 -04:00
return Servers ;
2015-07-03 00:10:01 -04:00
}
2017-09-29 22:42:24 -04:00
public IList < Command > GetCommands ( )
2015-08-17 16:38:42 -04:00
{
2017-05-26 18:49:27 -04:00
return Commands ;
2015-08-17 16:38:42 -04:00
}
2017-06-19 13:58:01 -04:00
public static ApplicationManager GetInstance ( )
2015-08-22 02:04:30 -04:00
{
2017-06-19 13:58:01 -04:00
return Instance ? ? ( Instance = new ApplicationManager ( ) ) ;
2015-08-22 02:04:30 -04:00
}
2017-05-26 18:49:27 -04:00
public void Init ( )
2015-07-06 13:13:42 -04:00
{
2017-09-29 22:42:24 -04:00
#region WEBSERVICE
SharedLibrary . WebService . Init ( ) ;
webServiceTask = WebService . GetScheduler ( ) ;
WebThread = new Thread ( webServiceTask . Start )
{
Name = "Web Thread"
} ;
WebThread . Start ( ) ;
#endregion
2017-08-09 00:35:23 -04:00
#region PLUGINS
SharedLibrary . Plugins . PluginImporter . Load ( this ) ;
foreach ( var Plugin in SharedLibrary . Plugins . PluginImporter . ActivePlugins )
{
try
{
2017-10-16 23:47:41 -04:00
Plugin . OnLoadAsync ( this ) ;
2017-08-09 00:35:23 -04:00
}
catch ( Exception e )
{
Logger . WriteError ( $"An error occured loading plugin {Plugin.Name}" ) ;
Logger . WriteDebug ( $"Exception: {e.Message}" ) ;
Logger . WriteDebug ( $"Stack Trace: {e.StackTrace}" ) ;
}
}
#endregion
2017-06-19 13:58:01 -04:00
#region CONFIG
2017-05-26 18:49:27 -04:00
var Configs = Directory . EnumerateFiles ( "config/servers" ) . Where ( x = > x . Contains ( ".cfg" ) ) ;
2015-07-06 13:13:42 -04:00
2017-05-26 18:49:27 -04:00
if ( Configs . Count ( ) = = 0 )
2017-06-19 13:58:01 -04:00
ServerConfigurationGenerator . Generate ( ) ;
2015-08-17 16:38:42 -04:00
2017-05-26 18:49:27 -04:00
foreach ( var file in Configs )
2015-07-03 00:10:01 -04:00
{
2017-06-19 13:58:01 -04:00
var Conf = ServerConfiguration . Read ( file ) ;
2015-08-17 16:38:42 -04:00
2017-05-26 18:49:27 -04:00
Task . Run ( async ( ) = >
2015-07-03 00:10:01 -04:00
{
2017-05-26 18:49:27 -04:00
try
2015-07-06 13:13:42 -04:00
{
2017-08-09 00:35:23 -04:00
var ServerInstance = new IW4MServer ( this , Conf ) ;
2017-05-26 18:49:27 -04:00
await ServerInstance . Initialize ( ) ;
2017-05-28 16:47:21 -04:00
2017-10-04 19:01:04 -04:00
lock ( _servers )
2017-08-09 00:35:23 -04:00
{
2017-10-04 19:01:04 -04:00
_servers . Add ( ServerInstance ) ;
2017-08-09 00:35:23 -04:00
}
2017-05-28 16:47:21 -04:00
2017-05-27 19:29:20 -04:00
Logger . WriteVerbose ( $"Now monitoring {ServerInstance.Hostname}" ) ;
2017-08-09 00:35:23 -04:00
// this way we can keep track of execution time and see if problems arise.
var Status = new AsyncStatus ( ServerInstance , UPDATE_FREQUENCY ) ;
lock ( TaskStatuses )
{
TaskStatuses . Add ( Status ) ;
}
2015-07-06 13:13:42 -04:00
}
2015-08-28 00:39:36 -04:00
2017-06-19 16:46:31 -04:00
catch ( ServerException e )
2017-05-26 18:49:27 -04:00
{
2017-11-13 16:58:23 -05:00
Logger . WriteError ( $"Not monitoring server {Conf.IP}:{Conf.Port} due to uncorrectable errors" ) ;
2017-06-19 16:46:31 -04:00
if ( e . GetType ( ) = = typeof ( DvarException ) )
2017-11-13 16:58:23 -05:00
Logger . WriteDebug ( $"Could not get the dvar value for {(e as DvarException).Data[" dvar_name "]} (ensure the server has a map loaded)" ) ;
2017-06-19 16:46:31 -04:00
else if ( e . GetType ( ) = = typeof ( NetworkException ) )
2017-11-13 16:58:23 -05:00
{
Logger . WriteDebug ( e . Message ) ;
Logger . WriteDebug ( $"Internal Exception: {e.Data[" internal_exception "]}" ) ;
}
2017-05-26 18:49:27 -04:00
}
} ) ;
2015-07-03 00:10:01 -04:00
}
2017-06-19 13:58:01 -04:00
#endregion
#region COMMANDS
2017-08-08 22:44:52 -04:00
if ( ( ClientDatabase as ClientsDB ) . GetOwner ( ) = = null )
2017-11-15 16:04:13 -05:00
Commands . Add ( new COwner ( ) ) ;
Commands . Add ( new CQuit ( ) ) ;
Commands . Add ( new CKick ( ) ) ;
Commands . Add ( new CSay ( ) ) ;
Commands . Add ( new CTempBan ( ) ) ;
Commands . Add ( new CBan ( ) ) ;
Commands . Add ( new CWhoAmI ( ) ) ;
Commands . Add ( new CList ( ) ) ;
Commands . Add ( new CHelp ( ) ) ;
Commands . Add ( new CFastRestart ( ) ) ;
Commands . Add ( new CMapRotate ( ) ) ;
Commands . Add ( new CSetLevel ( ) ) ;
Commands . Add ( new CUsage ( ) ) ;
Commands . Add ( new CUptime ( ) ) ;
Commands . Add ( new CWarn ( ) ) ;
Commands . Add ( new CWarnClear ( ) ) ;
Commands . Add ( new CUnban ( ) ) ;
Commands . Add ( new CListAdmins ( ) ) ;
Commands . Add ( new CLoadMap ( ) ) ;
Commands . Add ( new CFindPlayer ( ) ) ;
Commands . Add ( new CListRules ( ) ) ;
Commands . Add ( new CPrivateMessage ( ) ) ;
Commands . Add ( new CReload ( ) ) ;
Commands . Add ( new CFlag ( ) ) ;
Commands . Add ( new CReport ( ) ) ;
Commands . Add ( new CListReports ( ) ) ;
Commands . Add ( new CListBanInfo ( ) ) ;
Commands . Add ( new CListAlias ( ) ) ;
Commands . Add ( new CExecuteRCON ( ) ) ;
Commands . Add ( new CFindAllPlayers ( ) ) ;
Commands . Add ( new CPlugins ( ) ) ;
Commands . Add ( new CIP ( ) ) ;
2017-06-19 13:58:01 -04:00
foreach ( Command C in SharedLibrary . Plugins . PluginImporter . ActiveCommands )
Commands . Add ( C ) ;
#endregion
2017-09-27 16:07:43 -04:00
#region ADMINS
PrivilegedClients = GetClientDatabase ( ) . GetAdmins ( ) ;
#endregion
2017-05-26 18:49:27 -04:00
Running = true ;
2015-07-03 00:10:01 -04:00
}
2017-08-09 00:35:23 -04:00
2017-05-26 18:49:27 -04:00
public void Start ( )
2015-07-03 00:10:01 -04:00
{
2017-05-28 16:47:21 -04:00
while ( Running )
2015-07-03 00:10:01 -04:00
{
2017-08-09 00:35:23 -04:00
for ( int i = 0 ; i < TaskStatuses . Count ; i + + )
2015-07-03 00:10:01 -04:00
{
2017-08-09 00:35:23 -04:00
var Status = TaskStatuses [ i ] ;
2017-05-28 16:47:21 -04:00
if ( Status . RequestedTask = = null | | Status . RequestedTask . IsCompleted )
{
Status . Update ( new Task ( ( ) = > ( Status . Dependant as Server ) . ProcessUpdatesAsync ( Status . GetToken ( ) ) ) ) ;
2017-11-13 16:58:23 -05:00
if ( Status . RunAverage > 1000 + UPDATE_FREQUENCY )
2017-06-12 13:50:00 -04:00
Logger . WriteWarning ( $"Update task average execution is longer than desired for {(Status.Dependant as Server).GetIP()}::{(Status.Dependant as Server).GetPort()} [{Status.RunAverage}ms]" ) ;
2017-05-28 16:47:21 -04:00
}
2015-07-03 00:10:01 -04:00
}
2017-05-28 16:47:21 -04:00
2017-09-27 16:07:43 -04:00
Thread . Sleep ( UPDATE_FREQUENCY ) ;
2015-07-03 00:10:01 -04:00
}
2017-05-26 18:49:27 -04:00
#if ! DEBUG
foreach ( var S in Servers )
S . Broadcast ( "^1IW4MAdmin going offline!" ) ;
#endif
2017-10-04 19:01:04 -04:00
_servers . Clear ( ) ;
2017-05-26 18:49:27 -04:00
WebThread . Abort ( ) ;
webServiceTask . Stop ( ) ;
2015-07-03 00:10:01 -04:00
}
2015-07-06 15:51:08 -04:00
2017-08-09 00:35:23 -04:00
2017-05-26 18:49:27 -04:00
public void Stop ( )
2015-07-06 15:51:08 -04:00
{
2017-05-26 18:49:27 -04:00
Running = false ;
2015-07-06 15:51:08 -04:00
}
2017-05-27 18:08:04 -04:00
public ClientsDB GetClientDatabase ( )
{
return ClientDatabase as ClientsDB ;
}
2017-05-28 21:54:46 -04:00
public AliasesDB GetAliasesDatabase ( )
{
return AliasesDatabase as AliasesDB ;
}
2017-06-19 13:58:01 -04:00
public IPenaltyList GetClientPenalties ( )
2017-05-27 18:08:04 -04:00
{
return ClientPenalties ;
}
2017-05-27 19:29:20 -04:00
2017-06-19 13:58:01 -04:00
public ILogger GetLogger ( )
2017-05-27 19:29:20 -04:00
{
return Logger ;
}
2017-05-31 01:31:56 -04:00
2017-06-19 13:58:01 -04:00
public IList < MessageToken > GetMessageTokens ( )
2017-05-31 01:31:56 -04:00
{
return MessageTokens ;
}
2017-06-12 13:50:00 -04:00
public IList < Player > GetActiveClients ( )
{
var ActiveClients = new List < Player > ( ) ;
2017-10-04 19:01:04 -04:00
foreach ( var server in _servers )
2017-06-12 13:50:00 -04:00
ActiveClients . AddRange ( server . Players . Where ( p = > p ! = null ) ) ;
return ActiveClients ;
}
2017-08-17 19:28:08 -04:00
public IList < Player > GetAliasClients ( Player Origin )
{
List < int > databaseIDs = new List < int > ( ) ;
foreach ( Aliases A in GetAliases ( Origin ) )
databaseIDs . Add ( A . Number ) ;
return GetClientDatabase ( ) . GetPlayers ( databaseIDs ) ;
}
public IList < Aliases > GetAliases ( Player Origin )
{
List < Aliases > allAliases = new List < Aliases > ( ) ;
if ( Origin = = null )
return allAliases ;
Aliases currentIdentityAliases = GetAliasesDatabase ( ) . GetPlayerAliases ( Origin . DatabaseID ) ;
if ( currentIdentityAliases = = null )
return allAliases ;
GetAliases ( allAliases , currentIdentityAliases ) ;
if ( Origin . Alias ! = null )
allAliases . Add ( Origin . Alias ) ;
return allAliases ;
}
2017-09-27 16:07:43 -04:00
public IList < Player > GetPrivilegedClients ( )
{
return PrivilegedClients ;
}
2017-08-17 19:28:08 -04:00
private void GetAliases ( List < Aliases > returnAliases , Aliases currentAlias )
{
foreach ( String IP in currentAlias . IPS )
{
List < Aliases > Matching = GetAliasesDatabase ( ) . GetPlayerAliases ( IP ) ;
foreach ( Aliases I in Matching )
{
if ( ! returnAliases . Contains ( I ) & & returnAliases . Find ( x = > x . Number = = I . Number ) = = null )
{
returnAliases . Add ( I ) ;
GetAliases ( returnAliases , I ) ;
}
}
}
}
2015-07-03 00:10:01 -04:00
}
}