Пример #1
0
 public async Task OnLoadAsync(IManager manager)
 {
     Config = new BaseConfigurationHandler <DiscordAlertCfg>("DiscordAlertCfg");
     if (Config.Configuration() == null)
     {
         Config.Set((DiscordAlertCfg) new DiscordAlertCfg().Generate());
         await Config.Save();
     }
 }
Пример #2
0
 public async Task OnLoadAsync(IManager manager)
 {
     // load custom configuration
     Config = new BaseConfigurationHandler <WelcomeConfiguration>("WelcomePluginSettings");
     if (Config.Configuration() == null)
     {
         Config.Set((WelcomeConfiguration) new WelcomeConfiguration().Generate());
         await Config.Save();
     }
 }
Пример #3
0
        public async Task OnLoadAsync(IManager manager)
        {
            // load custom configuration
            Settings = new BaseConfigurationHandler <Configuration>("ProfanityDetermentSettings");
            if (Settings.Configuration() == null)
            {
                Settings.Set((Configuration) new Configuration().Generate());
                await Settings.Save();
            }

            ProfanityCounts = new ConcurrentDictionary <int, Tracking>();
            Manager         = manager;
        }
Пример #4
0
        public async Task OnLoadAsync(IManager manager)
        {
            AuthorizedClients = new ConcurrentDictionary <int, bool>();

            var cfg = new BaseConfigurationHandler <Configuration>("LoginPluginSettings");

            if (cfg.Configuration() == null)
            {
                cfg.Set((Configuration) new Configuration().Generate());
                await cfg.Save();
            }

            Config = cfg.Configuration();
        }
Пример #5
0
        public async Task OnLoadAsync(IManager manager)
        {
            var cfg = new BaseConfigurationHandler <Configuration>("AutomessageFeedPluginSettings");

            if (cfg.Configuration() == null)
            {
                cfg.Set((Configuration) new Configuration().Generate());
                await cfg.Save();
            }

            _configuration = cfg.Configuration();

            manager.GetMessageTokens().Add(new MessageToken("FEED", GetNextFeedItem));
        }
Пример #6
0
 private ApplicationManager()
 {
     Logger            = new Logger($@"{Utilities.OperatingDirectory}IW4MAdmin.log");
     _servers          = new List <Server>();
     Commands          = new List <Command>();
     TaskStatuses      = new List <AsyncStatus>();
     MessageTokens     = new List <MessageToken>();
     ClientSvc         = new ClientService();
     AliasSvc          = new AliasService();
     PenaltySvc        = new PenaltyService();
     PrivilegedClients = new Dictionary <int, Player>();
     Api = new EventApi();
     ServerEventOccurred    += Api.OnServerEvent;
     ConfigHandler           = new BaseConfigurationHandler <ApplicationConfiguration>("IW4MAdminSettings");
     Console.CancelKeyPress += new ConsoleCancelEventHandler(OnCancelKey);
     StartTime = DateTime.UtcNow;
 }
Пример #7
0
 private ApplicationManager()
 {
     _servers               = new List <Server>();
     Commands               = new List <Command>();
     TaskStatuses           = new List <AsyncStatus>();
     MessageTokens          = new List <MessageToken>();
     ClientSvc              = new ClientService();
     AliasSvc               = new AliasService();
     PenaltySvc             = new PenaltyService();
     ConfigHandler          = new BaseConfigurationHandler <ApplicationConfiguration>("IW4MAdminSettings");
     StartTime              = DateTime.UtcNow;
     OnQuit                 = new ManualResetEventSlim();
     PageList               = new PageList();
     AdditionalEventParsers = new List <IEventParser>();
     AdditionalRConParsers  = new List <IRConParser>();
     OnServerEvent         += OnGameEvent;
     OnServerEvent         += EventApi.OnGameEvent;
     _authenticator         = new TokenAuthentication();
     _metaService           = new MetaService();
 }
Пример #8
0
        public async Task Init()
        {
            #region DATABASE
            var ipList = (await ClientSvc.Find(c => c.Level > Player.Permission.Trusted))
                         .Select(c => new
            {
                c.Password,
                c.PasswordSalt,
                c.ClientId,
                c.Level,
                c.Name
            });

            foreach (var a in ipList)
            {
                try
                {
                    PrivilegedClients.Add(a.ClientId, new Player()
                    {
                        Name         = a.Name,
                        ClientId     = a.ClientId,
                        Level        = a.Level,
                        PasswordSalt = a.PasswordSalt,
                        Password     = a.Password
                    });
                }

                catch (ArgumentException)
                {
                    continue;
                }
            }
            #endregion

            #region CONFIG
            var config = ConfigHandler.Configuration();

            // copy over default config if it doesn't exist
            if (config == null)
            {
                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);
                    newConfig.Servers = new List <ServerConfiguration>();

                    do
                    {
                        newConfig.Servers.Add((ServerConfiguration) new ServerConfiguration().Generate());
                    } while (Utilities.PromptBool(Utilities.CurrentLocalization.LocalizationSet["SETUP_SERVER_SAVE"]));

                    config = newConfig;
                    await ConfigHandler.Save();
                }
            }

            else if (config != null)
            {
                if (string.IsNullOrEmpty(config.Id))
                {
                    config.Id = Guid.NewGuid().ToString();
                    await ConfigHandler.Save();
                }

                if (string.IsNullOrEmpty(config.WebfrontBindUrl))
                {
                    config.WebfrontBindUrl = "http://127.0.0.1:1624";
                    await ConfigHandler.Save();
                }
            }

            else if (config.Servers.Count == 0)
            {
                throw new ServerException("A server configuration in IW4MAdminSettings.json is invalid");
            }

            Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
            Utilities.EncodingType = Encoding.GetEncoding(!string.IsNullOrEmpty(config.CustomParserEncoding) ? config.CustomParserEncoding : "windows-1252");

            #endregion
            #region PLUGINS
            SharedLibraryCore.Plugins.PluginImporter.Load(this);

            foreach (var Plugin in SharedLibraryCore.Plugins.PluginImporter.ActivePlugins)
            {
                try
                {
                    await Plugin.OnLoadAsync(this);
                }

                catch (Exception e)
                {
                    Logger.WriteError($"An error occured loading plugin {Plugin.Name}");
                    Logger.WriteDebug($"Exception: {e.Message}");
                    Logger.WriteDebug($"Stack Trace: {e.StackTrace}");
                }
            }
            #endregion

            #region COMMANDS
            if (ClientSvc.GetOwners().Result.Count == 0)
            {
                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());
            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());
            Commands.Add(new CMask());
            Commands.Add(new CPruneAdmins());
            Commands.Add(new CKillServer());
            Commands.Add(new CSetPassword());
            Commands.Add(new CPing());

            foreach (Command C in SharedLibraryCore.Plugins.PluginImporter.ActiveCommands)
            {
                Commands.Add(C);
            }
            #endregion

            #region INIT
            async Task Init(ServerConfiguration Conf)
            {
                try
                {
                    var ServerInstance = new IW4MServer(this, Conf);
                    await ServerInstance.Initialize();

                    lock (_servers)
                    {
                        _servers.Add(ServerInstance);
                    }

                    Logger.WriteVerbose($"Now monitoring {ServerInstance.Hostname}");

                    // 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);
                    }
                }

                catch (ServerException e)
                {
                    Logger.WriteError($"Not monitoring server {Conf.IPAddress}:{Conf.Port} due to uncorrectable errors");
                    if (e.GetType() == typeof(DvarException))
                    {
                        Logger.WriteDebug($"Could not get the dvar value for {(e as DvarException).Data["dvar_name"]} (ensure the server has a map loaded)");
                    }
                    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

            Running = true;
        }
