2015-07-03 00:10:01 -04:00
using System ;
using System.Collections.Generic ;
using System.Linq ;
using System.Threading ;
2015-08-20 01:06:44 -04:00
using SharedLibrary ;
2017-05-26 18:49:27 -04:00
using System.IO ;
using System.Threading.Tasks ;
2015-07-03 00:10:01 -04:00
namespace IW4MAdmin
{
2017-05-26 18:49:27 -04:00
class Manager : SharedLibrary . Interfaces . IManager
2015-07-03 00:10:01 -04:00
{
2017-05-26 18:49:27 -04:00
static Manager Instance ;
public List < Server > Servers { get ; private set ; }
2017-06-12 17:47:31 -04:00
List < SharedLibrary . Helpers . AsyncStatus > TaskStatuses ;
2017-05-27 18:08:04 -04:00
Database ClientDatabase ;
2017-05-28 21:54:46 -04:00
Database AliasesDatabase ;
2017-05-27 18:08:04 -04:00
SharedLibrary . Interfaces . IPenaltyList ClientPenalties ;
2017-05-26 18:49:27 -04:00
List < Command > Commands ;
2017-06-12 17:47:31 -04:00
List < SharedLibrary . Helpers . MessageToken > MessageTokens ;
2017-05-26 18:49:27 -04:00
Kayak . IScheduler webServiceTask ;
Thread WebThread ;
2017-05-27 19:29:20 -04:00
public SharedLibrary . Interfaces . ILogger Logger { get ; private set ; }
2017-05-26 18:49:27 -04:00
public bool Running { get ; private set ; }
#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
private Manager ( )
2015-07-03 00:10:01 -04:00
{
2017-05-27 19:29:20 -04:00
Logger = new Logger ( "Logs/IW4MAdmin.log" ) ;
2017-05-26 18:49:27 -04:00
Servers = new List < Server > ( ) ;
Commands = new List < Command > ( ) ;
2017-06-12 17:47:31 -04:00
TaskStatuses = new List < SharedLibrary . Helpers . AsyncStatus > ( ) ;
MessageTokens = new List < SharedLibrary . Helpers . MessageToken > ( ) ;
2017-05-28 16:47:21 -04:00
2017-05-27 18:08:04 -04:00
ClientDatabase = new ClientsDB ( "Database/clients.rm" ) ;
2017-05-28 21:54:46 -04:00
AliasesDatabase = new AliasesDB ( "Database/aliases.rm" ) ;
2017-05-27 18:08:04 -04:00
ClientPenalties = new PenaltyList ( ) ;
2015-07-03 00:10:01 -04:00
}
2017-05-26 18:49:27 -04:00
public List < 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-05-26 18:49:27 -04:00
public List < 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-05-26 18:49:27 -04:00
public static Manager GetInstance ( )
2015-08-22 02:04:30 -04:00
{
2017-05-27 19:29:20 -04:00
return Instance ? ? ( Instance = new Manager ( ) ) ;
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-06-13 18:33:47 -04:00
SharedLibrary . WebService . Init ( ) ;
SharedLibrary . Plugins . PluginImporter . Load ( this ) ;
foreach ( var Plugin in SharedLibrary . Plugins . PluginImporter . ActivePlugins )
{
try
{
Plugin . OnLoadAsync ( ) ;
}
catch ( Exception e )
{
Logger . WriteError ( $"An error occured loading plugin {Plugin.Name}" ) ;
Logger . WriteDebug ( $"Exception: {e.Message}" ) ;
Logger . WriteDebug ( $"Stack Trace: {e.StackTrace}" ) ;
}
}
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-12 13:50:00 -04:00
ServerConfig . 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-12 13:50:00 -04:00
var Conf = ServerConfig . Read ( file ) ;
2017-05-26 18:49:27 -04:00
var ServerInstance = new IW4MServer ( this , Conf . IP , Conf . Port , Conf . Password ) ;
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-05-26 18:49:27 -04:00
await ServerInstance . Initialize ( ) ;
Servers . Add ( ServerInstance ) ;
2017-05-28 16:47:21 -04:00
// this way we can keep track of execution time and see if problems arise.
2017-06-12 17:47:31 -04:00
var Status = new SharedLibrary . Helpers . AsyncStatus ( ServerInstance , UPDATE_FREQUENCY ) ;
2017-05-28 16:47:21 -04:00
TaskStatuses . Add ( Status ) ;
2017-05-27 19:29:20 -04:00
Logger . WriteVerbose ( $"Now monitoring {ServerInstance.Hostname}" ) ;
2015-07-06 13:13:42 -04:00
}
2015-08-28 00:39:36 -04:00
2017-05-26 18:49:27 -04:00
catch ( SharedLibrary . Exceptions . ServerException e )
{
2017-05-27 19:29:20 -04:00
Logger . WriteWarning ( $"Not monitoring server {Conf.IP}:{Conf.Port} due to uncorrectable errors" ) ;
2017-05-26 18:49:27 -04:00
if ( e . GetType ( ) = = typeof ( SharedLibrary . Exceptions . DvarException ) )
2017-05-27 19:29:20 -04:00
Logger . WriteError ( $"Could not get the dvar value for {(e as SharedLibrary.Exceptions.DvarException).Data[" dvar_name "]} (ensure the server has a map loaded)" ) ;
2017-05-26 18:49:27 -04:00
else if ( e . GetType ( ) = = typeof ( SharedLibrary . Exceptions . NetworkException ) )
2017-05-27 19:29:20 -04:00
Logger . WriteError ( "Could not communicate with the server (ensure the configuration is correct)" ) ;
2017-05-26 18:49:27 -04:00
}
} ) ;
2015-07-06 13:13:42 -04:00
2015-07-03 00:10:01 -04:00
}
2015-07-06 13:13:42 -04:00
2017-06-06 23:45:21 -04:00
webServiceTask = WebService . GetScheduler ( ) ;
2015-07-03 00:10:01 -04:00
2017-05-28 16:47:21 -04:00
WebThread = new Thread ( webServiceTask . Start )
{
Name = "Web Thread"
} ;
2017-05-31 01:31:56 -04:00
2017-05-26 18:49:27 -04:00
WebThread . Start ( ) ;
2015-07-03 00:10:01 -04:00
2017-05-26 18:49:27 -04:00
Running = true ;
2015-07-03 00:10:01 -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-05-28 16:47:21 -04:00
foreach ( var Status in TaskStatuses )
2015-07-03 00:10:01 -04:00
{
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 ( ) ) ) ) ;
if ( Status . RunAverage > 500 )
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
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
Servers . Clear ( ) ;
WebThread . Abort ( ) ;
webServiceTask . Stop ( ) ;
2015-07-03 00:10:01 -04:00
}
2015-07-06 15:51:08 -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-05-27 18:08:04 -04:00
public SharedLibrary . Interfaces . IPenaltyList GetClientPenalties ( )
{
return ClientPenalties ;
}
2017-05-27 19:29:20 -04:00
public SharedLibrary . Interfaces . ILogger GetLogger ( )
{
return Logger ;
}
2017-05-31 01:31:56 -04:00
2017-06-12 17:47:31 -04:00
public IList < SharedLibrary . Helpers . 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 > ( ) ;
foreach ( var server in Servers )
ActiveClients . AddRange ( server . Players . Where ( p = > p ! = null ) ) ;
return ActiveClients ;
}
2015-07-03 00:10:01 -04:00
}
}