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
2018-04-08 02:44:42 -04:00
using SharedLibraryCore ;
using SharedLibraryCore.Interfaces ;
using SharedLibraryCore.Commands ;
using SharedLibraryCore.Helpers ;
using SharedLibraryCore.Exceptions ;
using SharedLibraryCore.Objects ;
using SharedLibraryCore.Services ;
2018-04-08 14:48:40 -04:00
using IW4MAdmin.Application.API ;
2018-03-14 01:36:25 -04:00
using Microsoft.Extensions.Configuration ;
using WebfrontCore ;
2018-04-08 02:44:42 -04:00
using SharedLibraryCore.Configuration ;
2018-03-14 01:36:25 -04:00
using Newtonsoft.Json ;
using Newtonsoft.Json.Linq ;
2018-04-21 18:18:20 -04:00
using System.Text ;
2018-04-28 01:22:18 -04:00
using IW4MAdmin.Application.API.Master ;
2018-05-28 21:30:31 -04:00
using System.Reflection ;
2017-06-19 13:58:01 -04:00
2018-04-08 14:48:40 -04:00
namespace IW4MAdmin.Application
2015-07-03 00:10:01 -04:00
{
2018-02-21 20:29:23 -05:00
public 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 ( ) ;
2018-04-02 01:25:06 -04:00
public Dictionary < int , Player > PrivilegedClients { get ; set ; }
2017-06-19 13:58:01 -04:00
public ILogger Logger { get ; private set ; }
public bool Running { get ; private set ; }
2018-04-13 02:32:30 -04:00
public EventHandler < GameEvent > ServerEventOccurred { get ; private set ; }
2018-04-18 16:46:53 -04:00
public DateTime StartTime { get ; private set ; }
2017-06-19 13:58:01 -04:00
static ApplicationManager Instance ;
List < AsyncStatus > TaskStatuses ;
2017-05-26 18:49:27 -04:00
List < Command > Commands ;
2017-06-19 13:58:01 -04:00
List < MessageToken > MessageTokens ;
2017-11-25 20:29:58 -05:00
ClientService ClientSvc ;
AliasService AliasSvc ;
PenaltyService PenaltySvc ;
2018-03-18 22:25:11 -04:00
BaseConfigurationHandler < ApplicationConfiguration > ConfigHandler ;
2018-04-08 14:48:40 -04:00
EventApi Api ;
2018-04-26 02:13:04 -04:00
GameEventHandler Handler ;
ManualResetEventSlim OnEvent ;
2017-05-26 18:49:27 -04:00
2017-06-19 13:58:01 -04:00
private ApplicationManager ( )
2015-07-03 00:10:01 -04:00
{
2018-03-25 00:32:54 -04:00
Logger = new Logger ( $@"{Utilities.OperatingDirectory}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-11-25 20:29:58 -05:00
ClientSvc = new ClientService ( ) ;
AliasSvc = new AliasService ( ) ;
PenaltySvc = new PenaltyService ( ) ;
2018-04-02 01:25:06 -04:00
PrivilegedClients = new Dictionary < int , Player > ( ) ;
2018-04-08 14:48:40 -04:00
Api = new EventApi ( ) ;
ServerEventOccurred + = Api . OnServerEvent ;
2018-03-18 22:25:11 -04:00
ConfigHandler = new BaseConfigurationHandler < ApplicationConfiguration > ( "IW4MAdminSettings" ) ;
2018-04-18 16:46:53 -04:00
StartTime = DateTime . UtcNow ;
2018-04-26 02:13:04 -04:00
OnEvent = new ManualResetEventSlim ( ) ;
2018-03-14 01:36:25 -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
}
2018-04-28 01:22:18 -04:00
public async Task UpdateStatus ( object state )
2018-04-26 02:13:04 -04:00
{
2018-04-26 20:19:42 -04:00
var taskList = new List < Task > ( ) ;
2018-04-28 01:22:18 -04:00
while ( Running )
2018-04-26 02:13:04 -04:00
{
2018-04-28 01:22:18 -04:00
taskList . Clear ( ) ;
foreach ( var server in Servers )
{
taskList . Add ( Task . Run ( async ( ) = >
{
try
{
await server . ProcessUpdatesAsync ( new CancellationToken ( ) ) ;
}
catch ( Exception e )
{
Logger . WriteWarning ( $"Failed to update status for {server}" ) ;
Logger . WriteDebug ( $"Exception: {e.Message}" ) ;
Logger . WriteDebug ( $"StackTrace: {e.StackTrace}" ) ;
}
} ) ) ;
}
#if DEBUG
Logger . WriteDebug ( $"{taskList.Count} servers queued for stats updates" ) ;
ThreadPool . GetMaxThreads ( out int workerThreads , out int n ) ;
ThreadPool . GetAvailableThreads ( out int availableThreads , out int m ) ;
Logger . WriteDebug ( $"There are {workerThreads - availableThreads} active threading tasks" ) ;
#endif
await Task . WhenAll ( taskList . ToArray ( ) ) ;
GameEvent sensitiveEvent ;
while ( ( sensitiveEvent = Handler . GetNextSensitiveEvent ( ) ) ! = null )
{
try
{
await sensitiveEvent . Owner . ExecuteEvent ( sensitiveEvent ) ;
#if DEBUG
Logger . WriteDebug ( $"Processed Sensitive Event {sensitiveEvent.Type}" ) ;
#endif
}
2018-05-08 00:58:46 -04:00
catch ( NetworkException e )
{
Logger . WriteError ( Utilities . CurrentLocalization . LocalizationIndex [ "SERVER_ERROR_COMMUNICATION" ] ) ;
Logger . WriteDebug ( e . Message ) ;
}
2018-04-28 01:22:18 -04:00
catch ( Exception E )
{
2018-05-05 16:36:26 -04:00
Logger . WriteError ( $"{Utilities.CurrentLocalization.LocalizationIndex[" SERVER_ERROR_EXCEPTION "]} {sensitiveEvent.Owner}" ) ;
2018-04-28 01:22:18 -04:00
Logger . WriteDebug ( "Error Message: " + E . Message ) ;
Logger . WriteDebug ( "Error Trace: " + E . StackTrace ) ;
}
2018-05-10 01:34:29 -04:00
sensitiveEvent . OnProcessed . Set ( ) ;
2018-04-28 01:22:18 -04:00
}
2018-04-26 20:19:42 -04:00
2018-06-07 22:19:12 -04:00
await Task . Delay ( ConfigHandler . Configuration ( ) . RConPollRate ) ;
2018-04-28 01:22:18 -04:00
}
2018-04-26 02:13:04 -04:00
}
2018-03-06 02:22:19 -05:00
public async Task Init ( )
2015-07-06 13:13:42 -04:00
{
2018-05-10 01:34:29 -04:00
Running = true ;
2018-03-06 02:22:19 -05:00
#region DATABASE
2018-03-27 00:54:20 -04:00
var ipList = ( await ClientSvc . Find ( c = > c . Level > Player . Permission . Trusted ) )
2018-04-04 15:38:34 -04:00
. Select ( c = > new
{
c . Password ,
c . PasswordSalt ,
c . ClientId ,
c . Level ,
c . Name
} ) ;
2018-03-27 00:54:20 -04:00
foreach ( var a in ipList )
{
try
{
2018-04-04 15:38:34 -04:00
PrivilegedClients . Add ( a . ClientId , new Player ( )
2018-04-02 01:25:06 -04:00
{
2018-04-04 15:38:34 -04:00
Name = a . Name ,
2018-04-02 01:25:06 -04:00
ClientId = a . ClientId ,
2018-04-04 15:38:34 -04:00
Level = a . Level ,
PasswordSalt = a . PasswordSalt ,
Password = a . Password
2018-04-02 01:25:06 -04:00
} ) ;
2018-03-27 00:54:20 -04:00
}
catch ( ArgumentException )
{
continue ;
}
}
2017-09-29 22:42:24 -04:00
#endregion
2018-03-18 22:25:11 -04:00
#region CONFIG
var config = ConfigHandler . Configuration ( ) ;
2018-04-19 01:48:14 -04:00
// copy over default config if it doesn't exist
if ( config = = null )
2018-03-18 22:25:11 -04:00
{
2018-04-19 01:48:14 -04:00
var defaultConfig = new BaseConfigurationHandler < DefaultConfiguration > ( "DefaultSettings" ) . Configuration ( ) ;
ConfigHandler . Set ( ( ApplicationConfiguration ) new ApplicationConfiguration ( ) . Generate ( ) ) ;
var newConfig = ConfigHandler . Configuration ( ) ;
newConfig . AutoMessagePeriod = defaultConfig . AutoMessagePeriod ;
newConfig . AutoMessages = defaultConfig . AutoMessages ;
newConfig . GlobalRules = defaultConfig . GlobalRules ;
newConfig . Maps = defaultConfig . Maps ;
if ( newConfig . Servers = = null )
{
ConfigHandler . Set ( newConfig ) ;
2018-04-23 17:03:50 -04:00
newConfig . Servers = new List < ServerConfiguration > ( ) ;
do
{
newConfig . Servers . Add ( ( ServerConfiguration ) new ServerConfiguration ( ) . Generate ( ) ) ;
2018-05-05 16:36:26 -04:00
} while ( Utilities . PromptBool ( Utilities . CurrentLocalization . LocalizationIndex [ "SETUP_SERVER_SAVE" ] ) ) ;
2018-04-23 17:03:50 -04:00
2018-04-19 01:48:14 -04:00
config = newConfig ;
await ConfigHandler . Save ( ) ;
}
2018-03-18 22:25:11 -04:00
}
2018-04-19 01:48:14 -04:00
else if ( config ! = null )
2018-04-18 16:46:53 -04:00
{
if ( string . IsNullOrEmpty ( config . Id ) )
{
config . Id = Guid . NewGuid ( ) . ToString ( ) ;
await ConfigHandler . Save ( ) ;
}
2018-04-19 01:48:14 -04:00
if ( string . IsNullOrEmpty ( config . WebfrontBindUrl ) )
{
config . WebfrontBindUrl = "http://127.0.0.1:1624" ;
await ConfigHandler . Save ( ) ;
}
2018-04-18 16:46:53 -04:00
}
2018-03-18 22:25:11 -04:00
else if ( config . Servers . Count = = 0 )
throw new ServerException ( "A server configuration in IW4MAdminSettings.json is invalid" ) ;
2018-04-21 18:18:20 -04:00
Encoding . RegisterProvider ( CodePagesEncodingProvider . Instance ) ;
2018-04-22 16:04:18 -04:00
Utilities . EncodingType = Encoding . GetEncoding ( ! string . IsNullOrEmpty ( config . CustomParserEncoding ) ? config . CustomParserEncoding : "windows-1252" ) ;
2018-04-21 18:18:20 -04:00
2018-04-16 16:31:14 -04:00
#endregion
2017-08-09 00:35:23 -04:00
#region PLUGINS
2018-04-08 02:44:42 -04:00
SharedLibraryCore . Plugins . PluginImporter . Load ( this ) ;
2017-08-09 00:35:23 -04:00
2018-04-08 02:44:42 -04:00
foreach ( var Plugin in SharedLibraryCore . Plugins . PluginImporter . ActivePlugins )
2017-08-09 00:35:23 -04:00
{
try
{
2018-03-06 02:22:19 -05:00
await Plugin . OnLoadAsync ( this ) ;
2017-08-09 00:35:23 -04:00
}
catch ( Exception e )
{
2018-05-05 16:36:26 -04:00
Logger . WriteError ( $"{Utilities.CurrentLocalization.LocalizationIndex[" SERVER_ERROR_PLUGIN "]} {Plugin.Name}" ) ;
2017-08-09 00:35:23 -04:00
Logger . WriteDebug ( $"Exception: {e.Message}" ) ;
Logger . WriteDebug ( $"Stack Trace: {e.StackTrace}" ) ;
}
}
#endregion
2017-06-19 13:58:01 -04:00
#region COMMANDS
2017-11-25 20:29:58 -05:00
if ( ClientSvc . GetOwners ( ) . Result . Count = = 0 )
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 CFlag ( ) ) ;
2018-05-08 00:58:46 -04:00
Commands . Add ( new CUnflag ( ) ) ;
2017-11-15 16:04:13 -05:00
Commands . Add ( new CReport ( ) ) ;
Commands . Add ( new CListReports ( ) ) ;
Commands . Add ( new CListBanInfo ( ) ) ;
Commands . Add ( new CListAlias ( ) ) ;
Commands . Add ( new CExecuteRCON ( ) ) ;
Commands . Add ( new CPlugins ( ) ) ;
Commands . Add ( new CIP ( ) ) ;
2017-11-18 01:59:37 -05:00
Commands . Add ( new CMask ( ) ) ;
2018-02-10 01:26:38 -05:00
Commands . Add ( new CPruneAdmins ( ) ) ;
2018-05-05 16:36:26 -04:00
Commands . Add ( new CKillServer ( ) ) ;
2018-04-04 15:38:34 -04:00
Commands . Add ( new CSetPassword ( ) ) ;
2018-04-14 00:51:38 -04:00
Commands . Add ( new CPing ( ) ) ;
2018-06-02 00:48:10 -04:00
Commands . Add ( new CSetGravatar ( ) ) ;
2018-06-02 22:21:01 -04:00
Commands . Add ( new CNextMap ( ) ) ;
2017-06-19 13:58:01 -04:00
2018-04-08 02:44:42 -04:00
foreach ( Command C in SharedLibraryCore . Plugins . PluginImporter . ActiveCommands )
2017-06-19 13:58:01 -04:00
Commands . Add ( C ) ;
#endregion
2018-04-16 16:31:14 -04:00
#region INIT
async Task Init ( ServerConfiguration Conf )
{
2018-05-10 01:34:29 -04:00
// setup the event handler after the class is initialized
Handler = new GameEventHandler ( this ) ;
2018-04-16 16:31:14 -04:00
try
{
var ServerInstance = new IW4MServer ( this , Conf ) ;
await ServerInstance . Initialize ( ) ;
lock ( _servers )
{
_servers . Add ( ServerInstance ) ;
}
2018-05-05 16:36:26 -04:00
Logger . WriteVerbose ( $"{Utilities.CurrentLocalization.LocalizationIndex[" MANAGER_MONITORING_TEXT "]} {ServerInstance.Hostname}" ) ;
2018-04-26 02:13:04 -04:00
// add the start event for this server
Handler . AddEvent ( new GameEvent ( GameEvent . EventType . Start , "Server started" , null , null , ServerInstance ) ) ;
2018-04-16 16:31:14 -04:00
}
catch ( ServerException e )
{
2018-05-05 16:36:26 -04:00
Logger . WriteError ( $"{Utilities.CurrentLocalization.LocalizationIndex[" SERVER_ERROR_UNFIXABLE "]} [{Conf.IPAddress}:{Conf.Port}]" ) ;
2018-04-16 16:31:14 -04:00
if ( e . GetType ( ) = = typeof ( DvarException ) )
2018-05-05 16:36:26 -04:00
Logger . WriteDebug ( $"{Utilities.CurrentLocalization.LocalizationIndex[" SERVER_ERROR_DVAR "]} {(e as DvarException).Data[" dvar_name "]} ({Utilities.CurrentLocalization.LocalizationIndex[" SERVER_ERROR_DVAR_HELP "]})" ) ;
2018-04-16 16:31:14 -04:00
else if ( e . GetType ( ) = = typeof ( NetworkException ) )
{
Logger . WriteDebug ( e . Message ) ;
}
// throw the exception to the main method to stop before instantly exiting
throw e ;
}
}
await Task . WhenAll ( config . Servers . Select ( c = > Init ( c ) ) . ToArray ( ) ) ;
#endregion
2015-07-03 00:10:01 -04:00
}
2017-08-09 00:35:23 -04:00
2018-05-17 19:31:58 -04:00
private async Task SendHeartbeat ( object state )
2018-04-18 16:46:53 -04:00
{
2018-04-28 01:22:18 -04:00
var heartbeatState = ( HeartbeatState ) state ;
2018-05-16 00:57:37 -04:00
while ( Running )
2018-04-18 16:46:53 -04:00
{
2018-05-16 00:57:37 -04:00
if ( ! heartbeatState . Connected )
2018-04-18 16:46:53 -04:00
{
2018-05-16 00:57:37 -04:00
try
{
2018-05-17 19:31:58 -04:00
await Heartbeat . Send ( this , true ) ;
2018-05-16 00:57:37 -04:00
heartbeatState . Connected = true ;
}
2018-04-18 16:46:53 -04:00
2018-05-16 00:57:37 -04:00
catch ( Exception e )
{
heartbeatState . Connected = false ;
Logger . WriteWarning ( $"Could not connect to heartbeat server - {e.Message}" ) ;
}
2018-04-18 16:46:53 -04:00
}
2018-05-16 00:57:37 -04:00
else
2018-04-18 16:46:53 -04:00
{
2018-05-16 00:57:37 -04:00
try
{
2018-05-17 19:31:58 -04:00
await Heartbeat . Send ( this ) ;
2018-05-16 00:57:37 -04:00
}
2018-04-18 16:46:53 -04:00
2018-05-16 00:57:37 -04:00
catch ( System . Net . Http . HttpRequestException e )
{
Logger . WriteWarning ( $"Could not send heartbeat - {e.Message}" ) ;
}
2018-04-18 16:46:53 -04:00
2018-05-16 00:57:37 -04:00
catch ( AggregateException e )
2018-04-18 16:46:53 -04:00
{
2018-05-16 00:57:37 -04:00
Logger . WriteWarning ( $"Could not send heartbeat - {e.Message}" ) ;
var exceptions = e . InnerExceptions . Where ( ex = > ex . GetType ( ) = = typeof ( RestEase . ApiException ) ) ;
foreach ( var ex in exceptions )
2018-04-18 16:46:53 -04:00
{
2018-05-16 00:57:37 -04:00
if ( ( ( RestEase . ApiException ) ex ) . StatusCode = = System . Net . HttpStatusCode . Unauthorized )
{
heartbeatState . Connected = false ;
}
2018-04-18 16:46:53 -04:00
}
}
2018-05-16 00:57:37 -04:00
catch ( RestEase . ApiException e )
2018-04-18 16:46:53 -04:00
{
2018-05-16 00:57:37 -04:00
Logger . WriteWarning ( $"Could not send heartbeat - {e.Message}" ) ;
if ( e . StatusCode = = System . Net . HttpStatusCode . Unauthorized )
{
heartbeatState . Connected = false ;
}
}
catch ( Exception e )
{
Logger . WriteWarning ( $"Could not send heartbeat - {e.Message}" ) ;
2018-04-18 16:46:53 -04:00
}
2018-05-16 00:57:37 -04:00
}
2018-05-17 19:31:58 -04:00
await Task . Delay ( 30000 ) ;
2018-04-18 16:46:53 -04:00
}
}
2018-04-28 17:39:45 -04:00
public async Task Start ( )
2015-07-03 00:10:01 -04:00
{
2018-05-16 00:57:37 -04:00
// this needs to be run seperately from the main thread
#pragma warning disable CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed
2018-04-28 01:22:18 -04:00
#if ! DEBUG
// start heartbeat
2018-05-16 00:57:37 -04:00
Task . Run ( ( ) = > SendHeartbeat ( new HeartbeatState ( ) ) ) ;
2018-04-28 01:22:18 -04:00
#endif
Task . Run ( ( ) = > UpdateStatus ( null ) ) ;
2018-05-08 00:58:46 -04:00
#pragma warning restore CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed
var eventList = new List < Task > ( ) ;
async Task processEvent ( GameEvent newEvent )
{
try
{
await newEvent . Owner . ExecuteEvent ( newEvent ) ;
#if DEBUG
Logger . WriteDebug ( "Processed Event" ) ;
#endif
}
2018-04-28 17:39:45 -04:00
2018-05-10 01:34:29 -04:00
// this happens if a plugin requires login
catch ( AuthorizationException e )
{
await newEvent . Origin . Tell ( $"{Utilities.CurrentLocalization.LocalizationIndex[" COMMAND_NOTAUTHORIZED "]} - {e.Message}" ) ;
}
2018-05-08 00:58:46 -04:00
catch ( NetworkException e )
{
Logger . WriteError ( Utilities . CurrentLocalization . LocalizationIndex [ "SERVER_ERROR_COMMUNICATION" ] ) ;
Logger . WriteDebug ( e . Message ) ;
}
catch ( Exception E )
{
Logger . WriteError ( $"{Utilities.CurrentLocalization.LocalizationIndex[" SERVER_ERROR_EXCEPTION "]} {newEvent.Owner}" ) ;
Logger . WriteDebug ( "Error Message: " + E . Message ) ;
Logger . WriteDebug ( "Error Trace: " + E . StackTrace ) ;
}
// tell anyone waiting for the output that we're done
newEvent . OnProcessed . Set ( ) ;
} ;
GameEvent queuedEvent = null ;
2018-04-28 01:22:18 -04:00
2018-04-28 17:39:45 -04:00
while ( Running )
2015-07-03 00:10:01 -04:00
{
2018-04-28 17:39:45 -04:00
// wait for new event to be added
2018-05-17 19:31:58 -04:00
OnEvent . Wait ( ) ;
2018-04-28 01:22:18 -04:00
2018-04-28 17:39:45 -04:00
// todo: sequencially or parallelize?
2018-05-08 00:58:46 -04:00
while ( ( queuedEvent = Handler . GetNextEvent ( ) ) ! = null )
2018-04-28 17:39:45 -04:00
{
2018-05-17 19:31:58 -04:00
await processEvent ( queuedEvent ) ;
2018-04-28 01:22:18 -04:00
}
2018-04-28 17:39:45 -04:00
2018-05-08 00:58:46 -04:00
// this should allow parallel processing of events
2018-05-17 19:31:58 -04:00
// await Task.WhenAll(eventList);
2018-05-08 00:58:46 -04:00
2018-04-28 17:39:45 -04:00
// signal that all events have been processed
OnEvent . Reset ( ) ;
}
2017-05-26 18:49:27 -04:00
#if ! DEBUG
2018-05-10 01:34:29 -04:00
foreach ( var S in _servers )
await S . Broadcast ( "^1" + Utilities . CurrentLocalization . LocalizationIndex [ "BROADCAST_OFFLINE" ] ) ;
2017-05-26 18:49:27 -04:00
#endif
2018-04-28 17:39:45 -04:00
_servers . Clear ( ) ;
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 ;
2018-04-26 02:13:04 -04:00
// trigger the event processing loop to end
SetHasEvent ( ) ;
2015-07-06 15:51:08 -04:00
}
2017-05-27 18:08:04 -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
2017-11-25 20:29:58 -05:00
public ClientService GetClientService ( ) = > ClientSvc ;
public AliasService GetAliasService ( ) = > AliasSvc ;
public PenaltyService GetPenaltyService ( ) = > PenaltySvc ;
2018-03-18 22:25:11 -04:00
public IConfigurationHandler < ApplicationConfiguration > GetApplicationSettings ( ) = > ConfigHandler ;
2018-04-05 00:38:45 -04:00
public IDictionary < int , Player > GetPrivilegedClients ( ) = > PrivilegedClients ;
2018-04-08 14:48:40 -04:00
public IEventApi GetEventApi ( ) = > Api ;
2018-04-08 17:50:58 -04:00
public bool ShutdownRequested ( ) = > ! Running ;
2018-04-26 02:13:04 -04:00
public IEventHandler GetEventHandler ( ) = > Handler ;
public void SetHasEvent ( )
{
OnEvent . Set ( ) ;
}
2018-05-28 21:30:31 -04:00
public IList < Assembly > GetPluginAssemblies ( ) = > SharedLibraryCore . Plugins . PluginImporter . PluginAssemblies ;
2015-07-03 00:10:01 -04:00
}
}