Пример #9
0
        public async Task Init()
        {
            IsRunning         = true;
            ExternalIPAddress = await Utilities.GetExternalIP();

            #region DATABASE
            _logger.LogInformation("Beginning database migration sync");
            Console.WriteLine(_translationLookup["MANAGER_MIGRATION_START"]);
            await ContextSeed.Seed(_serviceProvider.GetRequiredService <IDatabaseContextFactory>(), _tokenSource.Token);

            await DatabaseHousekeeping.RemoveOldRatings(_serviceProvider.GetRequiredService <IDatabaseContextFactory>(), _tokenSource.Token);

            _logger.LogInformation("Finished database migration sync");
            Console.WriteLine(_translationLookup["MANAGER_MIGRATION_END"]);
            #endregion

            #region PLUGINS
            foreach (var plugin in Plugins)
            {
                try
                {
                    if (plugin is ScriptPlugin scriptPlugin)
                    {
                        await scriptPlugin.Initialize(this, _scriptCommandFactory, _scriptPluginServiceResolver);

                        scriptPlugin.Watcher.Changed += async(sender, e) =>
                        {
                            try
                            {
                                await scriptPlugin.Initialize(this, _scriptCommandFactory, _scriptPluginServiceResolver);
                            }

                            catch (Exception ex)
                            {
                                Console.WriteLine(Utilities.CurrentLocalization.LocalizationIndex["PLUGIN_IMPORTER_ERROR"].FormatExt(scriptPlugin.Name));
                                _logger.LogError(ex, "Could not properly load plugin {plugin}", scriptPlugin.Name);
                            }
                        };
                    }

                    else
                    {
                        await plugin.OnLoadAsync(this);
                    }
                }

                catch (Exception ex)
                {
                    _logger.LogError(ex, $"{_translationLookup["SERVER_ERROR_PLUGIN"]} {plugin.Name}");
                }
            }
            #endregion

            #region CONFIG
            // copy over default config if it doesn't exist
            if (!_appConfig.Servers?.Any() ?? true)
            {
                var defaultConfig = new BaseConfigurationHandler <DefaultSettings>("DefaultSettings").Configuration();
                //ConfigHandler.Set((ApplicationConfiguration)new ApplicationConfiguration().Generate());
                //var newConfig = ConfigHandler.Configuration();

                _appConfig.AutoMessages          = defaultConfig.AutoMessages;
                _appConfig.GlobalRules           = defaultConfig.GlobalRules;
                _appConfig.DisallowedClientNames = defaultConfig.DisallowedClientNames;

                //if (newConfig.Servers == null)
                {
                    ConfigHandler.Set(_appConfig);
                    _appConfig.Servers = new ServerConfiguration[1];

                    do
                    {
                        var serverConfig = new ServerConfiguration();
                        foreach (var parser in AdditionalRConParsers)
                        {
                            serverConfig.AddRConParser(parser);
                        }

                        foreach (var parser in AdditionalEventParsers)
                        {
                            serverConfig.AddEventParser(parser);
                        }

                        _appConfig.Servers = _appConfig.Servers.Where(_servers => _servers != null).Append((ServerConfiguration)serverConfig.Generate()).ToArray();
                    } while (Utilities.PromptBool(_translationLookup["SETUP_SERVER_SAVE"]));

                    await ConfigHandler.Save();
                }
            }

            else
            {
                if (string.IsNullOrEmpty(_appConfig.Id))
                {
                    _appConfig.Id = Guid.NewGuid().ToString();
                    await ConfigHandler.Save();
                }

                if (string.IsNullOrEmpty(_appConfig.WebfrontBindUrl))
                {
                    _appConfig.WebfrontBindUrl = "http://0.0.0.0:1624";
                    await ConfigHandler.Save();
                }

#pragma warning disable 618
                if (_appConfig.Maps != null)
                {
                    _appConfig.Maps = null;
                }

                if (_appConfig.QuickMessages != null)
                {
                    _appConfig.QuickMessages = null;
                }
#pragma warning restore 618

                var validator        = new ApplicationConfigurationValidator();
                var validationResult = validator.Validate(_appConfig);

                if (!validationResult.IsValid)
                {
                    throw new ConfigurationException("MANAGER_CONFIGURATION_ERROR")
                          {
                              Errors = validationResult.Errors.Select(_error => _error.ErrorMessage).ToArray(),
                              ConfigurationFileName = ConfigHandler.FileName
                          };
                }

                foreach (var serverConfig in _appConfig.Servers)
                {
                    ConfigurationMigration.ModifyLogPath020919(serverConfig);

                    if (serverConfig.RConParserVersion == null || serverConfig.EventParserVersion == null)
                    {
                        foreach (var parser in AdditionalRConParsers)
                        {
                            serverConfig.AddRConParser(parser);
                        }

                        foreach (var parser in AdditionalEventParsers)
                        {
                            serverConfig.AddEventParser(parser);
                        }

                        serverConfig.ModifyParsers();
                    }
                    await ConfigHandler.Save();
                }
            }

            if (_appConfig.Servers.Length == 0)
            {
                throw new ServerException("A server configuration in IW4MAdminSettings.json is invalid");
            }

            Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
            Utilities.EncodingType = Encoding.GetEncoding(!string.IsNullOrEmpty(_appConfig.CustomParserEncoding) ? _appConfig.CustomParserEncoding : "windows-1252");

            foreach (var parser in AdditionalRConParsers)
            {
                if (!parser.Configuration.ColorCodeMapping.ContainsKey(ColorCodes.Accent.ToString()))
                {
                    parser.Configuration.ColorCodeMapping.Add(ColorCodes.Accent.ToString(),
                                                              parser.Configuration.ColorCodeMapping.TryGetValue(_appConfig.IngameAccentColorKey, out var colorCode)
                            ? colorCode
                            : "");
                }
            }

            #endregion

            #region COMMANDS
            if (await ClientSvc.HasOwnerAsync(_tokenSource.Token))
            {
                _commands.RemoveAll(_cmd => _cmd.GetType() == typeof(OwnerCommand));
            }

            List <IManagerCommand> commandsToAddToConfig = new List <IManagerCommand>();
            var cmdConfig = _commandConfiguration.Configuration();

            if (cmdConfig == null)
            {
                cmdConfig = new CommandConfiguration();
                commandsToAddToConfig.AddRange(_commands);
            }

            else
            {
                var unsavedCommands = _commands.Where(_cmd => !cmdConfig.Commands.Keys.Contains(_cmd.CommandConfigNameForType()));
                commandsToAddToConfig.AddRange(unsavedCommands);
            }

            // this is because I want to store the command prefix in IW4MAdminSettings, but can't easily
            // inject it to all the places that need it
            cmdConfig.CommandPrefix          = _appConfig?.CommandPrefix ?? "!";
            cmdConfig.BroadcastCommandPrefix = _appConfig?.BroadcastCommandPrefix ?? "@";

            foreach (var cmd in commandsToAddToConfig)
            {
                if (cmdConfig.Commands.ContainsKey(cmd.CommandConfigNameForType()))
                {
                    continue;
                }
                cmdConfig.Commands.Add(cmd.CommandConfigNameForType(),
                                       new CommandProperties
                {
                    Name               = cmd.Name,
                    Alias              = cmd.Alias,
                    MinimumPermission  = cmd.Permission,
                    AllowImpersonation = cmd.AllowImpersonation,
                    SupportedGames     = cmd.SupportedGames
                });
            }

            _commandConfiguration.Set(cmdConfig);
            await _commandConfiguration.Save();

            #endregion

            _metaRegistration.Register();

            #region CUSTOM_EVENTS
            foreach (var customEvent in _customParserEvents.SelectMany(_events => _events.Events))
            {
                foreach (var parser in AdditionalEventParsers)
                {
                    parser.RegisterCustomEvent(customEvent.Item1, customEvent.Item2, customEvent.Item3);
                }
            }
            #endregion

            Console.WriteLine(_translationLookup["MANAGER_COMMUNICATION_INFO"]);
            await InitializeServers();
        }
