diff --git a/Plugins/SimpleStats/Cheat/Detection.cs b/Plugins/SimpleStats/Cheat/Detection.cs index 15c08f51f..a810e4746 100644 --- a/Plugins/SimpleStats/Cheat/Detection.cs +++ b/Plugins/SimpleStats/Cheat/Detection.cs @@ -173,8 +173,8 @@ namespace StatsPlugin.Cheat double marginOfError = Thresholds.GetMarginOfError(chestKills); double lerpAmount = Math.Min(1.0, (chestKills - Thresholds.LowSampleMinKills) / (double)(Thresholds.HighSampleMinKills - Thresholds.LowSampleMinKills)); // determine max acceptable ratio of chest to abdomen kills - double chestAbdomenRatioLerpValueForFlag = Thresholds.Lerp(Thresholds.ChestAbdomenRatioThresholdLowSample(2.25), Thresholds.ChestAbdomenRatioThresholdHighSample(2.25), lerpAmount) + marginOfError; - double chestAbdomenLerpValueForBan = Thresholds.Lerp(Thresholds.ChestAbdomenRatioThresholdLowSample(3.25), Thresholds.ChestAbdomenRatioThresholdHighSample(3.25), lerpAmount) + marginOfError; + double chestAbdomenRatioLerpValueForFlag = Thresholds.Lerp(Thresholds.ChestAbdomenRatioThresholdLowSample(3), Thresholds.ChestAbdomenRatioThresholdHighSample(3), lerpAmount) + marginOfError; + double chestAbdomenLerpValueForBan = Thresholds.Lerp(Thresholds.ChestAbdomenRatioThresholdLowSample(4), Thresholds.ChestAbdomenRatioThresholdHighSample(4), lerpAmount) + marginOfError; double currentChestAbdomenRatio = HitLocationCount[IW4Info.HitLocation.torso_upper] / (double)HitLocationCount[IW4Info.HitLocation.torso_lower]; @@ -198,7 +198,7 @@ namespace StatsPlugin.Cheat { ClientPenalty = Penalty.PenaltyType.Ban, RatioAmount = currentChestAbdomenRatio, - Bone = IW4Info.HitLocation.torso_upper, + Bone = 0, KillCount = chestKills }; } @@ -219,7 +219,7 @@ namespace StatsPlugin.Cheat { ClientPenalty = Penalty.PenaltyType.Flag, RatioAmount = currentChestAbdomenRatio, - Bone = IW4Info.HitLocation.torso_upper, + Bone = 0, KillCount = chestKills }; } diff --git a/Plugins/SimpleStats/Cheat/Thresholds.cs b/Plugins/SimpleStats/Cheat/Thresholds.cs index 0fa31deff..eed74d6f5 100644 --- a/Plugins/SimpleStats/Cheat/Thresholds.cs +++ b/Plugins/SimpleStats/Cheat/Thresholds.cs @@ -31,7 +31,7 @@ namespace StatsPlugin.Cheat public const int HighSampleMinKills = 100; public const double KillTimeThreshold = 0.2; - public static double GetMarginOfError(int numKills) => 0.98 / Math.Sqrt(numKills); + public static double GetMarginOfError(int numKills) => 1.6455 / Math.Sqrt(numKills); public static double Lerp(double v1, double v2, double amount) { diff --git a/Plugins/SimpleStats/Config/StatsConfiguration.cs b/Plugins/SimpleStats/Config/StatsConfiguration.cs new file mode 100644 index 000000000..5346bd437 --- /dev/null +++ b/Plugins/SimpleStats/Config/StatsConfiguration.cs @@ -0,0 +1,61 @@ +using SharedLibrary.Configuration; +using SharedLibrary.Interfaces; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace StatsPlugin.Config +{ + class StatsConfiguration : IBaseConfiguration + { + public bool EnableAntiCheat { get; set; } + public List KillstreakMessages { get; set; } + public List DeathstreakMessages { get; set; } + public string Name() => "Stats"; + public IBaseConfiguration Generate() + { + var config = new StatsConfiguration(); + + Console.Write("Enable server-side anti-cheat? [y/n]: "); + config.EnableAntiCheat = (Console.ReadLine().ToLower().FirstOrDefault() as char?) == 'y'; + + config.KillstreakMessages = new List() + { + new StreakMessageConfiguration(){ + Count = -1, + Message = "Try not to kill yourself anymore" + }, + new StreakMessageConfiguration() { + Count = 5, + Message = "Great job! You're on a ^55 killstreak!" + }, + new StreakMessageConfiguration() + { + Count = 10, + Message = "Amazing! ^510 kills ^7without dying!" + }, + new StreakMessageConfiguration(){ + Count = 25, + Message = "You better call in that nuke, ^525 killstreak^7!" + } + }; + + config.DeathstreakMessages = new List() + { + new StreakMessageConfiguration() + { + Count = 5, + Message = "Pick it up soldier, you've died ^55 times ^7in a row..." + }, + new StreakMessageConfiguration(){ + Count = 10, + Message = "Seriously? ^510 deaths ^7without getting a kill?" + }, + }; + + return config; + } + } +} diff --git a/Plugins/SimpleStats/Config/StreakMessageConfiguration.cs b/Plugins/SimpleStats/Config/StreakMessageConfiguration.cs new file mode 100644 index 000000000..1285fb58d --- /dev/null +++ b/Plugins/SimpleStats/Config/StreakMessageConfiguration.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace StatsPlugin.Config +{ + public class StreakMessageConfiguration + { + public int Count { get; set; } + public string Message { get; set; } + } +} diff --git a/Plugins/SimpleStats/Helpers/StatManager.cs b/Plugins/SimpleStats/Helpers/StatManager.cs index d55a06d41..0ae88b8fd 100644 --- a/Plugins/SimpleStats/Helpers/StatManager.cs +++ b/Plugins/SimpleStats/Helpers/StatManager.cs @@ -10,6 +10,8 @@ using SharedLibrary.Objects; using SharedLibrary.Services; using StatsPlugin.Models; using SharedLibrary.Commands; +using SharedLibrary.Configuration; +using StatsPlugin.Config; namespace StatsPlugin.Helpers { @@ -17,7 +19,6 @@ namespace StatsPlugin.Helpers { private ConcurrentDictionary Servers; private ConcurrentDictionary ContextThreads; - private ConcurrentDictionary StreakMessages; private ILogger Log; private IManager Manager; @@ -25,7 +26,6 @@ namespace StatsPlugin.Helpers { Servers = new ConcurrentDictionary(); ContextThreads = new ConcurrentDictionary(); - StreakMessages = new ConcurrentDictionary(); Log = mgr.GetLogger(); Manager = mgr; } @@ -48,7 +48,6 @@ namespace StatsPlugin.Helpers int serverId = sv.GetHashCode(); var statsSvc = new ThreadSafeStatsService(); ContextThreads.TryAdd(serverId, statsSvc); - StreakMessages.TryAdd(serverId, new StreakMessage(sv)); // get the server from the database if it exists, otherwise create and insert a new one var server = statsSvc.ServerSvc.Find(c => c.ServerId == serverId).FirstOrDefault(); @@ -247,7 +246,7 @@ namespace StatsPlugin.Helpers //statsSvc.KillStatsSvc.Insert(kill); //await statsSvc.KillStatsSvc.SaveChangesAsync(); - if(Manager.GetApplicationSettings().EnableAntiCheat) + if(Plugin.Config.Configuration().EnableAntiCheat) { async Task executePenalty(Cheat.DetectionPenaltyResult penalty) { @@ -313,10 +312,9 @@ namespace StatsPlugin.Helpers CalculateKill(attackerStats, victimStats); // show encouragement/discouragement - var streakMessageGen = StreakMessages[serverId]; string streakMessage = (attackerStats.ClientId != victimStats.ClientId) ? - streakMessageGen.MessageOnStreak(attackerStats.KillStreak, attackerStats.DeathStreak) : - streakMessageGen.MessageOnStreak(-1, -1); + StreakMessage.MessageOnStreak(attackerStats.KillStreak, attackerStats.DeathStreak) : + StreakMessage.MessageOnStreak(-1, -1); if (streakMessage != string.Empty) await attacker.Tell(streakMessage); diff --git a/Plugins/SimpleStats/Helpers/StreakMessage.cs b/Plugins/SimpleStats/Helpers/StreakMessage.cs index 4f49ae1d8..37b679aad 100644 --- a/Plugins/SimpleStats/Helpers/StreakMessage.cs +++ b/Plugins/SimpleStats/Helpers/StreakMessage.cs @@ -10,55 +10,20 @@ namespace StatsPlugin.Helpers { public class StreakMessage { - private ConfigurationManager config; - - public StreakMessage(Server sv) - { - config = new ConfigurationManager(sv); - - // initialize default messages - if (config.GetProperty>("KillstreakMessages") == null) - { - var killstreakMessages = new Dictionary() - { - { -1, "Try not to kill yourself anymore" }, - { 5, "Great job! You're on a ^55 killstreak!" }, - { 10, "Amazing! ^510 kills ^7without dying!" }, - { 25, "You better call in that nuke, ^525 killstreak^7!" } - }; - config.AddProperty(new KeyValuePair("KillstreakMessages", killstreakMessages)); - } - - if (config.GetProperty>("DeathstreakMessages") == null) - { - var deathstreakMessages = new Dictionary() - { - { 5, "Pick it up soldier, you've died ^55 times ^7in a row..." }, - { 10, "Seriously? ^510 deaths ^7without getting a kill?" }, - }; - config.AddProperty(new KeyValuePair("DeathstreakMessages", deathstreakMessages)); - } - } - /// /// Get a message from the configuration encouraging or discouraging clients /// /// how many kills the client has without dying /// how many deaths the client has without getting a kill /// message to send to the client - public string MessageOnStreak(int killStreak, int deathStreak) + public static string MessageOnStreak(int killStreak, int deathStreak) { - var killstreakMessage = config.GetProperty>("KillstreakMessages"); - var deathstreakMessage = config.GetProperty>("DeathstreakMessages"); + var killstreakMessage = Plugin.Config.Configuration().KillstreakMessages; + var deathstreakMessage = Plugin.Config.Configuration().DeathstreakMessages; - string message = ""; - - if (killstreakMessage.ContainsKey(killStreak)) - message =killstreakMessage[killStreak]; - else if (deathstreakMessage.ContainsKey(deathStreak)) - message = deathstreakMessage[deathStreak]; - - return message; + string message = killstreakMessage.FirstOrDefault(m => m.Count == killStreak)?.Message; + message = (message == null) ? deathstreakMessage.FirstOrDefault(m => m.Count == deathStreak)?.Message : message; + return message ?? ""; } } } diff --git a/Plugins/SimpleStats/Plugin.cs b/Plugins/SimpleStats/Plugin.cs index b647d5b92..7852a62ed 100644 --- a/Plugins/SimpleStats/Plugin.cs +++ b/Plugins/SimpleStats/Plugin.cs @@ -5,10 +5,12 @@ using System.Text; using System.Threading.Tasks; using SharedLibrary; +using SharedLibrary.Configuration; using SharedLibrary.Dtos; using SharedLibrary.Helpers; using SharedLibrary.Interfaces; using SharedLibrary.Services; +using StatsPlugin.Config; using StatsPlugin.Helpers; using StatsPlugin.Models; @@ -24,6 +26,7 @@ namespace StatsPlugin public static StatManager Manager { get; private set; } private IManager ServerManager; + public static BaseConfigurationHandler Config { get; private set; } public async Task OnEventAsync(Event E, Server S) { @@ -80,8 +83,16 @@ namespace StatsPlugin } } - public Task OnLoadAsync(IManager manager) + public async Task OnLoadAsync(IManager manager) { + // load custom configuration + Config = new BaseConfigurationHandler("StatsPluginSettings"); + if (Config.Configuration()== null) + { + Config.Set((StatsConfiguration)new StatsConfiguration().Generate()); + await Config.Save(); + } + // meta data info async Task> getStats(int clientId) { @@ -203,9 +214,7 @@ namespace StatsPlugin ServerManager = manager; - return Task.FromResult( - Manager = new StatManager(manager) - ); + Manager = new StatManager(manager); } public async Task OnTickAsync(Server S) diff --git a/Plugins/SimpleStats/StatsPlugin.csproj b/Plugins/SimpleStats/StatsPlugin.csproj index 9b478c4c3..3d1a0c8a6 100644 --- a/Plugins/SimpleStats/StatsPlugin.csproj +++ b/Plugins/SimpleStats/StatsPlugin.csproj @@ -124,6 +124,8 @@ + + @@ -150,11 +152,6 @@ SharedLibrary - - - 1.1.2 - - copy /Y "$(TargetDir)$(TargetName).dll" "$(SolutionDir)BUILD\plugins\" diff --git a/Plugins/Welcome/Plugin.cs b/Plugins/Welcome/Plugin.cs index cf6680b9e..0f2436199 100644 --- a/Plugins/Welcome/Plugin.cs +++ b/Plugins/Welcome/Plugin.cs @@ -7,6 +7,7 @@ using System.Threading.Tasks; using SharedLibrary.Network; using SharedLibrary.Objects; using SharedLibrary.Helpers; +using SharedLibrary.Configuration; namespace Welcome_Plugin { @@ -64,11 +65,17 @@ namespace Welcome_Plugin public string Name => "Welcome Plugin"; - private Dictionary Configs; + private BaseConfigurationHandler Config; public async Task OnLoadAsync(IManager manager) { - await Task.FromResult(Configs = new Dictionary()); + // load custom configuration + Config = new BaseConfigurationHandler("WelcomePluginSettings"); + if (Config.Configuration() == null) + { + Config.Set((WelcomeConfiguration)new WelcomeConfiguration().Generate()); + await Config.Save(); + } } public async Task OnUnloadAsync() @@ -84,39 +91,15 @@ namespace Welcome_Plugin if (E.Type == Event.GType.Connect) { Player newPlayer = E.Origin; - var cfg = Configs[S.GetHashCode()]; if (newPlayer.Level >= Player.Permission.Trusted && !E.Origin.Masked) - await E.Owner.Broadcast(ProcessAnnouncement(cfg.GetProperty("PrivilegedAnnouncementMessage"), newPlayer)); + await E.Owner.Broadcast(ProcessAnnouncement(Config.Configuration().PrivilegedAnnouncementMessage, newPlayer)); - await newPlayer.Tell(ProcessAnnouncement(cfg.GetProperty("UserWelcomeMessage"), newPlayer)); + await newPlayer.Tell(ProcessAnnouncement(Config.Configuration().UserWelcomeMessage, newPlayer)); if (newPlayer.Level == Player.Permission.Flagged) await E.Owner.ToAdmins($"^1NOTICE: ^7Flagged player ^5{newPlayer.Name} ^7has joined!"); else - await E.Owner.Broadcast(ProcessAnnouncement(cfg.GetProperty("UserAnnouncementMessage"), newPlayer)); - } - - if (E.Type == Event.GType.Start) - { - var cfg = new ConfigurationManager(S); - Configs.Add(S.GetHashCode(), cfg); - if (cfg.GetProperty("UserWelcomeMessage") == null) - { - string welcomeMsg = "Welcome ^5{{ClientName}}^7, this is your ^5{{TimesConnected}} ^7time connecting!"; - cfg.AddProperty(new KeyValuePair("UserWelcomeMessage", welcomeMsg)); - } - - if (cfg.GetProperty("PrivilegedAnnouncementMessage") == null) - { - string annoucementMsg = "{{ClientLevel}} {{ClientName}} has joined the server"; - cfg.AddProperty(new KeyValuePair("PrivilegedAnnouncementMessage", annoucementMsg)); - } - - if (cfg.GetProperty("UserAnnouncementMessage") == null) - { - string annoucementMsg = "^5{{ClientName}} ^7hails from ^5{{ClientLocation}}"; - cfg.AddProperty(new KeyValuePair("UserAnnouncementMessage", annoucementMsg)); - } + await E.Owner.Broadcast(ProcessAnnouncement(Config.Configuration().UserAnnouncementMessage, newPlayer)); } } diff --git a/Plugins/Welcome/WelcomeConfiguration.cs b/Plugins/Welcome/WelcomeConfiguration.cs new file mode 100644 index 000000000..bffaf3cbf --- /dev/null +++ b/Plugins/Welcome/WelcomeConfiguration.cs @@ -0,0 +1,26 @@ +using SharedLibrary.Interfaces; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Welcome_Plugin +{ + class WelcomeConfiguration : IBaseConfiguration + { + public string UserAnnouncementMessage { get; set; } + public string UserWelcomeMessage { get; set; } + public string PrivilegedAnnouncementMessage { get; set; } + + public IBaseConfiguration Generate() + { + UserAnnouncementMessage = "^5{{ClientName}} ^7hails from ^5{{ClientLocation}}"; + UserWelcomeMessage = "Welcome ^5{{ClientName}}^7, this is your ^5{{TimesConnected}} ^7time connecting!"; + PrivilegedAnnouncementMessage = "{{ClientLevel}} {{ClientName}} has joined the server"; + return this; + } + + public string Name() => "WelcomeConfiguration"; + } +} diff --git a/Plugins/Welcome/WelcomePlugin.csproj b/Plugins/Welcome/WelcomePlugin.csproj index e88851754..eb06c20b1 100644 --- a/Plugins/Welcome/WelcomePlugin.csproj +++ b/Plugins/Welcome/WelcomePlugin.csproj @@ -120,6 +120,7 @@ + diff --git a/SharedLibrary/Commands/NativeCommands.cs b/SharedLibrary/Commands/NativeCommands.cs index 9b3a9b69f..193fca448 100644 --- a/SharedLibrary/Commands/NativeCommands.cs +++ b/SharedLibrary/Commands/NativeCommands.cs @@ -424,7 +424,7 @@ namespace SharedLibrary.Commands if (newPerm == Player.Permission.Owner && E.Origin.Level != Player.Permission.Console) newPerm = Player.Permission.Banned; - if (newPerm == Player.Permission.Owner && !E.Owner.Manager.GetApplicationSettings().EnableMultipleOwners) + if (newPerm == Player.Permission.Owner && !E.Owner.Manager.GetApplicationSettings().Configuration().EnableMultipleOwners) { await E.Origin.Tell("There can only be 1 owner. Modify your appsettings if multiple owners are required"); return; @@ -585,7 +585,8 @@ namespace SharedLibrary.Commands public override async Task ExecuteAsync(Event E) { - if (E.Owner.Rules.Count < 1) + if (E.Owner.Manager.GetApplicationSettings().Configuration().GlobalRules?.Count < 1 && + E.Owner.ServerConfig.Rules?.Count < 1) { if (E.Message.IsBroadcastCommand()) await E.Owner.Broadcast("The server owner has not set any rules"); @@ -595,7 +596,12 @@ namespace SharedLibrary.Commands else { - foreach (String r in E.Owner.Rules) + var rules = new List(); + rules.AddRange(E.Owner.Manager.GetApplicationSettings().Configuration().GlobalRules); + if (E.Owner.ServerConfig.Rules != null) + rules.AddRange(E.Owner.ServerConfig.Rules); + + foreach (string r in rules) { if (E.Message.IsBroadcastCommand()) await E.Owner.Broadcast($"- {r}"); diff --git a/SharedLibrary/Configuration/ApplicationConfiguration.cs b/SharedLibrary/Configuration/ApplicationConfiguration.cs index 74b964dc7..f0e22503f 100644 --- a/SharedLibrary/Configuration/ApplicationConfiguration.cs +++ b/SharedLibrary/Configuration/ApplicationConfiguration.cs @@ -1,20 +1,53 @@ -using System.Collections.Generic; +using SharedLibrary.Interfaces; +using System; +using System.Collections.Generic; +using System.Linq; namespace SharedLibrary.Configuration { - public class ApplicationConfiguration + public class ApplicationConfiguration : IBaseConfiguration { public bool EnableMultipleOwners { get; set; } public bool EnableTrustedRank { get; set; } public bool EnableClientVPNs { get; set; } - public bool EnableAntiCheat { get; set; } public bool EnableDiscordLink { get; set; } public string DiscordInviteCode { get; set; } public string IPHubAPIKey { get; set; } public List Servers { get; set; } public int AutoMessagePeriod { get; set; } public List AutoMessages { get; set; } - public List Rules { get; set; } + public List GlobalRules { get; set; } public List Maps { get; set; } + + public IBaseConfiguration Generate() + { + Console.Write("Enable multiple owners? [y/n]: "); + EnableMultipleOwners = (Console.ReadLine().ToLower().FirstOrDefault() as char?) == 'y'; + + Console.Write("Enable trusted rank? [y/n]: "); + EnableTrustedRank = (Console.ReadLine().ToLower().FirstOrDefault() as char?) == 'y'; + + Console.Write("Enable client VPNs [y/n]: "); + EnableClientVPNs = (Console.ReadLine().ToLower().FirstOrDefault() as char?) == 'y'; + + if (EnableClientVPNs) + { + Console.Write("Enter iphub.info api key: "); + IPHubAPIKey = Console.ReadLine(); + } + + Console.Write("Display discord link on webfront [y/n]: "); + EnableDiscordLink = (Console.ReadLine().ToLower().FirstOrDefault() as char?) == 'y'; + + if (EnableDiscordLink) + { + Console.Write("Enter discord invite link: "); + DiscordInviteCode = Console.ReadLine(); + } + + return this; + } + + public string Name() => "ApplicationConfiguration"; } -} +} \ No newline at end of file diff --git a/SharedLibrary/Configuration/ServerConfiguration.cs b/SharedLibrary/Configuration/ServerConfiguration.cs index 922f406c3..0220cb1b3 100644 --- a/SharedLibrary/Configuration/ServerConfiguration.cs +++ b/SharedLibrary/Configuration/ServerConfiguration.cs @@ -1,9 +1,13 @@ -namespace SharedLibrary.Configuration +using System.Collections.Generic; + +namespace SharedLibrary.Configuration { public class ServerConfiguration { public string IPAddress { get; set; } public short Port { get; set; } public string Password { get; set; } + public List Rules { get; set; } + public List AutoMessages { get; set; } } } diff --git a/SharedLibrary/Dtos/ProfileMeta.cs b/SharedLibrary/Dtos/ProfileMeta.cs index 285f3d465..cb554c0ab 100644 --- a/SharedLibrary/Dtos/ProfileMeta.cs +++ b/SharedLibrary/Dtos/ProfileMeta.cs @@ -10,7 +10,6 @@ namespace SharedLibrary.Dtos public class ProfileMeta : SharedInfo { public DateTime When { get; set; } - public bool Sensitive { get; set; } public string WhenString => Utilities.GetTimePassed(When, false); public string Key { get; set; } public dynamic Value { get; set; } diff --git a/SharedLibrary/Helpers/BaseConfigurationHandler.cs b/SharedLibrary/Helpers/BaseConfigurationHandler.cs new file mode 100644 index 000000000..f2998e604 --- /dev/null +++ b/SharedLibrary/Helpers/BaseConfigurationHandler.cs @@ -0,0 +1,53 @@ +using Microsoft.Extensions.Configuration; +using Newtonsoft.Json; +using SharedLibrary.Interfaces; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace SharedLibrary.Configuration +{ + public class BaseConfigurationHandler : IConfigurationHandler where T : IBaseConfiguration + { + string Filename; + IConfigurationRoot ConfigurationRoot { get; set; } + T _configuration; + + public BaseConfigurationHandler(string fn) + { + Filename = fn; + Build(); + } + + public void Build() + { + ConfigurationRoot = new ConfigurationBuilder() + .AddJsonFile($"{AppDomain.CurrentDomain.BaseDirectory}{Filename}.json", true) + .Build(); + + _configuration = ConfigurationRoot.Get(); + + if (_configuration == null) + _configuration = default(T); + } + + public Task Save() + { + var appConfigJSON = JsonConvert.SerializeObject(_configuration, Formatting.Indented); + return Task.Factory.StartNew(() => + { + File.WriteAllText($"{AppDomain.CurrentDomain.BaseDirectory}{Filename}.json", appConfigJSON); + }); + } + + public T Configuration() => _configuration; + + public void Set(T config) + { + _configuration = config; + } + } +} diff --git a/SharedLibrary/Helpers/ConfigurationManager.cs b/SharedLibrary/Helpers/ConfigurationManager.cs deleted file mode 100644 index 7b17b5560..000000000 --- a/SharedLibrary/Helpers/ConfigurationManager.cs +++ /dev/null @@ -1,69 +0,0 @@ -using Microsoft.CSharp.RuntimeBinder; -using System; -using System.Collections.Concurrent; -using System.Collections.Generic; - -namespace SharedLibrary.Helpers -{ - public class ConfigurationManager - { - ConcurrentDictionary ConfigSet; - Server ServerInstance; - - public ConfigurationManager(Server S) - { - try - { - ConfigSet = Interfaces.Serialize>.Read($"{Utilities.OperatingDirectory}config/plugins_{S.ToString()}.cfg"); - } - - catch (Exception) - { - S.Logger.WriteInfo("ConfigurationManager could not deserialize configuration file, so initializing default config set"); - ConfigSet = new ConcurrentDictionary(); - } - - ServerInstance = S; - SaveChanges(); - } - - private void SaveChanges() - { - Interfaces.Serialize>.Write($"{Utilities.OperatingDirectory}config/plugins_{ServerInstance.ToString()}.cfg", ConfigSet); - } - - public void AddProperty(KeyValuePair prop) - { - if (!ConfigSet.ContainsKey(prop.Key)) - ConfigSet.TryAdd(prop.Key, prop.Value); - - SaveChanges(); - } - - public void UpdateProperty(KeyValuePair prop) - { - if (ConfigSet.ContainsKey(prop.Key)) - ConfigSet[prop.Key] = prop.Value; - - SaveChanges(); - } - - public T GetProperty(string prop) - { - try - { - return ConfigSet[prop].ToObject(); - } - - catch (RuntimeBinderException) - { - return ConfigSet[prop]; - } - - catch (Exception) - { - return default(T); - } - } - } -} diff --git a/SharedLibrary/Interfaces/IBaseConfiguration.cs b/SharedLibrary/Interfaces/IBaseConfiguration.cs new file mode 100644 index 000000000..49f1701d0 --- /dev/null +++ b/SharedLibrary/Interfaces/IBaseConfiguration.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace SharedLibrary.Interfaces +{ + public interface IBaseConfiguration + { + string Name(); + IBaseConfiguration Generate(); + } +} diff --git a/SharedLibrary/Interfaces/IConfigurationHandler.cs b/SharedLibrary/Interfaces/IConfigurationHandler.cs new file mode 100644 index 000000000..4fc8820f3 --- /dev/null +++ b/SharedLibrary/Interfaces/IConfigurationHandler.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace SharedLibrary.Interfaces +{ + public interface IConfigurationHandler where T : IBaseConfiguration + { + Task Save(); + void Build(); + T Configuration(); + void Set(T config); + } +} diff --git a/SharedLibrary/Interfaces/IManager.cs b/SharedLibrary/Interfaces/IManager.cs index 421592e8c..bffcd40a9 100644 --- a/SharedLibrary/Interfaces/IManager.cs +++ b/SharedLibrary/Interfaces/IManager.cs @@ -18,7 +18,7 @@ namespace SharedLibrary.Interfaces IList GetCommands(); IList GetMessageTokens(); IList GetActiveClients(); - ApplicationConfiguration GetApplicationSettings(); + IConfigurationHandler GetApplicationSettings(); ClientService GetClientService(); AliasService GetAliasService(); PenaltyService GetPenaltyService(); diff --git a/SharedLibrary/Server.cs b/SharedLibrary/Server.cs index 4ba8122a2..9b39f0c8c 100644 --- a/SharedLibrary/Server.cs +++ b/SharedLibrary/Server.cs @@ -15,7 +15,6 @@ using SharedLibrary.Configuration; namespace SharedLibrary { - [Guid("61d3829e-fcbe-44d3-bb7c-51db8c2d7ac5")] public abstract class Server { public enum Game @@ -44,7 +43,6 @@ namespace SharedLibrary NextMessage = 0; InitializeTokens(); InitializeAutoMessages(); - InitializeRules(); } //Returns current server IP set by `net_ip` -- *STRING* @@ -253,7 +251,7 @@ namespace SharedLibrary protected void InitializeMaps() { Maps = new List(); - Maps.AddRange(Manager.GetApplicationSettings().Maps.First(m => m.Game == GameName).Maps); + Maps.AddRange(Manager.GetApplicationSettings().Configuration().Maps.First(m => m.Game == GameName).Maps); } /// @@ -264,22 +262,11 @@ namespace SharedLibrary { BroadcastMessages = new List(); - BroadcastMessages.AddRange(Manager.GetApplicationSettings().AutoMessages); + if(ServerConfig.AutoMessages != null) + BroadcastMessages.AddRange(ServerConfig.AutoMessages); + BroadcastMessages.AddRange(Manager.GetApplicationSettings().Configuration().AutoMessages); } - /// - /// Initialize the rules configuration - /// todo: this needs to be a serialized file - /// - protected void InitializeRules() - { - Rules = new List(); - - Rules.AddRange(Manager.GetApplicationSettings().Rules); - } - - public ConfigurationManager Configuration { get; private set; } - public override string ToString() { return $"{IP}_{Port}"; @@ -303,10 +290,9 @@ namespace SharedLibrary public Interfaces.ILogger Logger { get; private set; } public ServerConfiguration ServerConfig { get; private set; } public List Maps { get; protected set; } - public List Rules { get; protected set; } public List Reports { get; set; } public List ChatHistory { get; protected set; } - public Queue PlayerHistory { get; private set; } + public Queue PlayerHistory { get; private set; } public Game GameName { get; protected set; } // Info diff --git a/SharedLibrary/SharedLibrary.csproj b/SharedLibrary/SharedLibrary.csproj index 4eff7270b..ec814ad0b 100644 --- a/SharedLibrary/SharedLibrary.csproj +++ b/SharedLibrary/SharedLibrary.csproj @@ -172,9 +172,11 @@ - + + + @@ -228,9 +230,18 @@ 6.2.0 + + 1.1.2 + 1.1.2 + + 1.1.2 + + + 1.1.2 + 11.0.1 diff --git a/WebfrontCore/Application/ConfigurationGenerater.cs b/WebfrontCore/Application/ConfigurationGenerator.cs similarity index 53% rename from WebfrontCore/Application/ConfigurationGenerater.cs rename to WebfrontCore/Application/ConfigurationGenerator.cs index 697900369..70eab71d0 100644 --- a/WebfrontCore/Application/ConfigurationGenerater.cs +++ b/WebfrontCore/Application/ConfigurationGenerator.cs @@ -48,6 +48,8 @@ namespace IW4MAdmin Console.Write("Enter server RCON password: "); newConfig.Password = Console.ReadLine(); + newConfig.AutoMessages = new List(); + newConfig.Rules = new List(); configList.Add(newConfig); @@ -57,39 +59,5 @@ namespace IW4MAdmin return configList; } - - public static ApplicationConfiguration GenerateApplicationConfig() - { - var config = new ApplicationConfiguration(); - - Console.Write("Enable multiple owners? [y/n]: "); - config.EnableMultipleOwners = (Console.ReadLine().ToLower().FirstOrDefault() as char?) == 'y'; - - Console.Write("Enable trusted rank? [y/n]: "); - config.EnableTrustedRank = (Console.ReadLine().ToLower().FirstOrDefault() as char?) == 'y'; - - Console.Write("Enable server-side anti-cheat [y/n]: "); - config.EnableAntiCheat = (Console.ReadLine().ToLower().FirstOrDefault() as char?) == 'y'; - - Console.Write("Enable client VPNS [y/n]: "); - config.EnableClientVPNs = (Console.ReadLine().ToLower().FirstOrDefault() as char?) == 'y'; - - if (!config.EnableClientVPNs) - { - Console.Write("Enter iphub.info api key: "); - config.IPHubAPIKey = Console.ReadLine(); - } - - Console.Write("Display Discord link on webfront [y/n]: "); - config.EnableDiscordLink = (Console.ReadLine().ToLower().FirstOrDefault() as char?) == 'y'; - - if (config.EnableDiscordLink) - { - Console.Write("Enter Discord invite link: "); - config.DiscordInviteCode = Console.ReadLine(); - } - - return config; - } } } diff --git a/WebfrontCore/Application/Main.cs b/WebfrontCore/Application/Main.cs index 37e254aa9..1df56effa 100644 --- a/WebfrontCore/Application/Main.cs +++ b/WebfrontCore/Application/Main.cs @@ -16,7 +16,7 @@ namespace IW4MAdmin static public ApplicationManager ServerManager = ApplicationManager.GetInstance(); public static string OperatingDirectory = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location) + Path.DirectorySeparatorChar; - public static void Start() + public static bool Start() { AppDomain.CurrentDomain.SetData("DataDirectory", OperatingDirectory); System.Diagnostics.Process.GetCurrentProcess().PriorityClass = System.Diagnostics.ProcessPriorityClass.BelowNormal; @@ -66,6 +66,8 @@ namespace IW4MAdmin Console.WriteLine("Shutdown complete"); }); + return true; + } catch (Exception e) @@ -78,7 +80,7 @@ namespace IW4MAdmin } Console.WriteLine("Press any key to exit..."); Console.ReadKey(); - return; + return false; } } @@ -86,15 +88,6 @@ namespace IW4MAdmin { string curDirectory = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location) + Path.DirectorySeparatorChar; - if (!Directory.Exists($"{curDirectory}Config")) - { - Console.WriteLine("Warning: Config folder does not exist"); - Directory.CreateDirectory($"{curDirectory}Config"); - } - - if (!Directory.Exists($"{curDirectory}Config/Servers")) - Directory.CreateDirectory($"{curDirectory}Config/Servers"); - if (!Directory.Exists($"{curDirectory}Logs")) Directory.CreateDirectory($"{curDirectory}Logs"); diff --git a/WebfrontCore/Application/Manager.cs b/WebfrontCore/Application/Manager.cs index 1aeababa9..22594b9d3 100644 --- a/WebfrontCore/Application/Manager.cs +++ b/WebfrontCore/Application/Manager.cs @@ -37,11 +37,11 @@ namespace IW4MAdmin ClientService ClientSvc; AliasService AliasSvc; PenaltyService PenaltySvc; - IConfigurationRoot AppSettings; + BaseConfigurationHandler ConfigHandler; #if FTP_LOG const int UPDATE_FREQUENCY = 700; #else - const int UPDATE_FREQUENCY = 750; + const int UPDATE_FREQUENCY = 450; #endif private ApplicationManager() @@ -56,13 +56,7 @@ namespace IW4MAdmin PenaltySvc = new PenaltyService(); AdministratorIPs = new List(); ServerEventOccurred += EventAPI.OnServerEventOccurred; - } - - private void BuildConfiguration() - { - AppSettings = new ConfigurationBuilder() - .AddJsonFile($"{AppDomain.CurrentDomain.BaseDirectory}IW4MAdminSettings.json") - .Build(); + ConfigHandler = new BaseConfigurationHandler("IW4MAdminSettings"); } public IList GetServers() @@ -88,6 +82,27 @@ namespace IW4MAdmin .ToList(); #endregion + + #region CONFIG + var config = ConfigHandler.Configuration(); + if (config?.Servers == null) + { + var newConfig = (ApplicationConfiguration)ConfigHandler.Configuration().Generate(); + ConfigHandler.Set(newConfig); + + newConfig.AutoMessagePeriod = config.AutoMessagePeriod; + newConfig.AutoMessages = config.AutoMessages; + newConfig.GlobalRules = config.GlobalRules; + newConfig.Maps = config.Maps; + newConfig.Servers = ConfigurationGenerator.GenerateServerConfig(new List()); + config = newConfig; + await ConfigHandler.Save(); + } + + else if (config.Servers.Count == 0) + throw new ServerException("A server configuration in IW4MAdminSettings.json is invalid"); + + #region PLUGINS SharedLibrary.Plugins.PluginImporter.Load(this); @@ -107,26 +122,7 @@ namespace IW4MAdmin } #endregion - #region CONFIG - BuildConfiguration(); - var settings = AppSettings.Get(); - - if (settings?.Servers == null) - { - var newSettings = ConfigurationGenerator.GenerateApplicationConfig(); - newSettings.Servers = ConfigurationGenerator.GenerateServerConfig(new List()); - newSettings.AutoMessagePeriod = settings.AutoMessagePeriod; - newSettings.AutoMessages = settings.AutoMessages; - newSettings.Rules = settings.Rules; - newSettings.Maps = settings.Maps; - settings = newSettings; - - var appConfigJSON = JsonConvert.SerializeObject(newSettings, Formatting.Indented); - File.WriteAllText($"{AppDomain.CurrentDomain.BaseDirectory}IW4MAdminSettings.json", appConfigJSON); - BuildConfiguration(); - } - - foreach (var Conf in settings.Servers) + foreach (var Conf in config.Servers) { try { @@ -285,6 +281,6 @@ namespace IW4MAdmin public AliasService GetAliasService() => AliasSvc; public PenaltyService GetPenaltyService() => PenaltySvc; - public ApplicationConfiguration GetApplicationSettings() => AppSettings.Get(); + public IConfigurationHandler GetApplicationSettings() => ConfigHandler; } } diff --git a/WebfrontCore/Application/Misc/VPNCheck.cs b/WebfrontCore/Application/Misc/VPNCheck.cs index 9aadef511..dc9306bc0 100644 --- a/WebfrontCore/Application/Misc/VPNCheck.cs +++ b/WebfrontCore/Application/Misc/VPNCheck.cs @@ -12,8 +12,9 @@ namespace WebfrontCore.Application.Misc public static async Task UsingVPN(string ip, string apiKey) { #if DEBUG - return false; -#endif + return await Task.FromResult(false); + +#else try { using (var RequestClient = new System.Net.Http.HttpClient()) @@ -30,6 +31,7 @@ namespace WebfrontCore.Application.Misc { return false; } +#endif } } } diff --git a/WebfrontCore/Application/Server.cs b/WebfrontCore/Application/Server.cs index 36e85375c..74a5a7606 100644 --- a/WebfrontCore/Application/Server.cs +++ b/WebfrontCore/Application/Server.cs @@ -144,8 +144,8 @@ namespace IW4MAdmin await ExecuteEvent(new Event(Event.GType.Connect, "", player, null, this)); - if (!Manager.GetApplicationSettings().EnableClientVPNs && - await VPNCheck.UsingVPN(player.IPAddressString, Manager.GetApplicationSettings().IPHubAPIKey)) + if (!Manager.GetApplicationSettings().Configuration().EnableClientVPNs && + await VPNCheck.UsingVPN(player.IPAddressString, Manager.GetApplicationSettings().Configuration().IPHubAPIKey)) { await player.Kick("VPNs are not allowed on this server", new Player() { ClientId = 1 }); } @@ -314,8 +314,8 @@ namespace IW4MAdmin else if (matchingPlayers.Count == 1) { E.Target = matchingPlayers.First(); - E.Data = Regex.Replace(E.Data, $"{E.Target.Name}", "", RegexOptions.IgnoreCase).Trim(); - E.Data = Regex.Replace(E.Data, $"{Args[0]}", "", RegexOptions.IgnoreCase).Trim(); + E.Data = Regex.Replace(E.Data, Regex.Escape($"{E.Target.Name}"), "", RegexOptions.IgnoreCase).Trim(); + E.Data = Regex.Replace(E.Data, Regex.Escape($"{Args[0]}"), "", RegexOptions.IgnoreCase).Trim(); if ((E.Data.Trim() == E.Target.Name.ToLower().Trim() || E.Data == String.Empty) && @@ -465,7 +465,9 @@ namespace IW4MAdmin playerCountStart = DateTime.Now; } - if (LastMessage.TotalSeconds > Manager.GetApplicationSettings().AutoMessagePeriod && BroadcastMessages.Count > 0 && ClientNum > 0) + if (LastMessage.TotalSeconds > Manager.GetApplicationSettings().Configuration().AutoMessagePeriod + && BroadcastMessages.Count > 0 + && ClientNum > 0) { await Broadcast(Utilities.ProcessMessageToken(Manager.GetMessageTokens(), BroadcastMessages[NextMessage])); NextMessage = NextMessage == (BroadcastMessages.Count - 1) ? 0 : NextMessage + 1; @@ -664,7 +666,7 @@ namespace IW4MAdmin await E.Origin.Tell($"There are ^5{Reports.Count} ^7recent reports"); // give trusted rank - if (Manager.GetApplicationSettings().EnableTrustedRank && + if (Manager.GetApplicationSettings().Configuration().EnableTrustedRank && E.Origin.TotalConnectionTime / 60.0 >= 2880 && E.Origin.Level < Player.Permission.Trusted && E.Origin.Level != Player.Permission.Flagged) @@ -960,7 +962,6 @@ namespace IW4MAdmin { InitializeMaps(); InitializeAutoMessages(); - InitializeRules(); return true; } catch (Exception E) @@ -968,7 +969,6 @@ namespace IW4MAdmin Logger.WriteError("Unable to reload configs! - " + E.Message); BroadcastMessages = new List(); Maps = new List(); - Rules = new List(); return false; } } diff --git a/WebfrontCore/Controllers/BaseController.cs b/WebfrontCore/Controllers/BaseController.cs index d841372d3..9a8cda483 100644 --- a/WebfrontCore/Controllers/BaseController.cs +++ b/WebfrontCore/Controllers/BaseController.cs @@ -22,7 +22,8 @@ namespace WebfrontCore.Controllers Manager.AdministratorIPs.Contains(context.HttpContext.Connection.RemoteIpAddress.ToString().ConvertToIP()); ViewBag.Authorized = Authorized; ViewBag.Url = Startup.Configuration["Web:Address"]; - ViewBag.DiscordLink = Manager.GetApplicationSettings().DiscordInviteCode; + string inviteLink = Manager.GetApplicationSettings().Configuration().DiscordInviteCode; + ViewBag.DiscordLink = inviteLink.Contains("http") ? inviteLink : $"https://discordapp.com/invite/{inviteLink}"; base.OnActionExecuting(context); } } diff --git a/WebfrontCore/IW4MAdminSettings.json b/WebfrontCore/IW4MAdminSettings.json index 007e4e4fe..fb3c78fea 100644 --- a/WebfrontCore/IW4MAdminSettings.json +++ b/WebfrontCore/IW4MAdminSettings.json @@ -1,19 +1,17 @@ { "AutoMessagePeriod": 60, "AutoMessages": [ - "Over ^5{{TOTALPLAYTIME}} ^7man hours have been played on this server!", "This server uses ^5IW4M Admin v{{VERSION}} ^7get it at ^5raidmax.org/IW4MAdmin", "^5IW4M Admin ^7sees ^5YOU!", - "This server has harvested the information of ^5{{TOTALPLAYERS}} ^7players!", + "This server has seen a total of ^5{{TOTALPLAYERS}} ^7players!", "Cheaters are ^1unwelcome ^7 on this server", - "Did you know 8/10 people agree with unverified statistics?", - "^5{{TOTALKILLS}} ^7innocent people have been murdered in this server!" + "Did you know 8/10 people agree with unverified statistics?" ], - "Rules": [ + "GlobalRules": [ "Cheating/Exploiting is not allowed", "Respect other players", "Administrators have the final say", - "No Racism or excessive trolling", + "No racism or excessive trolling", "Keep grenade launcher use to a minimum", "Balance teams at ALL times" ], diff --git a/WebfrontCore/Startup.cs b/WebfrontCore/Startup.cs index 5b392f480..ef89f324b 100644 --- a/WebfrontCore/Startup.cs +++ b/WebfrontCore/Startup.cs @@ -21,7 +21,8 @@ namespace WebfrontCore .AddEnvironmentVariables(); Configuration = builder.Build(); - IW4MAdmin.Program.Start(); + if (!IW4MAdmin.Program.Start()) + Environment.Exit(-1); } public static IConfigurationRoot Configuration { get; private set; } diff --git a/WebfrontCore/WebfrontCore.csproj b/WebfrontCore/WebfrontCore.csproj index 35289b27b..50b2db1c1 100644 --- a/WebfrontCore/WebfrontCore.csproj +++ b/WebfrontCore/WebfrontCore.csproj @@ -70,7 +70,7 @@ - + diff --git a/WebfrontCore/wwwroot/js/server.js b/WebfrontCore/wwwroot/js/server.js index 0ca171c81..bf8b987be 100644 --- a/WebfrontCore/wwwroot/js/server.js +++ b/WebfrontCore/wwwroot/js/server.js @@ -76,6 +76,7 @@ function refreshClientActivity() { cache: false }) .done(function (response) { + //const clientCount = $(response).find('.col-6 span').length; $('#server_clientactivity_' + serverId).html(response); }) .fail(function (jqxhr, textStatus, error) { diff --git a/version.txt b/version.txt index 10d1e17d9..114a6a282 100644 --- a/version.txt +++ b/version.txt @@ -2,7 +2,8 @@ Version 1.6: CHANGELOG: -migrated from SQLite to EntityFramework -migrated from kayak to ASP.Net Core MVC --webfront redone using boostrap and now mobile-friendly +-webfront redone using bootstrap and now mobile-friendly +-moved configuration files into IW4MAdminSettings.json -added profile page to view client history -got rid of pesky "error on character" message -optimizations to commands