Пример #10
0
        public async Task OnLoadAsync(IManager manager)
        {
            // load custom configuration
            Config = new BaseConfigurationHandler <StatsConfiguration>("StatsPluginSettings");
            if (Config.Configuration() == null)
            {
                Config.Set((StatsConfiguration) new StatsConfiguration().Generate());
                await Config.Save();
            }

            // meta data info
            async Task <List <ProfileMeta> > getStats(int clientId)
            {
                var statsSvc    = new GenericRepository <EFClientStatistics>();
                var clientStats = await statsSvc.FindAsync(c => c.ClientId == clientId);

                int    kills  = clientStats.Sum(c => c.Kills);
                int    deaths = clientStats.Sum(c => c.Deaths);
                double kdr    = Math.Round(kills / (double)deaths, 2);
                double skill  = Math.Round(clientStats.Sum(c => c.Skill) / clientStats.Count, 2);
                double spm    = Math.Round(clientStats.Sum(c => c.SPM), 1);

                return(new List <ProfileMeta>()
                {
                    new ProfileMeta()
                    {
                        Key = "Kills",
                        Value = kills
                    },
                    new ProfileMeta()
                    {
                        Key = "Deaths",
                        Value = deaths
                    },
                    new ProfileMeta()
                    {
                        Key = "KDR",
                        Value = kdr
                    },
                    new ProfileMeta()
                    {
                        Key = "Skill",
                        Value = skill
                    },
                    new ProfileMeta()
                    {
                        Key = "Score Per Minute",
                        Value = spm
                    }
                });
            }

            async Task <List <ProfileMeta> > getAnticheatInfo(int clientId)
            {
                var statsSvc    = new GenericRepository <EFClientStatistics>();
                var clientStats = await statsSvc.FindAsync(c => c.ClientId == clientId);

                double headRatio         = 0;
                double chestRatio        = 0;
                double abdomenRatio      = 0;
                double chestAbdomenRatio = 0;
                double hitOffsetAverage  = 0;

                if (clientStats.Where(cs => cs.HitLocations.Count > 0).FirstOrDefault() != null)
                {
                    chestRatio = Math.Round(clientStats.Where(c => c.HitLocations.Count > 0).Sum(c =>
                                                                                                 c.HitLocations.First(hl => hl.Location == IW4Info.HitLocation.torso_upper).HitCount) /
                                            (double)clientStats.Where(c => c.HitLocations.Count > 0)
                                            .Sum(c => c.HitLocations.Where(hl => hl.Location != IW4Info.HitLocation.none).Sum(f => f.HitCount)), 2);

                    abdomenRatio = Math.Round(clientStats.Where(c => c.HitLocations.Count > 0).Sum(c =>
                                                                                                   c.HitLocations.First(hl => hl.Location == IW4Info.HitLocation.torso_lower).HitCount) /
                                              (double)clientStats.Where(c => c.HitLocations.Count > 0).Sum(c => c.HitLocations.Where(hl => hl.Location != IW4Info.HitLocation.none).Sum(f => f.HitCount)), 2);

                    chestAbdomenRatio = Math.Round(clientStats.Where(c => c.HitLocations.Count > 0).Sum(cs => cs.HitLocations.First(hl => hl.Location == IW4Info.HitLocation.torso_upper).HitCount) /
                                                   (double)clientStats.Where(c => c.HitLocations.Count > 0).Sum(cs => cs.HitLocations.First(hl => hl.Location == IW4Info.HitLocation.torso_lower).HitCount), 2);

                    headRatio = Math.Round(clientStats.Where(c => c.HitLocations.Count > 0).Sum(cs => cs.HitLocations.First(hl => hl.Location == IW4Info.HitLocation.head).HitCount) /
                                           (double)clientStats.Where(c => c.HitLocations.Count > 0)
                                           .Sum(c => c.HitLocations.Where(hl => hl.Location != IW4Info.HitLocation.none).Sum(f => f.HitCount)), 2);

                    hitOffsetAverage = clientStats.Sum(c => c.AverageHitOffset) / Math.Max(1, clientStats.Where(c => c.AverageHitOffset > 0).Count());
                }

                return(new List <ProfileMeta>()
                {
                    new ProfileMeta()
                    {
                        Key = "Chest Ratio",
                        Value = chestRatio,
                        Sensitive = true
                    },
                    new ProfileMeta()
                    {
                        Key = "Abdomen Ratio",
                        Value = abdomenRatio,
                        Sensitive = true
                    },
                    new ProfileMeta()
                    {
                        Key = "Chest To Abdomen Ratio",
                        Value = chestAbdomenRatio,
                        Sensitive = true
                    },
                    new ProfileMeta()
                    {
                        Key = "Headshot Ratio",
                        Value = headRatio,
                        Sensitive = true
                    },
                    new ProfileMeta()
                    {
                        Key = "Hit Offset Average",
                        Value = $"{Math.Round(((float)hitOffsetAverage).ToDegrees(), 4)}°",
                        Sensitive = true
                    }
                });
            }

            async Task <List <ProfileMeta> > getMessages(int clientId)
            {
                var messageSvc = new GenericRepository <EFClientMessage>();
                var messages   = await messageSvc.FindAsync(m => m.ClientId == clientId);

                var messageMeta = messages.Select(m => new ProfileMeta()
                {
                    Key   = "EventMessage",
                    Value = m.Message,
                    When  = m.TimeSent
                }).ToList();

                messageMeta.Add(new ProfileMeta()
                {
                    Key   = "Messages",
                    Value = messages.Count
                });

                return(messageMeta);
            }

            MetaService.AddMeta(getStats);

            if (Config.Configuration().EnableAntiCheat)
            {
                MetaService.AddMeta(getAnticheatInfo);
            }

            MetaService.AddMeta(getMessages);

            string totalKills()
            {
                var serverStats = new GenericRepository <EFServerStatistics>();

                return(serverStats.Find(s => s.Active)
                       .Sum(c => c.TotalKills).ToString("#,##0"));
            }

            string totalPlayTime()
            {
                var serverStats = new GenericRepository <EFServerStatistics>();

                return(Math.Ceiling((serverStats.GetQuery(s => s.Active)
                                     .Sum(c => c.TotalPlayTime) / 3600.0)).ToString("#,##0"));
            }

            manager.GetMessageTokens().Add(new MessageToken("TOTALKILLS", totalKills));
            manager.GetMessageTokens().Add(new MessageToken("TOTALPLAYTIME", totalPlayTime));

            ServerManager = manager;

            Manager = new StatManager(manager);
        }
Пример #11
0
        public async Task OnLoadAsync(IManager manager)
        {
            // load custom configuration
            Config = new BaseConfigurationHandler <StatsConfiguration>("StatsPluginSettings");
            if (Config.Configuration() == null)
            {
                Config.Set((StatsConfiguration) new StatsConfiguration().Generate());
                await Config.Save();
            }

            // register the topstats page
            // todo:generate the URL/Location instead of hardcoding
            manager.GetPageList()
            .Pages.Add(
                Utilities.CurrentLocalization.LocalizationIndex["PLUGINS_STATS_COMMANDS_TOP_TEXT"],
                "/Stats/TopPlayersAsync");

            // meta data info
            async Task <List <ProfileMeta> > getStats(int clientId, int offset, int count, DateTime?startAt)
            {
                if (count > 1)
                {
                    return(new List <ProfileMeta>());
                }

                IList <EFClientStatistics> clientStats;

                using (var ctx = new DatabaseContext(disableTracking: true))
                {
                    clientStats = await ctx.Set <EFClientStatistics>().Where(c => c.ClientId == clientId).ToListAsync();
                }

                int    kills  = clientStats.Sum(c => c.Kills);
                int    deaths = clientStats.Sum(c => c.Deaths);
                double kdr    = Math.Round(kills / (double)deaths, 2);
                var    validPerformanceValues = clientStats.Where(c => c.Performance > 0);
                int    performancePlayTime    = validPerformanceValues.Sum(s => s.TimePlayed);
                double performance            = Math.Round(validPerformanceValues.Sum(c => c.Performance * c.TimePlayed / performancePlayTime), 2);
                double spm = Math.Round(clientStats.Sum(c => c.SPM) / clientStats.Where(c => c.SPM > 0).Count(), 1);

                return(new List <ProfileMeta>()
                {
                    new ProfileMeta()
                    {
                        Key = Utilities.CurrentLocalization.LocalizationIndex["WEBFRONT_CLIENT_META_RANKING"],
                        Value = "#" + (await StatManager.GetClientOverallRanking(clientId)).ToString("#,##0", new System.Globalization.CultureInfo(Utilities.CurrentLocalization.LocalizationName)),
                        Column = 0,
                        Order = 0,
                        Type = ProfileMeta.MetaType.Information
                    },
                    new ProfileMeta()
                    {
                        Key = Utilities.CurrentLocalization.LocalizationIndex["PLUGINS_STATS_TEXT_KILLS"],
                        Value = kills.ToString("#,##0", new System.Globalization.CultureInfo(Utilities.CurrentLocalization.LocalizationName)),
                        Column = 0,
                        Order = 1,
                        Type = ProfileMeta.MetaType.Information
                    },
                    new ProfileMeta()
                    {
                        Key = Utilities.CurrentLocalization.LocalizationIndex["PLUGINS_STATS_TEXT_DEATHS"],
                        Value = deaths.ToString("#,##0", new System.Globalization.CultureInfo(Utilities.CurrentLocalization.LocalizationName)),
                        Column = 0,
                        Order = 2,
                        Type = ProfileMeta.MetaType.Information
                    },
                    new ProfileMeta()
                    {
                        Key = Utilities.CurrentLocalization.LocalizationIndex["PLUGINS_STATS_TEXT_KDR"],
                        Value = kdr.ToString(new System.Globalization.CultureInfo(Utilities.CurrentLocalization.LocalizationName)),
                        Column = 0,
                        Order = 3,
                        Type = ProfileMeta.MetaType.Information
                    },
                    new ProfileMeta()
                    {
                        Key = Utilities.CurrentLocalization.LocalizationIndex["PLUGINS_STATS_COMMANDS_PERFORMANCE"],
                        Value = performance.ToString("#,##0", new System.Globalization.CultureInfo(Utilities.CurrentLocalization.LocalizationName)),
                        Column = 0,
                        Order = 4,
                        Type = ProfileMeta.MetaType.Information
                    },
                    new ProfileMeta()
                    {
                        Key = Utilities.CurrentLocalization.LocalizationIndex["PLUGINS_STATS_META_SPM"],
                        Value = spm.ToString(new System.Globalization.CultureInfo(Utilities.CurrentLocalization.LocalizationName)),
                        Column = 0,
                        Order = 5,
                        Type = ProfileMeta.MetaType.Information
                    }
                });
            }

            async Task <List <ProfileMeta> > getAnticheatInfo(int clientId, int offset, int count, DateTime?startAt)
            {
                if (count > 1)
                {
                    return(new List <ProfileMeta>());
                }

                IList <EFClientStatistics> clientStats;

                using (var ctx = new DatabaseContext(disableTracking: true))
                {
                    clientStats = await ctx.Set <EFClientStatistics>()
                                  .Include(c => c.HitLocations)
                                  .Where(c => c.ClientId == clientId)
                                  .ToListAsync();
                }

                double headRatio         = 0;
                double chestRatio        = 0;
                double abdomenRatio      = 0;
                double chestAbdomenRatio = 0;
                double hitOffsetAverage  = 0;
                double maxStrain         = clientStats.Count(c => c.MaxStrain > 0) == 0 ? 0 : clientStats.Max(cs => cs.MaxStrain);

                if (clientStats.Where(cs => cs.HitLocations.Count > 0).FirstOrDefault() != null)
                {
                    chestRatio = Math.Round((clientStats.Where(c => c.HitLocations.Count > 0).Sum(c =>
                                                                                                  c.HitLocations.First(hl => hl.Location == IW4Info.HitLocation.torso_upper).HitCount) /
                                             (double)clientStats.Where(c => c.HitLocations.Count > 0)
                                             .Sum(c => c.HitLocations.Where(hl => hl.Location != IW4Info.HitLocation.none).Sum(f => f.HitCount))) * 100.0, 0);

                    abdomenRatio = Math.Round((clientStats.Where(c => c.HitLocations.Count > 0).Sum(c =>
                                                                                                    c.HitLocations.First(hl => hl.Location == IW4Info.HitLocation.torso_lower).HitCount) /
                                               (double)clientStats.Where(c => c.HitLocations.Count > 0).Sum(c => c.HitLocations.Where(hl => hl.Location != IW4Info.HitLocation.none).Sum(f => f.HitCount))) * 100.0, 0);

                    chestAbdomenRatio = Math.Round((clientStats.Where(c => c.HitLocations.Count > 0).Sum(cs => cs.HitLocations.First(hl => hl.Location == IW4Info.HitLocation.torso_upper).HitCount) /
                                                    (double)clientStats.Where(c => c.HitLocations.Count > 0).Sum(cs => cs.HitLocations.First(hl => hl.Location == IW4Info.HitLocation.torso_lower).HitCount)) * 100.0, 0);

                    headRatio = Math.Round((clientStats.Where(c => c.HitLocations.Count > 0).Sum(cs => cs.HitLocations.First(hl => hl.Location == IW4Info.HitLocation.head).HitCount) /
                                            (double)clientStats.Where(c => c.HitLocations.Count > 0)
                                            .Sum(c => c.HitLocations.Where(hl => hl.Location != IW4Info.HitLocation.none).Sum(f => f.HitCount))) * 100.0, 0);

                    var validOffsets = clientStats.Where(c => c.HitLocations.Count(hl => hl.HitCount > 0) > 0).SelectMany(hl => hl.HitLocations);
                    hitOffsetAverage = validOffsets.Sum(o => o.HitCount * o.HitOffsetAverage) / (double)validOffsets.Sum(o => o.HitCount);
                }

                return(new List <ProfileMeta>()
                {
                    new ProfileMeta()
                    {
                        Key = $"{Utilities.CurrentLocalization.LocalizationIndex["WEBFRONT_CLIENT_META_AC_METRIC"]} 1",
                        Value = chestRatio.ToString(new System.Globalization.CultureInfo(Utilities.CurrentLocalization.LocalizationName)) + '%',
                        Type = ProfileMeta.MetaType.Information,
                        Column = 2,
                        Order = 0,
                        Extra = Utilities.CurrentLocalization.LocalizationIndex["WEBFRONT_CLIENT_TITLE_ACM1"],
                        Sensitive = true
                    },
                    new ProfileMeta()
                    {
                        Key = $"{Utilities.CurrentLocalization.LocalizationIndex["WEBFRONT_CLIENT_META_AC_METRIC"]} 2",
                        Value = abdomenRatio.ToString(new System.Globalization.CultureInfo(Utilities.CurrentLocalization.LocalizationName)) + '%',
                        Type = ProfileMeta.MetaType.Information,
                        Column = 2,
                        Order = 1,
                        Extra = Utilities.CurrentLocalization.LocalizationIndex["WEBFRONT_CLIENT_TITLE_ACM2"],
                        Sensitive = true
                    },
                    new ProfileMeta()
                    {
                        Key = $"{Utilities.CurrentLocalization.LocalizationIndex["WEBFRONT_CLIENT_META_AC_METRIC"]} 3",
                        Value = chestAbdomenRatio.ToString(new System.Globalization.CultureInfo(Utilities.CurrentLocalization.LocalizationName)) + '%',
                        Type = ProfileMeta.MetaType.Information,
                        Column = 2,
                        Order = 2,
                        Extra = Utilities.CurrentLocalization.LocalizationIndex["WEBFRONT_CLIENT_TITLE_ACM3"],
                        Sensitive = true
                    },
                    new ProfileMeta()
                    {
                        Key = $"{Utilities.CurrentLocalization.LocalizationIndex["WEBFRONT_CLIENT_META_AC_METRIC"]} 4",
                        Value = headRatio.ToString(new System.Globalization.CultureInfo(Utilities.CurrentLocalization.LocalizationName)) + '%',
                        Type = ProfileMeta.MetaType.Information,
                        Column = 2,
                        Order = 3,
                        Extra = Utilities.CurrentLocalization.LocalizationIndex["WEBFRONT_CLIENT_TITLE_ACM4"],
                        Sensitive = true
                    },
                    new ProfileMeta()
                    {
                        Key = $"{Utilities.CurrentLocalization.LocalizationIndex["WEBFRONT_CLIENT_META_AC_METRIC"]} 5",
                        // todo: make sure this is wrapped somewhere else
                        Value = $"{Math.Round(((float)hitOffsetAverage), 4).ToString(new System.Globalization.CultureInfo(Utilities.CurrentLocalization.LocalizationName))}°",
                        Type = ProfileMeta.MetaType.Information,
                        Column = 2,
                        Order = 4,
                        Extra = Utilities.CurrentLocalization.LocalizationIndex["WEBFRONT_CLIENT_TITLE_ACM5"],
                        Sensitive = true
                    },
                    new ProfileMeta()
                    {
                        Key = $"{Utilities.CurrentLocalization.LocalizationIndex["WEBFRONT_CLIENT_META_AC_METRIC"]} 6",
                        Value = Math.Round(maxStrain, 3).ToString(new System.Globalization.CultureInfo(Utilities.CurrentLocalization.LocalizationName)),
                        Type = ProfileMeta.MetaType.Information,
                        Column = 2,
                        Order = 5,
                        Extra = Utilities.CurrentLocalization.LocalizationIndex["WEBFRONT_CLIENT_TITLE_ACM6"],
                        Sensitive = true
                    },
                });
            }

            async Task <List <ProfileMeta> > getMessages(int clientId, int offset, int count, DateTime?startAt)
            {
                if (count <= 1)
                {
                    using (var ctx = new DatabaseContext(true))
                    {
                        return(new List <ProfileMeta>
                        {
                            new ProfileMeta()
                            {
                                Key = Utilities.CurrentLocalization.LocalizationIndex["WEBFRONT_PROFILE_MESSAGES"],
                                Value = (await ctx.Set <EFClientMessage>()
                                         .CountAsync(_message => _message.ClientId == clientId))
                                        .ToString("#,##0", new System.Globalization.CultureInfo(Utilities.CurrentLocalization.LocalizationName)),
                                Column = 1,
                                Order = 4,
                                Type = ProfileMeta.MetaType.Information
                            }
                        });
                    }
                }

                List <ProfileMeta> messageMeta;

                using (var ctx = new DatabaseContext(disableTracking: true))
                {
                    var messages = ctx.Set <EFClientMessage>()
                                   .Where(m => m.ClientId == clientId)
                                   .Where(_message => _message.TimeSent < startAt)
                                   .OrderByDescending(_message => _message.TimeSent)
                                   .Skip(offset)
                                   .Take(count);

                    messageMeta = await messages.Select(m => new ProfileMeta()
                    {
                        Key   = null,
                        Value = new { m.Message, m.Server.GameName },
                        When  = m.TimeSent,
                        Extra = m.ServerId.ToString(),
                        Type  = ProfileMeta.MetaType.ChatMessage
                    }).ToListAsync();

                    foreach (var message in messageMeta)
                    {
                        if ((message.Value.Message as string).IsQuickMessage())
                        {
                            try
                            {
                                var quickMessages = ServerManager.GetApplicationSettings().Configuration()
                                                    .QuickMessages
                                                    .First(_qm => _qm.Game == message.Value.GameName);
                                message.Value = quickMessages.Messages[(message.Value.Message as string).Substring(1)];
                                message.Type  = ProfileMeta.MetaType.QuickMessage;
                            }
                            catch
                            {
                                message.Value = message.Value.Message;
                            }
                        }

                        else
                        {
                            message.Value = message.Value.Message;
                        }
                    }
                }

                return(messageMeta);
            }

            if (Config.Configuration().EnableAntiCheat)
            {
                MetaService.AddRuntimeMeta(getAnticheatInfo);
            }

            MetaService.AddRuntimeMeta(getStats);
            MetaService.AddRuntimeMeta(getMessages);

            async Task <string> totalKills(Server server)
            {
                using (var ctx = new DatabaseContext(disableTracking: true))
                {
                    long kills = await ctx.Set <EFServerStatistics>().Where(s => s.Active).SumAsync(s => s.TotalKills);

                    return(kills.ToString("#,##0", new System.Globalization.CultureInfo(Utilities.CurrentLocalization.LocalizationName)));
                }
            }

            async Task <string> totalPlayTime(Server server)
            {
                using (var ctx = new DatabaseContext(disableTracking: true))
                {
                    long playTime = await ctx.Set <EFServerStatistics>().Where(s => s.Active).SumAsync(s => s.TotalPlayTime);

                    return((playTime / 3600.0).ToString("#,##0", new System.Globalization.CultureInfo(Utilities.CurrentLocalization.LocalizationName)));
                }
            }

            async Task <string> topStats(Server s)
            {
                return(string.Join(Environment.NewLine, await Commands.TopStats.GetTopStats(s)));
            }

            async Task <string> mostPlayed(Server s)
            {
                return(string.Join(Environment.NewLine, await Commands.MostPlayed.GetMostPlayed(s)));
            }

            manager.GetMessageTokens().Add(new MessageToken("TOTALKILLS", totalKills));
            manager.GetMessageTokens().Add(new MessageToken("TOTALPLAYTIME", totalPlayTime));
            manager.GetMessageTokens().Add(new MessageToken("TOPSTATS", topStats));
            manager.GetMessageTokens().Add(new MessageToken("MOSTPLAYED", mostPlayed));

            ServerManager = manager;
            Manager       = new StatManager(manager);
        }
Пример #12
0
        public async Task Init()
        {
            Running           = true;
            ExternalIPAddress = await Utilities.GetExternalIP();

            #region PLUGINS
            SharedLibraryCore.Plugins.PluginImporter.Load(this);

            foreach (var Plugin in SharedLibraryCore.Plugins.PluginImporter.ActivePlugins)
            {
                try
                {
                    await Plugin.OnLoadAsync(this);
                }

                catch (Exception ex)
                {
                    Logger.WriteError($"{Utilities.CurrentLocalization.LocalizationIndex["SERVER_ERROR_PLUGIN"]} {Plugin.Name}");
                    Logger.WriteDebug(ex.GetExceptionInfo());
                }
            }
            #endregion

            #region CONFIG
            var config = ConfigHandler.Configuration();

            // copy over default config if it doesn't exist
            if (config == null)
            {
                var defaultConfig = new BaseConfigurationHandler <DefaultConfiguration>("DefaultSettings").Configuration();
                ConfigHandler.Set((ApplicationConfiguration) new ApplicationConfiguration().Generate());
                var newConfig = ConfigHandler.Configuration();

                newConfig.AutoMessages          = defaultConfig.AutoMessages;
                newConfig.GlobalRules           = defaultConfig.GlobalRules;
                newConfig.Maps                  = defaultConfig.Maps;
                newConfig.DisallowedClientNames = defaultConfig.DisallowedClientNames;
                newConfig.QuickMessages         = defaultConfig.QuickMessages;

                if (newConfig.Servers == null)
                {
                    ConfigHandler.Set(newConfig);
                    newConfig.Servers = new List <ServerConfiguration>();

                    do
                    {
                        var serverConfig = new ServerConfiguration();
                        foreach (var parser in AdditionalRConParsers)
                        {
                            serverConfig.AddRConParser(parser);
                        }

                        foreach (var parser in AdditionalEventParsers)
                        {
                            serverConfig.AddEventParser(parser);
                        }

                        newConfig.Servers.Add((ServerConfiguration)serverConfig.Generate());
                    } while (Utilities.PromptBool(Utilities.CurrentLocalization.LocalizationIndex["SETUP_SERVER_SAVE"]));

                    config = newConfig;
                    await ConfigHandler.Save();
                }
            }

            else
            {
                if (string.IsNullOrEmpty(config.Id))
                {
                    config.Id = Guid.NewGuid().ToString();
                    await ConfigHandler.Save();
                }

                if (string.IsNullOrEmpty(config.WebfrontBindUrl))
                {
                    config.WebfrontBindUrl = "http://0.0.0.0:1624";
                    await ConfigHandler.Save();
                }

                foreach (var serverConfig in config.Servers)
                {
                    Migration.ConfigurationMigration.ModifyLogPath020919(serverConfig);

                    if (serverConfig.RConParserVersion == null || serverConfig.EventParserVersion == null)
                    {
                        foreach (var parser in AdditionalRConParsers)
                        {
                            serverConfig.AddRConParser(parser);
                        }

                        foreach (var parser in AdditionalEventParsers)
                        {
                            serverConfig.AddEventParser(parser);
                        }

                        serverConfig.ModifyParsers();
                    }
                    await ConfigHandler.Save();
                }
            }

            if (config.Servers.Count == 0)
            {
                throw new ServerException("A server configuration in IW4MAdminSettings.json is invalid");
            }

            Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
            Utilities.EncodingType = Encoding.GetEncoding(!string.IsNullOrEmpty(config.CustomParserEncoding) ? config.CustomParserEncoding : "windows-1252");

            #endregion

            #region DATABASE
            using (var db = new DatabaseContext(GetApplicationSettings().Configuration()?.ConnectionString,
                                                GetApplicationSettings().Configuration()?.DatabaseProvider))
            {
                await new ContextSeed(db).Seed();
            }

            PrivilegedClients = (await ClientSvc.GetPrivilegedClients()).ToDictionary(_client => _client.ClientId);
            #endregion

            #region COMMANDS
            if (ClientSvc.GetOwners().Result.Count == 0)
            {
                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());
            Commands.Add(new CUnflag());
            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());
            Commands.Add(new CMask());
            Commands.Add(new CPruneAdmins());
            Commands.Add(new CKillServer());
            Commands.Add(new CSetPassword());
            Commands.Add(new CPing());
            Commands.Add(new CSetGravatar());
            Commands.Add(new CNextMap());
            Commands.Add(new RequestTokenCommand());

            foreach (Command C in SharedLibraryCore.Plugins.PluginImporter.ActiveCommands)
            {
                Commands.Add(C);
            }
            #endregion

            #region META
            async Task <List <ProfileMeta> > getProfileMeta(int clientId, int offset, int count, DateTime?startAt)
            {
                var metaList = new List <ProfileMeta>();

                // we don't want to return anything because it means we're trying to retrieve paged meta data
                if (count > 1)
                {
                    return(metaList);
                }

                var lastMapMeta = await _metaService.GetPersistentMeta("LastMapPlayed", new EFClient()
                {
                    ClientId = clientId
                });

                if (lastMapMeta != null)
                {
                    metaList.Add(new ProfileMeta()
                    {
                        Id    = lastMapMeta.MetaId,
                        Key   = Utilities.CurrentLocalization.LocalizationIndex["WEBFRONT_CLIENT_META_LAST_MAP"],
                        Value = lastMapMeta.Value,
                        Show  = true,
                        Type  = ProfileMeta.MetaType.Information,
                    });
                }

                var lastServerMeta = await _metaService.GetPersistentMeta("LastServerPlayed", new EFClient()
                {
                    ClientId = clientId
                });

                if (lastServerMeta != null)
                {
                    metaList.Add(new ProfileMeta()
                    {
                        Id    = lastServerMeta.MetaId,
                        Key   = Utilities.CurrentLocalization.LocalizationIndex["WEBFRONT_CLIENT_META_LAST_SERVER"],
                        Value = lastServerMeta.Value,
                        Show  = true,
                        Type  = ProfileMeta.MetaType.Information
                    });
                }

                var client = await GetClientService().Get(clientId);

                metaList.Add(new ProfileMeta()
                {
                    Id     = client.ClientId,
                    Key    = $"{Utilities.CurrentLocalization.LocalizationIndex["GLOBAL_TIME_HOURS"]} {Utilities.CurrentLocalization.LocalizationIndex["WEBFRONT_PROFILE_PLAYER"]}",
                    Value  = Math.Round(client.TotalConnectionTime / 3600.0, 1).ToString("#,##0", new System.Globalization.CultureInfo(Utilities.CurrentLocalization.LocalizationName)),
                    Show   = true,
                    Column = 1,
                    Order  = 0,
                    Type   = ProfileMeta.MetaType.Information
                });

                metaList.Add(new ProfileMeta()
                {
                    Id     = client.ClientId,
                    Key    = Utilities.CurrentLocalization.LocalizationIndex["WEBFRONT_PROFILE_FSEEN"],
                    Value  = Utilities.GetTimePassed(client.FirstConnection, false),
                    Show   = true,
                    Column = 1,
                    Order  = 1,
                    Type   = ProfileMeta.MetaType.Information
                });

                metaList.Add(new ProfileMeta()
                {
                    Id     = client.ClientId,
                    Key    = Utilities.CurrentLocalization.LocalizationIndex["WEBFRONT_PROFILE_LSEEN"],
                    Value  = Utilities.GetTimePassed(client.LastConnection, false),
                    Show   = true,
                    Column = 1,
                    Order  = 2,
                    Type   = ProfileMeta.MetaType.Information
                });

                metaList.Add(new ProfileMeta()
                {
                    Id     = client.ClientId,
                    Key    = Utilities.CurrentLocalization.LocalizationIndex["WEBFRONT_CLIENT_META_CONNECTIONS"],
                    Value  = client.Connections.ToString("#,##0", new System.Globalization.CultureInfo(Utilities.CurrentLocalization.LocalizationName)),
                    Show   = true,
                    Column = 1,
                    Order  = 3,
                    Type   = ProfileMeta.MetaType.Information
                });

                metaList.Add(new ProfileMeta()
                {
                    Key       = Utilities.CurrentLocalization.LocalizationIndex["WEBFRONT_CLIENT_META_MASKED"],
                    Value     = client.Masked ? Utilities.CurrentLocalization.LocalizationIndex["WEBFRONT_CLIENT_META_TRUE"] : Utilities.CurrentLocalization.LocalizationIndex["WEBFRONT_CLIENT_META_FALSE"],
                    Sensitive = true,
                    Column    = 1,
                    Order     = 4,
                    Type      = ProfileMeta.MetaType.Information
                });

                return(metaList);
            }

            async Task <List <ProfileMeta> > getPenaltyMeta(int clientId, int offset, int count, DateTime?startAt)
            {
                if (count <= 1)
                {
                    return(new List <ProfileMeta>());
                }

                var penalties = await GetPenaltyService().GetClientPenaltyForMetaAsync(clientId, count, offset, startAt);

                return(penalties.Select(_penalty => new ProfileMeta()
                {
                    Id = _penalty.Id,
                    Type = _penalty.PunisherId == clientId ? ProfileMeta.MetaType.Penalized : ProfileMeta.MetaType.ReceivedPenalty,
                    Value = _penalty,
                    When = _penalty.TimePunished,
                    Sensitive = _penalty.Sensitive
                })
                       .ToList());
            }

            MetaService.AddRuntimeMeta(getProfileMeta);
            MetaService.AddRuntimeMeta(getPenaltyMeta);
            #endregion

            #region INIT
            int       failedServers  = 0;
            int       successServers = 0;
            Exception lastException  = null;

            async Task Init(ServerConfiguration Conf)
            {
                // setup the event handler after the class is initialized

                Handler = new GameEventHandler(this);

                try
                {
                    var ServerInstance = new IW4MServer(this, Conf);
                    await ServerInstance.Initialize();

                    lock (_servers)
                    {
                        _servers.Add(ServerInstance);
                    }

                    Logger.WriteVerbose(Utilities.CurrentLocalization.LocalizationIndex["MANAGER_MONITORING_TEXT"].FormatExt(ServerInstance.Hostname));
                    // add the start event for this server

                    var e = new GameEvent()
                    {
                        Type  = GameEvent.EventType.Start,
                        Data  = $"{ServerInstance.GameName} started",
                        Owner = ServerInstance
                    };

                    Handler.AddEvent(e);
                    successServers++;
                }

                catch (ServerException e)
                {
                    Logger.WriteError(Utilities.CurrentLocalization.LocalizationIndex["SERVER_ERROR_UNFIXABLE"].FormatExt($"[{Conf.IPAddress}:{Conf.Port}]"));

                    if (e.GetType() == typeof(DvarException))
                    {
                        Logger.WriteDebug($"{Utilities.CurrentLocalization.LocalizationIndex["SERVER_ERROR_DVAR"].FormatExt((e as DvarException).Data["dvar_name"])} ({Utilities.CurrentLocalization.LocalizationIndex["SERVER_ERROR_DVAR_HELP"]})");
                    }

                    else if (e.GetType() == typeof(NetworkException))
                    {
                        Logger.WriteDebug(e.Message);
                    }

                    failedServers++;
                    lastException = e;
                }
            }

            await Task.WhenAll(config.Servers.Select(c => Init(c)).ToArray());

            if (successServers - failedServers <= 0)
            {
                if (!Utilities.PromptBool(Utilities.CurrentLocalization.LocalizationIndex["MANAGER_START_WITH_ERRORS"]))
                {
                    throw lastException;
                }
            }
            #endregion
        }
Пример #13
0
        /// <summary>
        /// Configures the dependency injection services
        /// </summary>
        private static IServiceCollection ConfigureServices(string[] args)
        {
            var appConfigHandler = new BaseConfigurationHandler <ApplicationConfiguration>("IW4MAdminSettings");
            var appConfig        = appConfigHandler.Configuration();
            var defaultLogger    = new Logger("IW4MAdmin-Manager");

            var masterUri      = Utilities.IsDevelopment ? new Uri("http://127.0.0.1:8080") : appConfig?.MasterUrl ?? new ApplicationConfiguration().MasterUrl;
            var apiClient      = RestClient.For <IMasterApi>(masterUri);
            var pluginImporter = new PluginImporter(defaultLogger, appConfig, apiClient, new RemoteAssemblyHandler(defaultLogger, appConfig));

            var serviceCollection = new ServiceCollection();

            serviceCollection.AddSingleton <IServiceCollection>(_serviceProvider => serviceCollection)
            .AddSingleton(appConfigHandler as IConfigurationHandler <ApplicationConfiguration>)
            .AddSingleton(new BaseConfigurationHandler <CommandConfiguration>("CommandConfiguration") as IConfigurationHandler <CommandConfiguration>)
            .AddSingleton(_serviceProvider => _serviceProvider.GetRequiredService <IConfigurationHandler <ApplicationConfiguration> >().Configuration() ?? new ApplicationConfiguration())
            .AddSingleton(_serviceProvider => _serviceProvider.GetRequiredService <IConfigurationHandler <CommandConfiguration> >().Configuration() ?? new CommandConfiguration())
            .AddSingleton <ILogger>(_serviceProvider => defaultLogger)
            .AddSingleton <IPluginImporter, PluginImporter>()
            .AddSingleton <IMiddlewareActionHandler, MiddlewareActionHandler>()
            .AddSingleton <IRConConnectionFactory, RConConnectionFactory>()
            .AddSingleton <IGameServerInstanceFactory, GameServerInstanceFactory>()
            .AddSingleton <IConfigurationHandlerFactory, ConfigurationHandlerFactory>()
            .AddSingleton <IParserRegexFactory, ParserRegexFactory>()
            .AddSingleton <IDatabaseContextFactory, DatabaseContextFactory>()
            .AddSingleton <IGameLogReaderFactory, GameLogReaderFactory>()
            .AddSingleton <IScriptCommandFactory, ScriptCommandFactory>()
            .AddSingleton <IAuditInformationRepository, AuditInformationRepository>()
            .AddSingleton <IEntityService <EFClient>, ClientService>()
            .AddSingleton <IMetaService, MetaService>()
            .AddSingleton <IMetaRegistration, MetaRegistration>()
            .AddSingleton <IScriptPluginServiceResolver, ScriptPluginServiceResolver>()
            .AddSingleton <IResourceQueryHelper <ClientPaginationRequest, ReceivedPenaltyResponse>, ReceivedPenaltyResourceQueryHelper>()
            .AddSingleton <IResourceQueryHelper <ClientPaginationRequest, AdministeredPenaltyResponse>, AdministeredPenaltyResourceQueryHelper>()
            .AddSingleton <IResourceQueryHelper <ClientPaginationRequest, UpdatedAliasResponse>, UpdatedAliasResourceQueryHelper>()
            .AddSingleton <IResourceQueryHelper <ChatSearchQuery, MessageResponse>, ChatResourceQueryHelper>()
            .AddTransient <IParserPatternMatcher, ParserPatternMatcher>()
            .AddSingleton <IRemoteAssemblyHandler, RemoteAssemblyHandler>()
            .AddSingleton <IMasterCommunication, MasterCommunication>()
            .AddSingleton <IManager, ApplicationManager>()
            .AddSingleton(apiClient)
            .AddSingleton(_serviceProvider =>
            {
                var config = _serviceProvider.GetRequiredService <IConfigurationHandler <ApplicationConfiguration> >().Configuration();
                return(Localization.Configure.Initialize(useLocalTranslation: config?.UseLocalTranslations ?? false,
                                                         apiInstance: _serviceProvider.GetRequiredService <IMasterApi>(),
                                                         customLocale: config?.EnableCustomLocale ?? false ? (config.CustomLocale ?? "en-US") : "en-US"));
            });

            if (args.Contains("serialevents"))
            {
                serviceCollection.AddSingleton <IEventHandler, SerialGameEventHandler>();
            }
            else
            {
                serviceCollection.AddSingleton <IEventHandler, GameEventHandler>();
            }

            // register the native commands
            foreach (var commandType in typeof(SharedLibraryCore.Commands.QuitCommand).Assembly.GetTypes()
                     .Where(_command => _command.BaseType == typeof(Command)))
            {
                defaultLogger.WriteInfo($"Registered native command type {commandType.Name}");
                serviceCollection.AddSingleton(typeof(IManagerCommand), commandType);
            }

            // register the plugin implementations
            var pluginImplementations = pluginImporter.DiscoverAssemblyPluginImplementations();

            foreach (var pluginType in pluginImplementations.Item1)
            {
                defaultLogger.WriteInfo($"Registered plugin type {pluginType.FullName}");
                serviceCollection.AddSingleton(typeof(IPlugin), pluginType);
            }

            // register the plugin commands
            foreach (var commandType in pluginImplementations.Item2)
            {
                defaultLogger.WriteInfo($"Registered plugin command type {commandType.FullName}");
                serviceCollection.AddSingleton(typeof(IManagerCommand), commandType);
            }

            // register any script plugins
            foreach (var scriptPlugin in pluginImporter.DiscoverScriptPlugins())
            {
                serviceCollection.AddSingleton(scriptPlugin);
            }

            // register any eventable types
            foreach (var assemblyType in typeof(Program).Assembly.GetTypes()
                     .Where(_asmType => typeof(IRegisterEvent).IsAssignableFrom(_asmType))
                     .Union(pluginImplementations
                            .Item1.SelectMany(_asm => _asm.Assembly.GetTypes())
                            .Distinct()
                            .Where(_asmType => typeof(IRegisterEvent).IsAssignableFrom(_asmType))))
            {
                var instance = Activator.CreateInstance(assemblyType) as IRegisterEvent;
                serviceCollection.AddSingleton(instance);
            }

            return(serviceCollection);
        }
Пример #14
0
        /// <summary>
        /// Configures the dependency injection services
        /// </summary>
        private static IServiceCollection ConfigureServices(string[] args)
        {
            // setup the static resources (config/master api/translations)
            var serviceCollection    = new ServiceCollection();
            var appConfigHandler     = new BaseConfigurationHandler <ApplicationConfiguration>("IW4MAdminSettings");
            var defaultConfigHandler = new BaseConfigurationHandler <DefaultSettings>("DefaultSettings");
            var defaultConfig        = defaultConfigHandler.Configuration();
            var appConfig            = appConfigHandler.Configuration();
            var masterUri            = Utilities.IsDevelopment
                ? new Uri("http://127.0.0.1:8080")
                : appConfig?.MasterUrl ?? new ApplicationConfiguration().MasterUrl;
            var httpClient = new HttpClient
            {
                BaseAddress = masterUri,
                Timeout     = TimeSpan.FromSeconds(15)
            };
            var masterRestClient  = RestClient.For <IMasterApi>(httpClient);
            var translationLookup = Configure.Initialize(Utilities.DefaultLogger, masterRestClient, appConfig);

            if (appConfig == null)
            {
                appConfig = (ApplicationConfiguration) new ApplicationConfiguration().Generate();
                appConfigHandler.Set(appConfig);
                appConfigHandler.Save();
            }

            // register override level names
            foreach (var(key, value) in appConfig.OverridePermissionLevelNames)
            {
                if (!Utilities.PermissionLevelOverrides.ContainsKey(key))
                {
                    Utilities.PermissionLevelOverrides.Add(key, value);
                }
            }

            // build the dependency list
            HandlePluginRegistration(appConfig, serviceCollection, masterRestClient);

            serviceCollection
            .AddBaseLogger(appConfig)
            .AddSingleton(defaultConfig)
            .AddSingleton <IServiceCollection>(_serviceProvider => serviceCollection)
            .AddSingleton <IConfigurationHandler <DefaultSettings>, BaseConfigurationHandler <DefaultSettings> >()
            .AddSingleton((IConfigurationHandler <ApplicationConfiguration>)appConfigHandler)
            .AddSingleton(
                new BaseConfigurationHandler <CommandConfiguration>("CommandConfiguration") as
                IConfigurationHandler <CommandConfiguration>)
            .AddSingleton(appConfig)
            .AddSingleton(_serviceProvider =>
                          _serviceProvider.GetRequiredService <IConfigurationHandler <CommandConfiguration> >()
                          .Configuration() ?? new CommandConfiguration())
            .AddSingleton <IPluginImporter, PluginImporter>()
            .AddSingleton <IMiddlewareActionHandler, MiddlewareActionHandler>()
            .AddSingleton <IRConConnectionFactory, RConConnectionFactory>()
            .AddSingleton <IGameServerInstanceFactory, GameServerInstanceFactory>()
            .AddSingleton <IConfigurationHandlerFactory, ConfigurationHandlerFactory>()
            .AddSingleton <IParserRegexFactory, ParserRegexFactory>()
            .AddSingleton <IDatabaseContextFactory, DatabaseContextFactory>()
            .AddSingleton <IGameLogReaderFactory, GameLogReaderFactory>()
            .AddSingleton <IScriptCommandFactory, ScriptCommandFactory>()
            .AddSingleton <IAuditInformationRepository, AuditInformationRepository>()
            .AddSingleton <IEntityService <EFClient>, ClientService>()
            .AddSingleton <IMetaService, MetaService>()
            .AddSingleton <ClientService>()
            .AddSingleton <PenaltyService>()
            .AddSingleton <ChangeHistoryService>()
            .AddSingleton <IMetaRegistration, MetaRegistration>()
            .AddSingleton <IScriptPluginServiceResolver, ScriptPluginServiceResolver>()
            .AddSingleton <IResourceQueryHelper <ClientPaginationRequest, ReceivedPenaltyResponse>,
                           ReceivedPenaltyResourceQueryHelper>()
            .AddSingleton <IResourceQueryHelper <ClientPaginationRequest, AdministeredPenaltyResponse>,
                           AdministeredPenaltyResourceQueryHelper>()
            .AddSingleton <IResourceQueryHelper <ClientPaginationRequest, UpdatedAliasResponse>,
                           UpdatedAliasResourceQueryHelper>()
            .AddSingleton <IResourceQueryHelper <ChatSearchQuery, MessageResponse>, ChatResourceQueryHelper>()
            .AddSingleton <IResourceQueryHelper <ClientPaginationRequest, ConnectionHistoryResponse>, ConnectionsResourceQueryHelper>()
            .AddTransient <IParserPatternMatcher, ParserPatternMatcher>()
            .AddSingleton <IRemoteAssemblyHandler, RemoteAssemblyHandler>()
            .AddSingleton <IMasterCommunication, MasterCommunication>()
            .AddSingleton <IManager, ApplicationManager>()
            .AddSingleton <SharedLibraryCore.Interfaces.ILogger, Logger>()
            .AddSingleton <IClientNoticeMessageFormatter, ClientNoticeMessageFormatter>()
            .AddSingleton <IClientStatisticCalculator, HitCalculator>()
            .AddSingleton <IServerDistributionCalculator, ServerDistributionCalculator>()
            .AddSingleton <IWeaponNameParser, WeaponNameParser>()
            .AddSingleton <IHitInfoBuilder, HitInfoBuilder>()
            .AddSingleton(typeof(ILookupCache <>), typeof(LookupCache <>))
            .AddSingleton(typeof(IDataValueCache <,>), typeof(DataValueCache <,>))
            .AddSingleton <IServerDataViewer, ServerDataViewer>()
            .AddSingleton <IServerDataCollector, ServerDataCollector>()
            .AddSingleton <IEventPublisher, EventPublisher>()
            .AddSingleton(translationLookup)
            .AddDatabaseContextOptions(appConfig);

            if (args.Contains("serialevents"))
            {
                serviceCollection.AddSingleton <IEventHandler, SerialGameEventHandler>();
            }
            else
            {
                serviceCollection.AddSingleton <IEventHandler, GameEventHandler>();
            }

            serviceCollection.AddSource();

            return(serviceCollection);
        }
Пример #15
0
        public async Task Init()
        {
            IsRunning         = true;
            ExternalIPAddress = await Utilities.GetExternalIP();

            #region PLUGINS
            foreach (var plugin in Plugins)
            {
                try
                {
                    if (plugin is ScriptPlugin scriptPlugin)
                    {
                        await scriptPlugin.Initialize(this, _scriptCommandFactory, _scriptPluginServiceResolver);

                        scriptPlugin.Watcher.Changed += async(sender, e) =>
                        {
                            try
                            {
                                await scriptPlugin.Initialize(this, _scriptCommandFactory, _scriptPluginServiceResolver);
                            }

                            catch (Exception ex)
                            {
                                Logger.WriteError(Utilities.CurrentLocalization.LocalizationIndex["PLUGIN_IMPORTER_ERROR"].FormatExt(scriptPlugin.Name));
                                Logger.WriteDebug(ex.Message);
                            }
                        };
                    }

                    else
                    {
                        await plugin.OnLoadAsync(this);
                    }
                }

                catch (Exception ex)
                {
                    Logger.WriteError($"{_translationLookup["SERVER_ERROR_PLUGIN"]} {plugin.Name}");
                    Logger.WriteDebug(ex.GetExceptionInfo());
                }
            }
            #endregion

            #region CONFIG
            var config = ConfigHandler.Configuration();

            // copy over default config if it doesn't exist
            if (config == null)
            {
                var defaultConfig = new BaseConfigurationHandler <DefaultConfiguration>("DefaultSettings").Configuration();
                ConfigHandler.Set((ApplicationConfiguration) new ApplicationConfiguration().Generate());
                var newConfig = ConfigHandler.Configuration();

                newConfig.AutoMessages          = defaultConfig.AutoMessages;
                newConfig.GlobalRules           = defaultConfig.GlobalRules;
                newConfig.Maps                  = defaultConfig.Maps;
                newConfig.DisallowedClientNames = defaultConfig.DisallowedClientNames;
                newConfig.QuickMessages         = defaultConfig.QuickMessages;

                if (newConfig.Servers == null)
                {
                    ConfigHandler.Set(newConfig);
                    newConfig.Servers = new ServerConfiguration[1];

                    do
                    {
                        var serverConfig = new ServerConfiguration();
                        foreach (var parser in AdditionalRConParsers)
                        {
                            serverConfig.AddRConParser(parser);
                        }

                        foreach (var parser in AdditionalEventParsers)
                        {
                            serverConfig.AddEventParser(parser);
                        }

                        newConfig.Servers = newConfig.Servers.Where(_servers => _servers != null).Append((ServerConfiguration)serverConfig.Generate()).ToArray();
                    } while (Utilities.PromptBool(_translationLookup["SETUP_SERVER_SAVE"]));

                    config = newConfig;
                    await ConfigHandler.Save();
                }
            }

            else
            {
                if (string.IsNullOrEmpty(config.Id))
                {
                    config.Id = Guid.NewGuid().ToString();
                    await ConfigHandler.Save();
                }

                if (string.IsNullOrEmpty(config.WebfrontBindUrl))
                {
                    config.WebfrontBindUrl = "http://0.0.0.0:1624";
                    await ConfigHandler.Save();
                }

                var validator        = new ApplicationConfigurationValidator();
                var validationResult = validator.Validate(config);

                if (!validationResult.IsValid)
                {
                    throw new ConfigurationException("MANAGER_CONFIGURATION_ERROR")
                          {
                              Errors = validationResult.Errors.Select(_error => _error.ErrorMessage).ToArray(),
                              ConfigurationFileName = ConfigHandler.FileName
                          };
                }

                foreach (var serverConfig in config.Servers)
                {
                    Migration.ConfigurationMigration.ModifyLogPath020919(serverConfig);

                    if (serverConfig.RConParserVersion == null || serverConfig.EventParserVersion == null)
                    {
                        foreach (var parser in AdditionalRConParsers)
                        {
                            serverConfig.AddRConParser(parser);
                        }

                        foreach (var parser in AdditionalEventParsers)
                        {
                            serverConfig.AddEventParser(parser);
                        }

                        serverConfig.ModifyParsers();
                    }
                    await ConfigHandler.Save();
                }
            }

            if (config.Servers.Length == 0)
            {
                throw new ServerException("A server configuration in IW4MAdminSettings.json is invalid");
            }

            Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
            Utilities.EncodingType = Encoding.GetEncoding(!string.IsNullOrEmpty(config.CustomParserEncoding) ? config.CustomParserEncoding : "windows-1252");

            #endregion

            #region DATABASE
            using (var db = new DatabaseContext(GetApplicationSettings().Configuration()?.ConnectionString,
                                                GetApplicationSettings().Configuration()?.DatabaseProvider))
            {
                await new ContextSeed(db).Seed();
            }
            #endregion

            #region COMMANDS
            if (ClientSvc.GetOwners().Result.Count > 0)
            {
                _commands.RemoveAll(_cmd => _cmd.GetType() == typeof(OwnerCommand));
            }

            List <IManagerCommand> commandsToAddToConfig = new List <IManagerCommand>();
            var cmdConfig = _commandConfiguration.Configuration();

            if (cmdConfig == null)
            {
                cmdConfig = new CommandConfiguration();
                commandsToAddToConfig.AddRange(_commands);
            }

            else
            {
                var unsavedCommands = _commands.Where(_cmd => !cmdConfig.Commands.Keys.Contains(_cmd.CommandConfigNameForType()));
                commandsToAddToConfig.AddRange(unsavedCommands);
            }

            // this is because I want to store the command prefix in IW4MAdminSettings, but can't easily
            // inject it to all the places that need it
            cmdConfig.CommandPrefix          = config.CommandPrefix;
            cmdConfig.BroadcastCommandPrefix = config.BroadcastCommandPrefix;

            foreach (var cmd in commandsToAddToConfig)
            {
                cmdConfig.Commands.Add(cmd.CommandConfigNameForType(),
                                       new CommandProperties()
                {
                    Name               = cmd.Name,
                    Alias              = cmd.Alias,
                    MinimumPermission  = cmd.Permission,
                    AllowImpersonation = cmd.AllowImpersonation,
                    SupportedGames     = cmd.SupportedGames
                });
            }

            _commandConfiguration.Set(cmdConfig);
            await _commandConfiguration.Save();

            #endregion

            _metaRegistration.Register();

            #region CUSTOM_EVENTS
            foreach (var customEvent in _customParserEvents.SelectMany(_events => _events.Events))
            {
                foreach (var parser in AdditionalEventParsers)
                {
                    parser.RegisterCustomEvent(customEvent.Item1, customEvent.Item2, customEvent.Item3);
                }
            }
            #endregion

            await InitializeServers();
        }