From fa799688f28a970eeea87b3f5476f6cd74290b1e Mon Sep 17 00:00:00 2001 From: Evan Date: Wed, 22 Jul 2020 20:14:31 +0200 Subject: [PATCH] Updated master to AT 1.3.8-14 (Servermod 3.7.0) (#109) * CLOSESTDOOR command. For modifying the closest door to the player * LOCKDOORS command. For locking/unlocking doors when interacted with. Toggable. * RESPAWNLOCK command. For stopping respawns. Toggable. * GRENADEMODE command. Adds a grenade to the users inventory when a grenade is used. Toggable. * INFINITEITEM command. Adds a new item of the same type when used/dropped. Toggable. * Discord Webhook feature & API * EditorConfig * More debug * Utility API Class * New Warp-point system and save format (JSON) * PlayerFile format, will automatically upgrade (temporarily disabled) * All command classes now contain their own command aliases * Playerfiles is now stored as a serialized class * Refactored ATFileManager --- AdminToolbox/AdminToolbox/.editorconfig | 119 +++++ AdminToolbox/AdminToolbox/API/ATWeb.cs | 87 ++-- .../AdminToolbox/API/DiscordWebhook.cs | 51 ++ .../AdminToolbox/API/ExtentionMethods.cs | 222 ++++++++- .../AdminToolbox/API/GetPlayerFromString.cs | 10 +- AdminToolbox/AdminToolbox/API/JailHandler.cs | 93 ++-- .../AdminToolbox/API/LevenshteinDistance.cs | 4 +- .../AdminToolbox/API/PlayerSettings.cs | 121 ++--- .../AdminToolbox/API/ScheduledCommandCall.cs | 15 +- .../AdminToolbox/API/ScheduledRestart.cs | 13 +- .../AdminToolbox/API/SetPlayerVariables.cs | 71 +++ AdminToolbox/AdminToolbox/API/Utility.cs | 131 +++++ .../AdminToolbox/API/WaitForTeleport.cs | 13 + AdminToolbox/AdminToolbox/API/WarpPoint.cs | 46 ++ AdminToolbox/AdminToolbox/AdminToolbox.cs | 301 ++++++------ AdminToolbox/AdminToolbox/AdminToolbox.csproj | 34 +- .../Commands/AT_TemplateCommand.cs | 31 +- .../Commands/Facility/ClosestDoorCommand.cs | 88 ++++ .../Commands/Facility/DoorCommand.cs | 65 --- .../Commands/Facility/IntercomLockCommand.cs | 56 +-- .../Commands/Facility/JailCommand.cs | 87 ++-- .../Commands/Facility/SpeakCommand.cs | 63 ++- .../Commands/Facility/WarpCommand.cs | 204 ++++---- .../Commands/Facility/WarpsCommand.cs | 39 +- .../Commands/Player/ATBanCommand.cs | 127 +++-- .../Commands/Player/BreakDoorsCommand.cs | 143 +++--- .../Commands/Player/EmptyCommand.cs | 145 +++--- .../Commands/Player/GhostCommand.cs | 176 ++++--- .../Commands/Player/GodModeCommand.cs | 160 +++--- .../Commands/Player/GrenadeModeCommand.cs | 76 +++ .../Commands/Player/HealCommand.cs | 89 ++-- .../Commands/Player/InfiniteItemCommand.cs | 76 +++ .../Commands/Player/InstantKillCommand.cs | 143 +++--- .../Commands/Player/KeepSettingsCommand.cs | 138 +++--- .../Commands/Player/KillCommand.cs | 81 ++-- .../Commands/Player/LockDoorsCommand.cs | 94 ++++ .../Commands/Player/LockdownCommand.cs | 144 +++--- .../Commands/Player/NoDmgCommand.cs | 147 +++--- .../Commands/Player/PlayerCommand.cs | 154 +++--- .../Commands/Player/PosCommand.cs | 166 ++++--- .../Commands/Player/RoleCommand.cs | 104 ++-- .../Commands/Player/SetHpCommand.cs | 88 ++-- .../Commands/Player/SpectatorCommand.cs | 146 +++--- .../Commands/Player/TeleportCommand.cs | 70 +-- .../Commands/Player/TutorialCommand.cs | 82 ++-- .../Commands/Server/ATColorCommand.cs | 67 ++- .../AdminToolbox/Commands/Server/ATCommand.cs | 93 ++-- .../Commands/Server/ATDisableCommand.cs | 39 +- .../Commands/Server/AT_HelpCommand.cs | 29 +- .../Commands/Server/PlayerListCommand.cs | 52 +- .../Commands/Server/RespawnLockCommand.cs | 34 ++ .../Commands/Server/RoundLockCommand.cs | 82 ++-- .../Commands/Server/ServerCommand.cs | 98 ++-- .../Commands/Server/ServerStatsCommand.cs | 37 +- .../Commands/Server/TimedCommand.cs | 25 +- .../Events/LateOnCheckRoundEndEvent.cs | 16 +- .../AdminToolbox/Events/MyMiscEvents.cs | 330 +++++++++---- .../AdminToolbox/Events/PlayerDamageEvent.cs | 295 +++++------ .../AdminToolbox/Events/RoundEventHandler.cs | 107 ++-- .../AdminToolbox/Managers/ATFileManager.cs | 458 +++++++++++++----- .../AdminToolbox/Managers/LogManager.cs | 157 +++--- .../AdminToolbox/Managers/PlayerFile.cs | 16 - .../AdminToolbox/Managers/WarpManager.cs | 253 ++++++---- .../AdminToolbox/Properties/AssemblyInfo.cs | 12 +- 64 files changed, 4078 insertions(+), 2635 deletions(-) create mode 100644 AdminToolbox/AdminToolbox/.editorconfig create mode 100644 AdminToolbox/AdminToolbox/API/DiscordWebhook.cs create mode 100644 AdminToolbox/AdminToolbox/API/SetPlayerVariables.cs create mode 100644 AdminToolbox/AdminToolbox/API/Utility.cs create mode 100644 AdminToolbox/AdminToolbox/API/WaitForTeleport.cs create mode 100644 AdminToolbox/AdminToolbox/API/WarpPoint.cs create mode 100644 AdminToolbox/AdminToolbox/Commands/Facility/ClosestDoorCommand.cs delete mode 100644 AdminToolbox/AdminToolbox/Commands/Facility/DoorCommand.cs create mode 100644 AdminToolbox/AdminToolbox/Commands/Player/GrenadeModeCommand.cs create mode 100644 AdminToolbox/AdminToolbox/Commands/Player/InfiniteItemCommand.cs create mode 100644 AdminToolbox/AdminToolbox/Commands/Player/LockDoorsCommand.cs create mode 100644 AdminToolbox/AdminToolbox/Commands/Server/RespawnLockCommand.cs delete mode 100644 AdminToolbox/AdminToolbox/Managers/PlayerFile.cs diff --git a/AdminToolbox/AdminToolbox/.editorconfig b/AdminToolbox/AdminToolbox/.editorconfig new file mode 100644 index 0000000..ad64de0 --- /dev/null +++ b/AdminToolbox/AdminToolbox/.editorconfig @@ -0,0 +1,119 @@ +# To learn more about .editorconfig see https://aka.ms/editorconfigdocs +############################### +# Core EditorConfig Options # +############################### +root = true +# All files +[*] +indent_style = tab +# Code files +[*.cs] +charset = utf-8 +indent_size = 4 +insert_final_newline = true +trim_trailing_whitespaces = true +############################### +# .NET Coding Conventions # +############################### +[*.cs] +# Organize usings +dotnet_sort_system_directives_first = true +# this. preferences +dotnet_style_qualification_for_field = false:silent +dotnet_style_qualification_for_property = false:silent +dotnet_style_qualification_for_method = false:silent +dotnet_style_qualification_for_event = false:silent +# Language keywords vs BCL types preferences +dotnet_style_predefined_type_for_locals_parameters_members = true:suggestion +dotnet_style_predefined_type_for_member_access = true:suggestion +# Parentheses preferences +dotnet_style_parentheses_in_arithmetic_binary_operators = always_for_clarity:suggestion +dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity:suggestion +dotnet_style_parentheses_in_other_binary_operators = always_for_clarity:suggestion +dotnet_style_parentheses_in_other_operators = always_for_clarity:suggestion +# Modifier preferences +dotnet_style_require_accessibility_modifiers = for_non_interface_members:suggestion +dotnet_style_readonly_field = true:suggestion +# Expression-level preferences +dotnet_style_object_initializer = true:suggestion +dotnet_style_collection_initializer = true:suggestion +dotnet_style_explicit_tuple_names = true:suggestion +dotnet_style_null_propagation = true:suggestion +dotnet_style_coalesce_expression = true:suggestion +dotnet_style_prefer_is_null_check_over_reference_equality_method = true:suggestion +dotnet_prefer_inferred_tuple_names = true:suggestion +dotnet_prefer_inferred_anonymous_type_member_names = true:suggestion +dotnet_style_prefer_auto_properties = true:suggestion +dotnet_style_prefer_conditional_expression_over_assignment = false:suggestion +dotnet_style_prefer_conditional_expression_over_return = false:suggestion +############################### +# Naming Conventions # +############################### +# Style Definitions +dotnet_naming_style.pascal_case_style.capitalization = pascal_case +# Use PascalCase for constant fields +dotnet_naming_rule.constant_fields_should_be_pascal_case.severity = suggestion +dotnet_naming_rule.constant_fields_should_be_pascal_case.symbols = constant_fields +dotnet_naming_rule.constant_fields_should_be_pascal_case.style = pascal_case_style +dotnet_naming_symbols.constant_fields.applicable_kinds = field +dotnet_naming_symbols.constant_fields.applicable_accessibilities = * +dotnet_naming_symbols.constant_fields.required_modifiers = const +############################### +# C# Coding Conventions # +############################### +[*.cs] +# var preferences +csharp_style_var_for_built_in_types = false:suggestion +csharp_style_var_when_type_is_apparent = false:suggestion +csharp_style_var_elsewhere = false:suggestion +# Expression-bodied members +csharp_style_expression_bodied_methods = true:suggestion +csharp_style_expression_bodied_constructors = true:suggestion +csharp_style_expression_bodied_operators = true:suggestion +csharp_style_expression_bodied_properties = true:suggestion +csharp_style_expression_bodied_indexers = true:suggestion +csharp_style_expression_bodied_accessors = true:suggestion +# Pattern matching preferences +csharp_style_pattern_matching_over_is_with_cast_check = true:suggestion +csharp_style_pattern_matching_over_as_with_null_check = true:suggestion +# Null-checking preferences +csharp_style_throw_expression = true:suggestion +csharp_style_conditional_delegate_call = true:suggestion +# Modifier preferences +csharp_preferred_modifier_order = public,private,protected,internal,static,extern,new,virtual,abstract,sealed,override,readonly,unsafe,volatile,async:suggestion +# Expression-level preferences +csharp_prefer_braces = true:silent +csharp_style_deconstructed_variable_declaration = true:suggestion +csharp_prefer_simple_default_expression = true:suggestion +csharp_style_pattern_local_over_anonymous_function = true:suggestion +csharp_style_inlined_variable_declaration = true:suggestion +############################### +# C# Formatting Rules # +############################### +# New line preferences +csharp_new_line_before_open_brace = all +csharp_new_line_before_else = true +csharp_new_line_before_catch = true +csharp_new_line_before_finally = true +csharp_new_line_before_members_in_object_initializers = true +csharp_new_line_before_members_in_anonymous_types = true +csharp_new_line_between_query_expression_clauses = true +# Indentation preferences +csharp_indent_case_contents = true +csharp_indent_switch_labels = true +csharp_indent_labels = flush_left +# Space preferences +csharp_space_after_cast = false +csharp_space_after_keywords_in_control_flow_statements = true +csharp_space_between_method_call_parameter_list_parentheses = false +csharp_space_between_method_declaration_parameter_list_parentheses = false +csharp_space_between_parentheses = false +csharp_space_before_colon_in_inheritance_clause = true +csharp_space_after_colon_in_inheritance_clause = true +csharp_space_around_binary_operators = before_and_after +csharp_space_between_method_declaration_empty_parameter_list_parentheses = false +csharp_space_between_method_call_name_and_opening_parenthesis = false +csharp_space_between_method_call_empty_parameter_list_parentheses = false +# Wrapping preferences +csharp_preserve_single_line_statements = true +csharp_preserve_single_line_blocks = true diff --git a/AdminToolbox/AdminToolbox/API/ATWeb.cs b/AdminToolbox/AdminToolbox/API/ATWeb.cs index 238f7d2..2bb4e63 100644 --- a/AdminToolbox/AdminToolbox/API/ATWeb.cs +++ b/AdminToolbox/AdminToolbox/API/ATWeb.cs @@ -1,41 +1,38 @@ -using Smod2.Commands; -using Smod2; -using Smod2.API; -using System.Collections.Generic; using System; using System.Linq; +using System.Net; +using Smod2; using UnityEngine.Networking; - namespace AdminToolbox.API { + using API.Webhook; /// /// Static class that contains all of the plugins web-based methods /// public static class ATWeb { + private static AdminToolbox Plugin => AdminToolbox.singleton; + + private static void Debug(string str) => Plugin.Debug("[ATWeb]: " + str); + /// /// Class for storing the latest GitHub release info /// public class AT_LatestReleaseInfo { - readonly string title; - readonly string version; - readonly string author; - readonly string downloadLink; - #pragma warning disable CS1591 // Missing XML comment for publicly visible type or member - public string Title => title; - public string Version => version; - public string Author => author; - public string DownloadLink => downloadLink; + public string Title { get; } + public string Version { get; } + public string Author { get; } + public string DownloadLink { get; } public AT_LatestReleaseInfo(string Title, string Version, string Author, string DownloadLink) { - this.title = Title; - this.version = Version; - this.author = Author; - this.downloadLink = DownloadLink; + this.Title = Title; + this.Version = Version; + this.Author = Author; + this.DownloadLink = DownloadLink; } #pragma warning restore CS1591 // Missing XML comment for publicly visible type or member } @@ -49,24 +46,23 @@ public static AT_LatestReleaseInfo GetOnlineInfo(AdminToolbox plugin) || ConfigManager.Manager.Config.GetBoolValue("admintoolbox_disable_networking", false)) return new AT_LatestReleaseInfo(plugin.Details.name, plugin.Details.version, plugin.Details.author, ""); string rawResponse = string.Empty; string apiURL = "https://api.github.com/repos/Rnen/AdminToolbox/releases/latest"; - string _title = "", _version = "", _author = "", _dllink =""; - + string _title = "", _version = "", _author = "", _dllink = ""; + try { using (UnityWebRequest ww = UnityWebRequest.Get(apiURL)) { ww.SendWebRequest(); DateTime timer = DateTime.Now.AddSeconds(2); - while (!ww.isDone || !ww.downloadHandler.isDone && DateTime.Now < timer) { } + while (!ww.isDone || (!ww.downloadHandler.isDone && DateTime.Now < timer)) { } rawResponse = ww.downloadHandler.text; if (string.IsNullOrEmpty(rawResponse)) - throw new Exception(); + throw new Exception("[AdminToolbox]: GitHub web request response was NullOrEmpty!"); string FindValue(string key) { - plugin.Debug("Searched: " + key); + //plugin.Debug("Searched: " + key); string str = rawResponse.Split(Environment.NewLine.ToCharArray()).Where(s => s.Trim().StartsWith("\"" + key)).FirstOrDefault().Split(new[] { ':' }, 2).Last().Replace("\"", string.Empty).Trim(',').Trim(); - plugin.Debug("Found: " + str); - if (key.ToLower() == "tag_name") return str.Split('-').FirstOrDefault(); + //plugin.Debug("Found: " + str); return str; } _title = FindValue("name"); @@ -74,15 +70,50 @@ string FindValue(string key) _author = FindValue("login"); _dllink = FindValue("html_url"); //FindValue("browser_download_url"); if (string.IsNullOrEmpty(_version)) - throw new Exception(); + throw new Exception("[AdminToolbox]: GitHub version was NullOrEmpty!"); } } - catch + catch (Exception e) { + Debug("Exception: " + e.Message); plugin.Info(" \n\n - Downloading online version failed, skipping..." + "\n \n"); return new AT_LatestReleaseInfo(plugin.Details.name, plugin.Details.version, plugin.Details.author, ""); } - return new AT_LatestReleaseInfo(_title,_version,_author,_dllink); + return new AT_LatestReleaseInfo(_title, _version, _author, _dllink); + } + + internal static bool NewerVersionAvailable() + { + if (Plugin == null) return false; + string thisVersion = Plugin.Details.version.Split('-').FirstOrDefault().Replace(".", string.Empty); + string onlineVersion = Plugin.GetGitReleaseInfo().Version.Split('-').FirstOrDefault().Replace(".", string.Empty); + + if (int.TryParse(thisVersion, out int thisV) + && int.TryParse(onlineVersion, out int onlineV) + && onlineV > thisV) + return true; + else return false; + } + + internal static string SendWebhook(DiscordWebhook discordWebHook, string url) + { + if (!string.IsNullOrEmpty(url) && Uri.TryCreate(url, UriKind.Absolute, out Uri uri)) + { + //string jsonData = UnityEngine.JsonUtility.ToJson(discordWebHook, true); + string jsonData = Newtonsoft.Json.JsonConvert.SerializeObject(discordWebHook); + return WebPost(uri, jsonData); + } + else + return "Failed creating URI of WebHook link: " + url; + } + + private static string WebPost(Uri uri, string rawJsonData) + { + using (WebClient wb = new WebClient()) + { + wb.Headers[HttpRequestHeader.ContentType] = "application/json"; + return wb.UploadString(uri, "POST", rawJsonData); + } } } } diff --git a/AdminToolbox/AdminToolbox/API/DiscordWebhook.cs b/AdminToolbox/AdminToolbox/API/DiscordWebhook.cs new file mode 100644 index 0000000..ced6225 --- /dev/null +++ b/AdminToolbox/AdminToolbox/API/DiscordWebhook.cs @@ -0,0 +1,51 @@ +namespace AdminToolbox.API.Webhook +{ + public class Image + { + public string url; + } + public class Author + { + public string name = ""; + public string url = ""; + public string icon_url = ""; + } + public class Field + { + public string name; + public string value; + public string inline = "false"; + public Field() { } + + public Field(Field field) + { + this.name = field.name; + this.value = field.value; + this.inline = field.inline; + } + + public override string ToString() + { + return "Name: " + this.name + " Value: " + this.value + " InLine: " + inline; + } + } + public class EmbedData + { + public Author author = new Author(); + public string title = ""; + public string url = ""; + public string description = ""; + public int color = 12395008; + public Field[] fields = new Field[0]; + public Image image; + public Image thumbnail; + } + + public class DiscordWebhook + { + public string username = "AdminToolbox"; + public string avatar_url = "https://puu.sh/D0DRU.png"; + public string content = ""; + public EmbedData[] embeds = new EmbedData[1] { new EmbedData() }; + } +} diff --git a/AdminToolbox/AdminToolbox/API/ExtentionMethods.cs b/AdminToolbox/AdminToolbox/API/ExtentionMethods.cs index 393dd28..8f79820 100644 --- a/AdminToolbox/AdminToolbox/API/ExtentionMethods.cs +++ b/AdminToolbox/AdminToolbox/API/ExtentionMethods.cs @@ -1,56 +1,230 @@ -using Smod2; -using Smod2.API; -using Smod2.Events; -using Smod2.EventHandlers; +using System; using System.Collections.Generic; using System.Linq; -using System; -using System.Text.RegularExpressions; -using System.Threading; -using UnityEngine; -using Unity; - +using Smod2; +using Smod2.API; +using Smod2.Commands; -namespace AdminToolbox.API +namespace AdminToolbox.API.Extentions { - static internal class ExtentionMethods + using API.Webhook; + + public static class ExtentionMethods { - static Server Server => PluginManager.Manager.Server; + private static Server Server => PluginManager.Manager.Server; + + private static AdminToolbox Plugin => AdminToolbox.singleton; internal static bool GetIsJailed(this Player player) + => AdminToolbox.ATPlayerDict.ContainsKey(player.UserId) && AdminToolbox.ATPlayerDict[player.UserId].isJailed; + + public static bool IsInsideJail(this Player player) { - return AdminToolbox.ATPlayerDict.ContainsKey(player.SteamId) && AdminToolbox.ATPlayerDict[player.SteamId].isJailed; + Vector + jail = JailHandler.JailPos, + playerPos = player.GetPosition(); + float + x = Math.Abs(playerPos.x - jail.x), + y = Math.Abs(playerPos.y - jail.y), + z = Math.Abs(playerPos.z - jail.z); + return x > 7 || y > 5 || z > 7 ? false : true; } - internal static string[] CurrentOnlineIDs(this List players) + internal static string[] UserIdsToArray(this List players) { string[] newArray = new string[players.Count]; - for(int i = 0; i < players.Count; i++) + for (int i = 0; i < players.Count; i++) { - newArray[i] = players[i].SteamId; + newArray[i] = players[i].UserId; } return newArray; } - internal static bool ContainsPlayer(this Dictionary dict, Player player) + internal static Player[] JailedPlayers(this Player[] players) + { + if (players == null) + { + throw new ArgumentNullException(nameof(players)); + } + + return players.Length > 0 && Server.Round.Duration > 0 + ? players + .Where(p => p.TeamRole.Role != Smod2.API.RoleType.UNASSIGNED + && p.TeamRole.Role != Smod2.API.RoleType.SPECTATOR + && !p.OverwatchMode + && p.GetIsJailed()).ToArray() + : (new Player[0]); + } + + internal static List AddField(this List list, string title, string content, bool inline = false) + { + list.Add(new Field { name = title, value = content, inline = inline ? "true" : "false" }); + return list; + } + + private static bool ContainsPlayer(this string[] array, Player player) + { + if (array != null && player != null && array.Length > 0) + { + foreach (string str in array.Select(s => s.Trim().ToUpper())) + { + if (string.IsNullOrEmpty(str)) + continue; + if (str == player.UserId) + return true; + else if (player.GetUserGroup().Name != null && str == player.GetUserGroup().Name.Trim().ToUpper()) + return true; + else if (player.GetUserGroup().BadgeText != null && str == player.GetUserGroup().BadgeText.Trim().ToUpper()) + return true; + else if (player.GetRankName() != null && str == player.GetRankName().Trim().ToUpper()) + return true; + } + return false; + } + else //if empty, let anyone use it + { + return false; + } + } + + internal static bool IsPlayer(this ICommandSender sender) => sender is Player p && !string.IsNullOrEmpty(p.UserId); + + internal static bool IsPermitted(this ICommandSender sender, string[] commandKey) => sender.IsPermitted(commandKey, false, out string[] reply); + + internal static bool IsPermitted(this ICommandSender sender, string[] commandKey, bool mustBeListed) => sender.IsPermitted(commandKey, mustBeListed, out string[] reply); + + internal static bool IsPermitted(this ICommandSender sender, string[] commandKey, out string[] denied) => sender.IsPermitted(commandKey, false, out denied); + + internal static bool IsPermitted(this ICommandSender sender, string[] commandKey, bool mustBeListed, out string[] denied) + { + denied = new string[] { "Error during command whitelist calculation!" }; + if (sender is Player pl) + { + if (commandKey.Length < 1) + return true; + string[] masterWhitelist = ConfigManager.Manager.Config.GetListValue("admintoolbox_master_whitelist", new string[] { }); + if (masterWhitelist.ContainsPlayer(pl)) + return true; + + int validConfigs = 0; + foreach (string command in commandKey) + { + command.Trim(); + if (string.IsNullOrEmpty(command)) continue; + //Gets a array of whitelisted users (if any) + string[] configList = ConfigManager.Manager.Config.GetListValue("admintoolbox_" + command.ToLower() + "_whitelist", new string[0]); + if (configList.Length > 0) + validConfigs++; + if (configList.ContainsPlayer(pl)) + return true; + } + string reply = "You are not permitted to use the (" + string.Join(" / ", commandKey) + ") command!"; + denied = mustBeListed ? new string[] { reply, "You are required to be spesificly whitelisted to use this command." } : new string[] { reply }; + return (mustBeListed || ConfigManager.Manager.Config.GetBoolValue("admintoolbox_whitelist_required", false)) && validConfigs < 1 + ? false + : !(validConfigs > 0); + } + else + return true; + } + + internal static bool ContainsPlayer(this Dictionary dict, Player player) + => AdminToolbox.ATPlayerDict?.ContainsKey(player?.UserId) ?? false; + + internal static void ResetPlayerBools(this Dictionary.KeyCollection dict) { - return AdminToolbox.ATPlayerDict?.ContainsKey(player.SteamId) ?? false; + string[] keys = dict.ToArray(); + if (keys.Length > 0) + { + foreach (string key in keys) + { + if (AdminToolbox.ATPlayerDict.ContainsKey(key) && !AdminToolbox.ATPlayerDict[key].keepSettings) + { + SetPlayerVariables.SetPlayerBools(key, godMode: false, dmgOff: false, destroyDoor: false, lockDown: false, instantKill: false); + } + } + } + } + + internal static bool TryGetVector(this Dictionary dict, string key, out Vector vector) + { + vector = Vector.Zero; + if (dict.TryGetValue(key, out WarpPoint wp)) + { + vector = wp.Vector.ToSMVector(); + return true; + } + else + return false; } /// /// Cleans up any that does not have a player attached, and is older than "2" minutes old /// - internal static void Cleanup(this Dictionary dict) + internal static void Cleanup(this Dictionary dict) { - string[] currentPlayers = PluginManager.Manager.Server.GetPlayers().CurrentOnlineIDs(); + string[] currentPlayers = PluginManager.Manager.Server.GetPlayers().UserIdsToArray(); Dictionary newDict = new Dictionary(dict); - foreach(KeyValuePair kp in newDict) + if (newDict.Count > 0) { - if (!currentPlayers.Any(s => s == kp.Key) && !kp.Value.keepSettings && Math.Abs((DateTime.Now - kp.Value.JoinTime).TotalMinutes - Server.Round.Duration) > 2) + foreach (KeyValuePair kp in newDict) { - dict.Remove(kp.Key); + if (!currentPlayers.Any(s => s == kp.Key) && !kp.Value.keepSettings && Math.Abs((DateTime.Now - kp.Value.JoinTime).TotalMinutes - Server.Round.Duration) > 2) + { + AdminToolbox.atfileManager.PlayerStatsFileManager(kp.Key, Managers.ATFileManager.PlayerFile.Write); + dict.Remove(kp.Key); + } } } } + + /// + /// Colors the team for the MultiAdmin console window + /// + public static string ToColoredMultiAdminTeam(this Player player) + { + if (!AdminToolbox.isColored) return player.TeamRole.Name; + switch ((Team)player.TeamRole.Team) + { + case Team.SCP: + return "@#fg=Red;" + player.TeamRole.Name + "@#fg=Default;"; + case Team.MTF: + return "@#fg=Blue;" + player.TeamRole.Name + "@#fg=Default;"; + case Team.CHI: + return "@#fg=Green;" + player.TeamRole.Name + "@#fg=Default;"; + case Team.RSC: + return "@#fg=Yellow;" + player.TeamRole.Name + "@#fg=Default;"; + case Team.CDP: + return "@#fg=Orange;" + player.TeamRole.Name + "@#fg=Default;"; + case Team.TUT: + return "@#fg=Green;" + player.TeamRole.Name + "@#fg=Default;"; + default: + return player.TeamRole.Name; + } + } + + /// + /// Colors the team for the rich text game windows + /// + public static string ToColoredRichTextRole(this Player player) + { + switch ((Team)player.TeamRole.Team) + { + case Team.SCP: + return "" + player.TeamRole.Name + ""; + case Team.MTF: + return "" + player.TeamRole.Name + ""; + case Team.CHI: + return "" + player.TeamRole.Name + ""; + case Team.RSC: + return "" + player.TeamRole.Name + ""; + case Team.CDP: + return "" + player.TeamRole.Name + ""; + case Team.TUT: + return "" + player.TeamRole.Name + ""; + default: + return player.TeamRole.Name; + } + } } } diff --git a/AdminToolbox/AdminToolbox/API/GetPlayerFromString.cs b/AdminToolbox/AdminToolbox/API/GetPlayerFromString.cs index 2d0ad9d..c9e5b0d 100644 --- a/AdminToolbox/AdminToolbox/API/GetPlayerFromString.cs +++ b/AdminToolbox/AdminToolbox/API/GetPlayerFromString.cs @@ -1,4 +1,5 @@ -using Smod2; +using System.Linq; +using Smod2; using Smod2.API; namespace AdminToolbox.API @@ -25,11 +26,13 @@ public static Player GetPlayer(string args) else if (long.TryParse(args, out long sID)) { foreach (Player pl in Server.GetPlayers()) - if (pl.SteamId == sID.ToString()) + if (pl.UserId == sID.ToString()) return pl; } else { + return Server.GetPlayers(args.ToLower()).OrderBy(s => s.Name.Length).FirstOrDefault(); + /* //Takes a string and finds the closest player from the playerlist int maxNameLength = 31, LastnameDifference = 31; string str1 = args.ToLower(); @@ -50,7 +53,7 @@ public static Player GetPlayer(string args) { str2 += "z"; } - int nameDifference = API.LevenshteinDistance.Compute(str1, str2); + int nameDifference = LevenshteinDistance.Compute(str1, str2); if (nameDifference < LastnameDifference) { LastnameDifference = nameDifference; @@ -58,6 +61,7 @@ public static Player GetPlayer(string args) } } } + */ } return playerOut; } diff --git a/AdminToolbox/AdminToolbox/API/JailHandler.cs b/AdminToolbox/AdminToolbox/API/JailHandler.cs index c27869c..a739488 100644 --- a/AdminToolbox/AdminToolbox/API/JailHandler.cs +++ b/AdminToolbox/AdminToolbox/API/JailHandler.cs @@ -1,15 +1,11 @@ -using Smod2; -using Smod2.Attributes; -using Smod2.Events; -using Smod2.EventHandlers; -using Smod2.API; using System; -using System.IO; -using System.Collections.Generic; -using System.Linq; +using Smod2; +using Smod2.API; +using SMItem = Smod2.API.Item; namespace AdminToolbox.API { + using API.Extentions; /// /// Contains all Jail-related functionality /// @@ -18,32 +14,24 @@ public class JailHandler /// /// jail position /// - public static Vector JailPos => AdminToolbox.JailPos; + public static Vector JailPos => AdminToolbox.WarpVectorDict?["jail"]?.Vector.ToSMVector() ?? new Vector(53, 1020, -44); + + private static Server Server => PluginManager.Manager.Server; + + private static void Debug(string message) => AdminToolbox.singleton.Debug("[JailHandler]: " + message); /// - /// Returns of jailed s + /// Checks the players marked as "Jailed" to see if they are at where they're supposed to be + /// Gets run in the .cs Update event /// - /// is the same as the SMod GetPlayers filter - public static List GetJailedPlayers(string filter = "") - { - if (PluginManager.Manager.Server.GetPlayers(filter).Count > 0 && PluginManager.Manager.Server.Round.Duration > 0) - return PluginManager.Manager.Server.GetPlayers(filter) - .Where(p => AdminToolbox.ATPlayerDict.ContainsKey(p.SteamId) - && p.TeamRole.Role != Role.UNASSIGNED - && p.TeamRole.Role != Role.SPECTATOR - && !p.OverwatchMode - && AdminToolbox.ATPlayerDict[p.SteamId].isJailed).ToList(); - else - return new List(); - } internal static void CheckJailedPlayers() { - List jailedPlayers = GetJailedPlayers(); - if (jailedPlayers.Count > 0 && PluginManager.Manager.Server.Round.Duration > 0) + Player[] jailedPlayers = Server.GetPlayers().ToArray().JailedPlayers(); + if (jailedPlayers.Length > 0) foreach (Player pl in jailedPlayers) - if (AdminToolbox.ATPlayerDict.ContainsKey(pl.SteamId)) - if (!AdminToolbox.ATPlayerDict[pl.SteamId].IsInsideJail) SendToJail(pl); - else if (AdminToolbox.ATPlayerDict[pl.SteamId].JailedToTime <= DateTime.Now) ReturnFromJail(pl); + if (AdminToolbox.ATPlayerDict.ContainsKey(pl.UserId)) + if (!pl.IsInsideJail()) SendToJail(pl); + else if (AdminToolbox.ATPlayerDict[pl.UserId].JailedToTime <= DateTime.Now) ReturnFromJail(pl); } /// @@ -51,14 +39,18 @@ internal static void CheckJailedPlayers() /// public static bool SendToJail(Player player) => SendToJail(player, null); /// - /// Sends to jail + /// Sends to jail, with time overload. Returns bool of operation success /// - public static bool SendToJail(Player player, DateTime? jailedToTime) + /// the to send into jail + /// the time to jail the player. Null sets the time to remaining time, or if thats null, one year + public static bool SendToJail(Smod2.API.Player player, DateTime? jailedToTime) { - if (player.TeamRole.Role == Role.SPECTATOR) return false; - if (AdminToolbox.ATPlayerDict.ContainsKey(player.SteamId)) + if (player == null || player.TeamRole.Role == Smod2.API.RoleType.SPECTATOR || player.OverwatchMode) return false; + Debug($"Attempting to jail {player.Name}"); + if (AdminToolbox.ATPlayerDict.TryGetValue(player.UserId, out PlayerSettings psetting)) { - API.PlayerSettings psetting = AdminToolbox.ATPlayerDict[player.SteamId]; + if (!jailedToTime.HasValue || jailedToTime < DateTime.Now) + Debug($"Jail time for \"{player.Name}\" not specified, jailing for a year."); psetting.JailedToTime = jailedToTime ?? ((psetting.JailedToTime > DateTime.Now) ? psetting.JailedToTime : DateTime.Now.AddYears(1)); //Saves original variables psetting.originalPos = player.GetPosition(); @@ -72,29 +64,36 @@ public static bool SendToJail(Player player, DateTime? jailedToTime) psetting.prevAmmo9 = player.GetAmmo(AmmoType.DROPPED_9); } //Changes role to Tutorial, teleports to jail, removes inv. - player.ChangeRole(Role.TUTORIAL, true, false); + Debug($"Variables stored, sending \"{player.Name}\" to jail"); + player.ChangeRole(Smod2.API.RoleType.TUTORIAL, true, false); player.Teleport(JailPos, true); - foreach (Smod2.API.Item item in player.GetInventory()) + foreach (SMItem item in player.GetInventory()) item.Remove(); psetting.isJailed = true; return true; } else { - AdminToolbox.plugin.Debug("Could not send player to jail! Player not in PlayerDict!"); + Debug($"Could not send player to jail! Player \"{player.Name}\" not in AT-PlayerDict!"); return false; } } /// - /// Returns from jail + /// Removes from jail and restored original values/position. + /// Returns bool of operation success /// - public static void ReturnFromJail(Player player) + /// the player to return + public static bool ReturnFromJail(Player player) { - if (player == null || string.IsNullOrEmpty(player.SteamId.Trim())) return; - if (AdminToolbox.ATPlayerDict.ContainsKey(player.SteamId)) + if (player == null || string.IsNullOrEmpty(player.UserId.Trim())) + { + Debug("Return: Player or UserId null/empty"); + return false; + } + Debug($"Attempting to unjail \"{player.Name}\""); + if (AdminToolbox.ATPlayerDict.TryGetValue(player.UserId, out PlayerSettings psetting)) { - API.PlayerSettings psetting = AdminToolbox.ATPlayerDict[player.SteamId]; psetting.isJailed = false; psetting.JailedToTime = DateTime.Now; player.ChangeRole(psetting.previousRole, true, false); @@ -102,18 +101,22 @@ public static void ReturnFromJail(Player player) player.SetHealth(psetting.previousHealth); if (psetting.playerPrevInv != null) { - foreach (Smod2.API.Item item in player.GetInventory()) + foreach (SMItem item in player.GetInventory()) item.Remove(); - foreach (Smod2.API.Item item in psetting.playerPrevInv) + foreach (SMItem item in psetting.playerPrevInv) player.GiveItem(item.ItemType); } player.SetAmmo(AmmoType.DROPPED_5, psetting.prevAmmo5); player.SetAmmo(AmmoType.DROPPED_7, psetting.prevAmmo7); player.SetAmmo(AmmoType.DROPPED_9, psetting.prevAmmo9); - AdminToolbox.ATPlayerDict[player.SteamId].playerPrevInv = null; + AdminToolbox.ATPlayerDict[player.UserId].playerPrevInv = null; + return true; } else - AdminToolbox.plugin.Info("Could not return player from jail! Player not in PlayerDict!"); + { + AdminToolbox.singleton.Info("Could not return player from jail! Player not in PlayerDict!"); + return false; + } } } } diff --git a/AdminToolbox/AdminToolbox/API/LevenshteinDistance.cs b/AdminToolbox/AdminToolbox/API/LevenshteinDistance.cs index 264be1c..33ff087 100644 --- a/AdminToolbox/AdminToolbox/API/LevenshteinDistance.cs +++ b/AdminToolbox/AdminToolbox/API/LevenshteinDistance.cs @@ -2,12 +2,12 @@ namespace AdminToolbox.API { - internal static class LevenshteinDistance + public static class LevenshteinDistance { /// /// Compute the distance between two s. /// - internal static int Compute(string s, string t) + public static int Compute(string s, string t) { int n = s.Length; int m = t.Length; diff --git a/AdminToolbox/AdminToolbox/API/PlayerSettings.cs b/AdminToolbox/AdminToolbox/API/PlayerSettings.cs index 3645995..5ce39c6 100644 --- a/AdminToolbox/AdminToolbox/API/PlayerSettings.cs +++ b/AdminToolbox/AdminToolbox/API/PlayerSettings.cs @@ -1,23 +1,44 @@ -using Smod2; -using Smod2.Attributes; -using Smod2.Events; -using Smod2.EventHandlers; -using Smod2.API; using System; -using System.IO; using System.Collections.Generic; -using System.Linq; +using Smod2.API; +using SMItem = Smod2.API.Item; namespace AdminToolbox.API { + public class PlayerInfo + { + public string LastNickname { get; internal set; } = "Unknown"; + public string UserId { get; internal set; } = "00000000000000000"; + public bool DNT { get; internal set; } = false; + + public string FirstJoin { get; set; } = ""; + + public PlayerInfo() { } + } /// - /// is 's settings + /// is a class containing all the player's stats for + /// Used in + /// + public class PlayerStats + { + public int Kills { get; set; } = 0; + public int TeamKills { get; set; } = 0; + public int SuicideCount { get; set; } = 0; + public int Deaths { get; set; } = 0; + public int RoundsPlayed { get; set; } = 0; + public int BanCount { get; set; } = 0; + public int EscapeCount { get; set; } = 0; + + public double MinutesPlayed { get; set; } = 0.1; + + public PlayerStats() { } + } + /// + /// is 's settings /// Used in /// public class PlayerSettings { -#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member - public string SteamID { get; private set; } = ""; public bool overwatchMode = false, godMode = false, @@ -26,80 +47,30 @@ public bool keepSettings = false, lockDown = false, instantKill = false, - isJailed = false; -#pragma warning restore CS1591 // Missing XML comment for publicly visible type or member + isJailed = false, + lockDoors = false, + grenadeMode = false; - /// - /// Checks to see if is currently inside radius of - /// - public bool IsInsideJail => GetIsInsideJail(); - private bool GetIsInsideJail() - { - if (string.IsNullOrEmpty(this.SteamID)) - foreach (KeyValuePair kp in AdminToolbox.ATPlayerDict) - if (string.IsNullOrEmpty(kp.Value.SteamID)) kp.Value.SteamID = kp.Key; - Player player = AdminToolbox.plugin?.Server.GetPlayers(this.SteamID).FirstOrDefault(); - if (player == null || player.SteamId != this.SteamID) return false; - Vector jail = AdminToolbox.JailPos, - pPos = player.GetPosition(); - float x = Math.Abs(pPos.x - jail.x), - y = Math.Abs(pPos.y - jail.y), - z = Math.Abs(pPos.z - jail.z); - if (x > 7 || y > 5 || z > 7) - return false; - else - return true; - } + public PlayerStats PlayerStats = new PlayerStats(); + public PlayerInfo PlayerInfo = new PlayerInfo(); - public int -#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member - Kills = 0, - TeamKills = 0, - Deaths = 0, - RoundsPlayed = 0, - banCount = 0; - internal int - previousHealth = 100, + internal float + previousHealth = 100; + internal int prevAmmo5 = 0, prevAmmo7 = 0, prevAmmo9 = 0; public Vector DeathPos = Vector.Zero; internal Vector originalPos = Vector.Zero; - internal Role previousRole = Role.CLASSD; - internal List playerPrevInv = new List(); + internal Smod2.API.RoleType previousRole = Smod2.API.RoleType.CLASSD; + internal List playerPrevInv = new List(); + + internal Smod2.API.ItemType InfiniteItem = Smod2.API.ItemType.NULL; + public DateTime JailedToTime { get; internal set; } = DateTime.Now; public DateTime JoinTime { get; internal set; } = DateTime.Now; - public double MinutesPlayed { get; internal set; } = 1; - public PlayerSettings(string steamID) => this.SteamID = steamID; - public PlayerSettings(PlayerSettings playerSettings) - { - this.SteamID = playerSettings.SteamID; - this.banCount = playerSettings.banCount; - this.DeathPos = playerSettings.DeathPos; - this.Deaths = playerSettings.Deaths; - this.destroyDoor = playerSettings.destroyDoor; - this.dmgOff = playerSettings.dmgOff; - this.godMode = playerSettings.godMode; - this.instantKill = playerSettings.instantKill; - this.isJailed = playerSettings.isJailed; - this.JailedToTime = playerSettings.JailedToTime; - this.JoinTime = playerSettings.JoinTime; - this.keepSettings = playerSettings.keepSettings; - this.Kills = playerSettings.Kills; - this.lockDown = playerSettings.lockDown; - this.MinutesPlayed = playerSettings.MinutesPlayed; - this.originalPos = playerSettings.originalPos; - this.overwatchMode = playerSettings.overwatchMode; - this.playerPrevInv = playerSettings.playerPrevInv; - this.prevAmmo5 = playerSettings.prevAmmo5; - this.prevAmmo7 = playerSettings.prevAmmo7; - this.prevAmmo9 = playerSettings.prevAmmo9; - this.previousHealth = playerSettings.previousHealth; - this.previousRole = playerSettings.previousRole; - this.RoundsPlayed = playerSettings.RoundsPlayed; - this.TeamKills = playerSettings.TeamKills; - } -#pragma warning restore CS1591 // Missing XML comment for publicly visible type or member + + public PlayerSettings(string UserId) => this.PlayerInfo.UserId = UserId; } } diff --git a/AdminToolbox/AdminToolbox/API/ScheduledCommandCall.cs b/AdminToolbox/AdminToolbox/API/ScheduledCommandCall.cs index 1bf0637..6483165 100644 --- a/AdminToolbox/AdminToolbox/API/ScheduledCommandCall.cs +++ b/AdminToolbox/AdminToolbox/API/ScheduledCommandCall.cs @@ -15,8 +15,9 @@ public class ScheduledCommandCall public DateTime timeToExecute; public bool hasExecuted = false; - ICommandManager CommandManager => PluginManager.Manager.CommandManager; - Server Server => PluginManager.Manager.Server; + private ICommandManager CommandManager => PluginManager.Manager.CommandManager; + + private Server Server => PluginManager.Manager.Server; public ScheduledCommandCall(string command) { @@ -24,10 +25,7 @@ public ScheduledCommandCall(string command) this.args = new string[] { }; this.timeToExecute = DateTime.Now; } - protected ScheduledCommandCall() - { - AdminToolbox.plugin.Info("New ScheduledCommandCall class created"); - } + protected ScheduledCommandCall() => AdminToolbox.plugin.Info("New ScheduledCommandCall class created"); ~ScheduledCommandCall() { AdminToolbox.plugin.Info("ScheduledCommandCall class deleted!"); @@ -51,10 +49,7 @@ public ScheduledCommandCall(string command, string[] args, DateTime dateTime) this.timeToExecute = dateTime; } - public string[] CallCommand() - { - return CommandManager.CallCommand(Server as ICommandSender, this.command, this.args); - } + public string[] CallCommand() => CommandManager.CallCommand(Server as ICommandSender, this.command, this.args); } #pragma warning restore CS1591 // Missing XML comment for publicly visible type or member } diff --git a/AdminToolbox/AdminToolbox/API/ScheduledRestart.cs b/AdminToolbox/AdminToolbox/API/ScheduledRestart.cs index f3d9f70..ddb3aec 100644 --- a/AdminToolbox/AdminToolbox/API/ScheduledRestart.cs +++ b/AdminToolbox/AdminToolbox/API/ScheduledRestart.cs @@ -10,10 +10,11 @@ namespace AdminToolbox.API #pragma warning disable CS1591 // Missing XML comment for publicly visible type or member public class ScheduledRestart { - IConfigFile Config => ConfigManager.Manager.Config; - Server Server => PluginManager.Manager.Server; + private IConfigFile Config => ConfigManager.Manager.Config; - readonly AdminToolbox plugin; + private Server Server => PluginManager.Manager.Server; + + private readonly AdminToolbox plugin; public bool enabled; public DateTime restartTime; @@ -51,9 +52,9 @@ public void CallRestart() catch { throw new Exception(this.plugin.Details.name + " failed to save files!"); } try { - if (PlayerManager.singleton.players.Length > 0) - foreach (PlayerStats ps in PlayerManager.singleton.players.Where(p => p.GetComponent()).Select(s => s.GetComponent())) - ps.CallRpcRoundrestart(); + //if (PlayerManager.singleton.players.Length > 0) + //foreach (PlayerStats ps in PlayerManager.singleton.players.Where(p => p.GetComponent()).Select(s => s.GetComponent())) + //ps.CallRpcRoundrestart(); foreach(Plugin pl in PluginManager.Manager.Plugins.Where(i => i.Details.id != this.plugin.Details.id)) PluginManager.Manager.DisablePlugin(pl); diff --git a/AdminToolbox/AdminToolbox/API/SetPlayerVariables.cs b/AdminToolbox/AdminToolbox/API/SetPlayerVariables.cs new file mode 100644 index 0000000..c2aa84d --- /dev/null +++ b/AdminToolbox/AdminToolbox/API/SetPlayerVariables.cs @@ -0,0 +1,71 @@ +using System.Collections.Generic; +using Smod2.API; + +namespace AdminToolbox.API +{ + /// + /// Class containing methods for modifying on s + /// + public static class SetPlayerVariables + { + /// + /// For setting bools by + /// Returns false if is not in + /// + public static bool SetPlayerBools(string UserId, bool? spectatorOnly = null, bool? godMode = null, bool? dmgOff = null, bool? destroyDoor = null, bool? keepSettings = null, bool? lockDown = null, bool? instantKill = null, bool? isJailed = null) + { + if (AdminToolbox.ATPlayerDict.TryGetValue(UserId, out PlayerSettings setting)) + { + setting.overwatchMode = spectatorOnly ?? setting.overwatchMode; + setting.godMode = godMode ?? setting.godMode; + setting.dmgOff = dmgOff ?? setting.dmgOff; + setting.destroyDoor = destroyDoor ?? setting.destroyDoor; + setting.lockDown = lockDown ?? setting.lockDown; + setting.instantKill = instantKill ?? setting.instantKill; + setting.isJailed = isJailed ?? setting.isJailed; + return true; + } + else + return false; + + } + /// + /// For setting bools on a + /// Returns false if 's UserId is not in + /// + public static bool SetPlayerBools(Player player, bool? spectatorOnly = null, bool? godMode = null, bool? dmgOff = null, bool? destroyDoor = null, bool? keepSettings = null, bool? lockDown = null, bool? instantKill = null, bool? isJailed = null) + => SetPlayerBools(player.UserId, spectatorOnly, godMode, dmgOff, destroyDoor, keepSettings, lockDown, instantKill, isJailed); + /// + /// For setting bools on a list of s + /// Returns false if one or more of UserId's is not in + /// + public static bool SetPlayerBools(List players, bool? spectatorOnly = null, bool? godMode = null, bool? dmgOff = null, bool? destroyDoor = null, bool? keepSettings = null, bool? lockDown = null, bool? instantKill = null, bool? isJailed = null) + { + int failiures = 0; + foreach (Player player in players) + if (!SetPlayerBools(player.UserId, spectatorOnly, godMode, dmgOff, destroyDoor, keepSettings, lockDown, instantKill, isJailed)) + failiures++; + return !(failiures > 0); + } + /// + /// For setting + /// Returns false if is not in + /// + public static bool SetPlayerStats(string UserId, int? Kills = null, int? TeamKills = null, int? Deaths = null, int? RoundsPlayed = null, int? BanCount = null) + { + if (AdminToolbox.ATPlayerDict.TryGetValue(UserId, out PlayerSettings settings)) + { + PlayerStats stats = settings.PlayerStats; + stats.Kills = Kills ?? stats.Kills; + stats.TeamKills = TeamKills ?? stats.TeamKills; + stats.Deaths = Deaths ?? stats.Deaths; + stats.RoundsPlayed = RoundsPlayed ?? stats.RoundsPlayed; + stats.BanCount = BanCount ?? stats.BanCount; + settings.PlayerStats = stats; + return true; + } + else + return false; + } + } +} diff --git a/AdminToolbox/AdminToolbox/API/Utility.cs b/AdminToolbox/AdminToolbox/API/Utility.cs new file mode 100644 index 0000000..35f2cf2 --- /dev/null +++ b/AdminToolbox/AdminToolbox/API/Utility.cs @@ -0,0 +1,131 @@ +using System; +using System.Linq; +using Smod2.API; + + +namespace AdminToolbox.API +{ + public static class Utility + { + /// + /// Safely getting a from an . + /// Returns based on success + /// Invalid parameters returns + /// + public static bool TryParseRole(int roleID, out Smod2.API.RoleType role) + { + role = Smod2.API.RoleType.UNASSIGNED; + try + { + int[] validRoles = Enum.GetValues(typeof(Smod2.API.RoleType)).Cast().ToArray(); + if (!validRoles.Contains(roleID)) + return false; + else + { + role = (Smod2.API.RoleType)roleID; + return true; + } + } + catch (Exception e) + { + AdminToolbox.singleton.Info("AT " + AdminToolbox.AT_Version + "-" + AdminToolbox.AT_Revision + + "\nSMOD " + Smod2.PluginManager.GetSmodVersion() + "-" + Smod2.PluginManager.GetSmodBuild() + "\n" + e); + return false; + } + } + + /// + /// Safely getting a from an . + /// Returns based on success + /// Invalid parameters returns + /// + public static bool TryParseItem(int itemID, out Smod2.API.ItemType itemType) + { + itemType = Smod2.API.ItemType.NULL; + int[] validItems = Enum.GetValues(typeof(Smod2.API.ItemType)).Cast().ToArray(); + if (!validItems.Contains(itemID)) + return false; + else + { + itemType = (Smod2.API.ItemType)itemID; + return true; + } + } + + /// + /// Safely getting a from a . + /// Returns based on success + /// Tries to cast to first, then compares names + /// + public static bool TryParseItem(string item, out Smod2.API.ItemType itemType) + { + if (int.TryParse(item, out int x)) + return TryParseItem(x, out itemType); + + itemType = Smod2.API.ItemType.NULL; + + foreach (Smod2.API.ItemType i in Enum.GetValues(typeof(Smod2.API.ItemType))) + { + if (i.ToString().ToUpper().Contains(item.ToUpper())) + { + itemType = i; + return true; + } + } + return true; + } + + /// + /// *, ALL, EVERY + /// Uses all-caps + /// + public static string[] AllAliasWords = { "*", "ALL", "EVERY" }; + + public static readonly int[] + HumanDamageTypes = { + (int)DamageType.COM15, + (int)DamageType.E11_STANDARD_RIFLE, + (int)DamageType.P90, + (int)DamageType.MP7, + (int)DamageType.LOGICER, + (int)DamageType.FRAG + }, + ScpDamagesTypes = { + (int)DamageType.SCP_049, + (int)DamageType.SCP_049_2, + (int)DamageType.SCP_096, + (int)DamageType.SCP_106, + (int)DamageType.SCP_173, + (int)DamageType.SCP_939 + }, + NineTailsTeam = { + (int)Team.MTF, + (int)Team.RSC + }, + ChaosTeam = { + (int)Team.CHI, + (int)Team.CDP + }; + + public static readonly DamageType Human = DamageType.COM15 | DamageType.E11_STANDARD_RIFLE | DamageType.P90 | DamageType.MP7 | DamageType.LOGICER | DamageType.FRAG; + public static readonly DamageType SCP = DamageType.SCP_049 | DamageType.SCP_049_2 | DamageType.SCP_096 | DamageType.SCP_106 | DamageType.SCP_173 | DamageType.SCP_939; + + + /// + /// Checks if two s are on the same team + /// Returns False when both are the same player + /// + public static bool IsTeam(Player player1, Player player2) + { + if (player1 == null || player2 == null || player1.PlayerId == player2.PlayerId) + return false; + if (NineTailsTeam.Contains((int)player1.TeamRole.Team) && NineTailsTeam.Contains((int)player2.TeamRole.Team)) + return true; + else if (ChaosTeam.Contains((int)player1.TeamRole.Team) && ChaosTeam.Contains((int)player2.TeamRole.Team)) + return true; + else + return false; + } + + } +} diff --git a/AdminToolbox/AdminToolbox/API/WaitForTeleport.cs b/AdminToolbox/AdminToolbox/API/WaitForTeleport.cs new file mode 100644 index 0000000..2bc8a39 --- /dev/null +++ b/AdminToolbox/AdminToolbox/API/WaitForTeleport.cs @@ -0,0 +1,13 @@ +using System; +using Smod2.API; + +namespace AdminToolbox.API +{ + internal class WaitForTeleport + { + internal Player Player { get; set; } + internal Vector Pos { get; set; } + internal DateTime DateTime { get; set; } + internal bool Done { get; set; } = false; + } +} diff --git a/AdminToolbox/AdminToolbox/API/WarpPoint.cs b/AdminToolbox/AdminToolbox/API/WarpPoint.cs new file mode 100644 index 0000000..165977c --- /dev/null +++ b/AdminToolbox/AdminToolbox/API/WarpPoint.cs @@ -0,0 +1,46 @@ +using Smod2.API; + +namespace AdminToolbox.API +{ + /// + /// The class uses for warp-points + /// + public class WarpPoint + { + public string Name { get; set; } + public string Description { get; set; } = ""; + public ATVector Vector { get; set; } + public WarpPoint() { } + } + + /// + /// This is just a wrapper for the SMod because the SMod Vector is not JSON Serializable + /// + public class ATVector + { + public float X { get; set; } + public float Y { get; set; } + public float Z { get; set; } + + public ATVector() { } + public ATVector(float X, float Y, float Z) + { + this.X = X; + this.Y = Y; + this.Z = Z; + } + public ATVector(Vector vec) + { + this.X = vec.x; + this.Y = vec.y; + this.Z = vec.z; + } + /// + /// Converting the ATVector to because the SMod Vector is not JSON Serializable + /// + public Smod2.API.Vector ToSMVector() + { + return new Smod2.API.Vector(X, Y, Z); + } + } +} diff --git a/AdminToolbox/AdminToolbox/AdminToolbox.cs b/AdminToolbox/AdminToolbox/AdminToolbox.cs index f569961..e4f40b8 100644 --- a/AdminToolbox/AdminToolbox/AdminToolbox.cs +++ b/AdminToolbox/AdminToolbox/AdminToolbox.cs @@ -1,38 +1,42 @@ +using System; +using System.Collections.Generic; using Smod2; +using Smod2.API; using Smod2.Attributes; -using Smod2.Events; +using Smod2.Config; using Smod2.EventHandlers; -using Smod2.API; -using System; -using System.IO; -using System.Collections.Generic; -using System.Linq; -using AdminToolbox.Managers; -using AdminToolbox.API; +using Smod2.Events; namespace AdminToolbox { + using API; + using Command; + using Managers; + /// - /// The ! + /// The main class /// [PluginDetails( author = "Evan (AKA Rnen)", name = "Admin Toolbox", description = "Plugin for advanced admin tools", id = "rnen.admin.toolbox", - version = "1.3.8-2", + version = AT_Version + "-" + AT_Revision, SmodMajor = 3, - SmodMinor = 1, - SmodRevision = 22 + SmodMinor = 7, + SmodRevision = 0 )] public class AdminToolbox : Plugin { - internal const string assemblyInfoVersion = "1.3.8.2"; + internal const string AT_Version = "1.3.8"; + internal const string AT_Revision = "14"; #region GitHub release info - DateTime LastOnlineCheck = DateTime.Now; + private DateTime LastOnlineCheck = DateTime.Now; private ATWeb.AT_LatestReleaseInfo LatestReleaseInfo; + internal static List waitForTeleports = new List(); + internal ATWeb.AT_LatestReleaseInfo GetGitReleaseInfo() { if (LastOnlineCheck.AddMinutes(5) < DateTime.Now || LatestReleaseInfo == null) @@ -44,30 +48,24 @@ internal ATWeb.AT_LatestReleaseInfo GetGitReleaseInfo() } #endregion -#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member - public List scheduledCommands; - public ScheduledRestart scheduledRestart; -#pragma warning restore CS1591 // Missing XML comment for publicly visible type or member - /// - /// s instance of + /// The plugin's instance of /// public static readonly LogManager logManager = new LogManager(); /// - /// s instance of + /// The plugin's instance instance of /// public static readonly WarpManager warpManager = new WarpManager(); /// - /// s instance of + /// The plugin's instance instance of /// public static readonly ATFileManager atfileManager = new ATFileManager(); internal static bool roundStatsRecorded = false; internal static readonly ATRoundStats roundStats = new ATRoundStats(); -#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member internal static bool isRoundFinished = false, isColored = false, @@ -76,53 +74,50 @@ internal static bool isStarting = true; public static bool lockRound = false, - intercomLock = false; + intercomLock = false, + respawnLock = false; + /// + /// debug mode + /// + public static bool DebugMode { get; internal set; } #if DEBUG - public static bool DebugMode { get; internal set; } = true; + = true; #else - public static bool DebugMode { get; internal set; } = false; + = false; #endif -#pragma warning restore CS1591 // Missing XML comment for publicly visible type or member /// - /// of containing settings on all players. Uses as KEY + /// of containing the plugin's settings on all players. Uses as KEY /// public static Dictionary ATPlayerDict { get; internal set; } = new Dictionary(); - + /// /// of all current warp vectors /// - public static Dictionary warpVectors = new Dictionary(warpManager.presetWarps); - - internal static Vector JailPos => warpVectors?["jail"]?.Vector ?? new Vector(53, 1020, -44); + public static Dictionary WarpVectorDict = new Dictionary(warpManager.presetWarps); /// /// round count /// public static int RoundCount { get; internal set; } = 0; - internal static string _logStartTime; - - internal static AdminToolbox plugin; + + internal static AdminToolbox singleton; /// /// Called when gets disabled /// public override void OnDisable() - => this.Info(this.Details.name + " v." + this.Details.version + (isColored ? " - @#fg=Red;Disabled@#fg=Default;" : " - Disabled")); + => Debug(this.Details.name + " v." + this.Details.version + (isColored ? " - @#fg=Red;Disabled@#fg=Default;" : " - Disabled")); /// /// Called when gets enabled /// public override void OnEnable() { - plugin = this; + singleton = this; ATFileManager.WriteVersionToFile(); - this.Info(this.Details.name + " v." + this.Details.version + (isColored ? " - @#fg=Green;Enabled@#fg=Default;" : " - Enabled")); - _logStartTime = DateTime.Now.Year.ToString() + "-" + ((DateTime.Now.Month >= 10) ? DateTime.Now.Month.ToString() : ("0" + DateTime.Now.Month.ToString())) + "-" + ((DateTime.Now.Day >= 10) ? DateTime.Now.Day.ToString() : ("0" + DateTime.Now.Day.ToString())) + " " + ((DateTime.Now.Hour >= 10) ? DateTime.Now.Hour.ToString() : ("0" + DateTime.Now.Hour.ToString())) + "." + ((DateTime.Now.Minute >= 10) ? DateTime.Now.Minute.ToString() : ("0" + DateTime.Now.Minute.ToString())) + "." + ((DateTime.Now.Second >= 10) ? DateTime.Now.Second.ToString() : ("0" + DateTime.Now.Second.ToString())); - logManager.WriteToLog(new string[] { "\"Plugin Started\"" }, LogManager.ServerLogType.Misc); - scheduledRestart = new ScheduledRestart(this); - scheduledCommands = new List(); + Debug(this.Details.name + " v." + this.Details.version + (isColored ? " - @#fg=Green;Enabled@#fg=Default;" : " - Enabled")); } /// @@ -137,101 +132,106 @@ public override void Register() internal void RegisterEvents() { - this.AddEventHandlers(new RoundEventHandler(this), Priority.Normal); - this.AddEventHandler(typeof(IEventHandlerPlayerHurt), new DamageDetect(this), Priority.Normal); - this.AddEventHandler(typeof(IEventHandlerPlayerDie), new DieDetect(this), Priority.Normal); - this.AddEventHandlers(new MyMiscEvents(this), Priority.Normal); + this.AddEventHandlers(new RoundEventHandler(this)); + this.AddEventHandler(typeof(IEventHandlerPlayerHurt), new DamageDetect(this)); + this.AddEventHandler(typeof(IEventHandlerPlayerDie), new DieDetect(this)); + this.AddEventHandlers(new MyMiscEvents(this)); this.AddEventHandler(typeof(IEventHandlerCheckRoundEnd), new LateOnCheckRoundEndEvent(this), Priority.Highest); + this.AddEventHandler(typeof(IEventHandlerCheckEscape), new LateEscapeEventCheck(), Priority.Highest); } - internal void UnRegisterEvents() - { - this.eventManager.RemoveEventHandlers(this); - } + internal void UnRegisterEvents() => EventManager.Manager.RemoveEventHandlers(this); internal void RegisterCommands() { - this.AddCommands(new string[] { "spec", "spectator", "atoverwatch" }, new Command.SpectatorCommand()); - this.AddCommands(new string[] { "p", "player", "playerinfo", "pinfo" }, new Command.PlayerCommand()); - this.AddCommands(new string[] { "players", "playerlist", "plist" }, new Command.PlayerListCommand()); - this.AddCommands(new string[] { "atheal", "at-heal" }, new Command.HealCommand()); - this.AddCommands(new string[] { "atgod", "atgodmode", "at-god", "at-godmode" }, new Command.GodModeCommand()); - this.AddCommand("nodmg", new Command.NoDmgCommand()); - this.AddCommands(new string[] { "tut", "tutorial" }, new Command.TutorialCommand()); - this.AddCommand("role", new Command.RoleCommand()); - this.AddCommands(new string[] { "keep", "keepsettings" }, new Command.KeepSettingsCommand()); - this.AddCommands(new string[] { "athp", "atsethp", "at-hp", "at-sethp" }, new Command.SetHpCommand()); - this.AddCommand("pos", new Command.PosCommand()); - this.AddCommand("tpx", new Command.TeleportCommand()); - this.AddCommand("warp", new Command.WarpCommmand()); - this.AddCommand("warps", new Command.WarpsCommmand()); - this.AddCommands(new string[] { "roundlock", "lockround", "rlock", "lockr" }, new Command.RoundLockCommand(this)); - this.AddCommands(new string[] { "breakdoor", "bd", "breakdoors" }, new Command.BreakDoorsCommand()); - this.AddCommands(new string[] { "pl", "playerlockdown", "plock", "playerlock" }, new Command.LockdownCommand()); - this.AddCommand("atcolor", new Command.ATColorCommand(this)); - this.AddCommand("atdisable", new Command.ATDisableCommand(this)); - this.AddCommands(new string[] { "ik", "instakill", "instantkill" }, new Command.InstantKillCommand()); - this.AddCommands(new string[] { "j", "jail" }, new Command.JailCommand()); - this.AddCommands(new string[] { "il", "ilock", "INTERLOCK", "intercomlock" }, new Command.IntercomLockCommand(this)); - this.AddCommands(new string[] { "s", "si", "server", "serverinfo" }, new Command.ServerCommand()); - this.AddCommands(new string[] { "e", "empty" }, new Command.EmptyCommand()); - this.AddCommands(new string[] { "atban", "offlineban", "oban" }, new Command.ATBanCommand(this)); - this.AddCommands(new string[] { "kill", "slay" }, new Command.KillCommand(this)); - this.AddCommands(new string[] { "atspeak", "speak", "atintercom", "at-speak" }, new Command.SpeakCommand()); - this.AddCommands(new string[] { "ghost", "ghostmode", "ghostm", "invisible", "gh" }, new Command.GhostCommand(this)); - this.AddCommands(new string[] { "athelp", "atbhelp", "at-help", "admintoolboxhelp", "admintoolbox-help" }, new Command.AT_HelpCommand()); - this.AddCommands(new string[] { "at", "admintoolbox", "atb", "a-t", "admin-toolbox", "admin_toolbox" }, new Command.ATCommand(this)); - this.AddCommands(new string[] { "serverstats", "sstats", "roundstats", "rstats" }, new Command.ServerStatsCommand(this)); - //this.AddCommands(new string[] { "timedrestart", "trestart" }, new Command.TimedCommand(this)); - } - internal void UnRegisterCommands() - { - this.pluginManager.CommandManager.UnregisterCommands(this); + this.AddCommands(SpectatorCommand.CommandAliases, new SpectatorCommand()); + this.AddCommands(PlayerCommand.CommandAliases, new PlayerCommand()); + this.AddCommands(PlayerListCommand.CommandAliases, new PlayerListCommand()); + this.AddCommands(HealCommand.CommandAliases, new HealCommand()); + this.AddCommands(GodModeCommand.CommandAliases, new GodModeCommand()); + this.AddCommands(NoDmgCommand.CommandAliases, new NoDmgCommand()); + this.AddCommands(TutorialCommand.CommandAliases, new TutorialCommand()); + this.AddCommands(RoleCommand.CommandAliases, new RoleCommand()); + this.AddCommands(KeepSettingsCommand.CommandAliases, new KeepSettingsCommand()); + this.AddCommands(SetHpCommand.CommandAliases, new SetHpCommand()); + this.AddCommands(PosCommand.CommandAliases, new PosCommand()); + this.AddCommands(TeleportCommand.CommandAliases, new TeleportCommand()); + this.AddCommands(WarpCommmand.CommandAliases, new WarpCommmand()); + this.AddCommands(WarpsCommmand.CommandAliases, new WarpsCommmand()); + this.AddCommands(RoundLockCommand.CommandAliases, new RoundLockCommand(this)); + this.AddCommands(BreakDoorsCommand.CommandAliases, new BreakDoorsCommand()); + this.AddCommands(LockdownCommand.CommandAliases, new LockdownCommand()); + this.AddCommands(ATColorCommand.CommandAliases, new ATColorCommand(this)); + this.AddCommands(ATDisableCommand.CommandAliases, new ATDisableCommand(this)); + this.AddCommands(InstantKillCommand.CommandAliases, new InstantKillCommand()); + this.AddCommands(JailCommand.CommandAliases, new JailCommand()); + this.AddCommands(IntercomLockCommand.CommandAliases, new IntercomLockCommand(this)); + this.AddCommands(ServerCommand.CommandAliases, new ServerCommand()); + this.AddCommands(EmptyCommand.CommandAliases, new EmptyCommand()); + this.AddCommands(ATBanCommand.CommandAliases, new ATBanCommand(this)); + this.AddCommands(KillCommand.CommandAliases, new KillCommand(this)); + this.AddCommands(SpeakCommand.CommandAliases, new SpeakCommand()); + this.AddCommands(GhostCommand.CommandAliases, new GhostCommand(this)); + this.AddCommands(AT_HelpCommand.CommandAliases, new AT_HelpCommand()); + this.AddCommands(ATCommand.CommandAliases, new ATCommand(this)); + this.AddCommands(ServerStatsCommand.CommandAliases, new ServerStatsCommand(this)); + this.AddCommands(LockDoorsCommand.CommandAliases, new LockDoorsCommand(this)); + this.AddCommands(RespawnLockCommand.CommandAliases, new RespawnLockCommand()); + this.AddCommands(ClosestDoorCommand.CommandAliases, new ClosestDoorCommand(this)); + this.AddCommands(GrenadeModeCommand.CommandAliases, new GrenadeModeCommand(this)); + this.AddCommands(InfiniteItemCommand.CommandAliases, new InfiniteItemCommand(this)); } + internal void UnRegisterCommands() => PluginManager.CommandManager.UnregisterCommands(this); internal void RegisterConfigs() { - this.AddConfig(new Smod2.Config.ConfigSetting("admintoolbox_enable", true, Smod2.Config.SettingType.BOOL, true, "Enable/Disable AdminToolbox")); - this.AddConfig(new Smod2.Config.ConfigSetting("admintoolbox_colors", false, Smod2.Config.SettingType.BOOL, true, "Enable/Disable AdminToolbox colors in server window")); - this.AddConfig(new Smod2.Config.ConfigSetting("admintoolbox_tracking", true, Smod2.Config.SettingType.BOOL, true, "Appends the AdminToolbox version to your server name, this is for tracking how many servers are running the plugin")); - - this.AddConfig(new Smod2.Config.ConfigSetting("admintoolbox_tutorial_dmg_allowed", new int[] { -1 }, Smod2.Config.SettingType.NUMERIC_LIST, true, "What (int)damagetypes TUTORIAL is allowed to take")); - - this.AddConfig(new Smod2.Config.ConfigSetting("admintoolbox_debug_damagetypes", new int[] { 5, 13, 14, 15, 16, 17 }, Smod2.Config.SettingType.NUMERIC_LIST, true, "What (int)damagetypes to debug")); - this.AddConfig(new Smod2.Config.ConfigSetting("admintoolbox_debug_server", false, Smod2.Config.SettingType.BOOL, true, "Debugs damage dealt by server")); - this.AddConfig(new Smod2.Config.ConfigSetting("admintoolbox_debug_spectator", false, Smod2.Config.SettingType.BOOL, true, "Debugs damage done to/by spectators")); - this.AddConfig(new Smod2.Config.ConfigSetting("admintoolbox_debug_tutorial", false, Smod2.Config.SettingType.BOOL, true, "Debugs damage done to tutorial")); - this.AddConfig(new Smod2.Config.ConfigSetting("admintoolbox_debug_player_damage", false, Smod2.Config.SettingType.BOOL, true, "Debugs damage to all players except teammates")); - this.AddConfig(new Smod2.Config.ConfigSetting("admintoolbox_debug_friendly_damage", false, Smod2.Config.SettingType.BOOL, true, "Debugs damage to teammates")); - this.AddConfig(new Smod2.Config.ConfigSetting("admintoolbox_debug_player_kill", false, Smod2.Config.SettingType.BOOL, true, "Debugs player kills except teamkills")); - this.AddConfig(new Smod2.Config.ConfigSetting("admintoolbox_debug_friendly_kill", true, Smod2.Config.SettingType.BOOL, true, "Debugs team-kills")); - this.AddConfig(new Smod2.Config.ConfigSetting("admintoolbox_debug_scp_and_self_killed", false, Smod2.Config.SettingType.BOOL, true, "Debug suicides and SCP kills")); - - this.AddConfig(new Smod2.Config.ConfigSetting("admintoolbox_endedRound_damagemultiplier", 1f, Smod2.Config.SettingType.FLOAT, true, "Damage multiplier after end of round")); - this.AddConfig(new Smod2.Config.ConfigSetting("admintoolbox_round_damagemultiplier", 1f, Smod2.Config.SettingType.FLOAT, true, "Damage multiplier")); - this.AddConfig(new Smod2.Config.ConfigSetting("admintoolbox_decontamination_damagemultiplier", 1f, Smod2.Config.SettingType.FLOAT, true, "Damage multiplier for the decontamination of LCZ")); - this.AddConfig(new Smod2.Config.ConfigSetting("admintoolbox_friendlyfire_damagemultiplier", 1f, Smod2.Config.SettingType.FLOAT, true, "Damage multiplier for friendly fire")); - - this.AddConfig(new Smod2.Config.ConfigSetting("admintoolbox_custom_nuke_cards", false, Smod2.Config.SettingType.BOOL, true, "Enables the use of custom keycards for the activation of the nuke")); - this.AddConfig(new Smod2.Config.ConfigSetting("admintoolbox_nuke_card_list", new int[] { 6, 9, 11 }, Smod2.Config.SettingType.NUMERIC_LIST, true, "List of all cards that can enable the nuke")); - - this.AddConfig(new Smod2.Config.ConfigSetting("admintoolbox_log_teamkills", false, Smod2.Config.SettingType.BOOL, true, "Writing logfiles for teamkills")); - this.AddConfig(new Smod2.Config.ConfigSetting("admintoolbox_log_kills", false, Smod2.Config.SettingType.BOOL, true, "Writing logfiles for regular kills")); - this.AddConfig(new Smod2.Config.ConfigSetting("admintoolbox_log_commands", false, Smod2.Config.SettingType.BOOL, true, "Writing logfiles for all AT command usage")); - - this.AddConfig(new Smod2.Config.ConfigSetting("admintoolbox_round_info", true, Smod2.Config.SettingType.BOOL, true, "Prints round count and player number on round start & end")); - this.AddConfig(new Smod2.Config.ConfigSetting("admintoolbox_player_join_info", true, Smod2.Config.SettingType.BOOL, true, "Writes player name in console on players joining")); - + #region Core-configs + this.AddConfig(new ConfigSetting("admintoolbox_enable", true, true, "Enable/Disable AdminToolbox")); + this.AddConfig(new ConfigSetting("admintoolbox_colors", false, true, "Enable/Disable AdminToolbox colors in server window")); + this.AddConfig(new ConfigSetting("admintoolbox_tracking", true, true, "Appends the AdminToolbox version to your server name, this is for tracking how many servers are running the plugin")); + #endregion + + this.AddConfig(new ConfigSetting("admintoolbox_tutorial_dmg_allowed", new int[] { -1 }, true, "What (int)damagetypes TUTORIAL is allowed to take")); + + #region Debug + this.AddConfig(new ConfigSetting("admintoolbox_debug_damagetypes", new int[] { 5, 13, 14, 15, 16, 17 }, true, "What (int)damagetypes to debug")); + this.AddConfig(new ConfigSetting("admintoolbox_debug_server", false, true, "Debugs damage dealt by server")); + this.AddConfig(new ConfigSetting("admintoolbox_debug_spectator", false, true, "Debugs damage done to/by spectators")); + this.AddConfig(new ConfigSetting("admintoolbox_debug_tutorial", false, true, "Debugs damage done to tutorial")); + this.AddConfig(new ConfigSetting("admintoolbox_debug_player_damage", false, true, "Debugs damage to all players except teammates")); + this.AddConfig(new ConfigSetting("admintoolbox_debug_friendly_damage", false, true, "Debugs damage to teammates")); + this.AddConfig(new ConfigSetting("admintoolbox_debug_player_kill", false, true, "Debugs player kills except teamkills")); + this.AddConfig(new ConfigSetting("admintoolbox_debug_friendly_kill", true, true, "Debugs team-kills")); + this.AddConfig(new ConfigSetting("admintoolbox_debug_scp_and_self_killed", false, true, "Debug suicides and SCP kills")); + #endregion + + #region DamageMultipliers + this.AddConfig(new ConfigSetting("admintoolbox_endedRound_damagemultiplier", 1f, true, "Damage multiplier after end of round")); + this.AddConfig(new ConfigSetting("admintoolbox_round_damagemultiplier", 1f, true, "Damage multiplier")); + this.AddConfig(new ConfigSetting("admintoolbox_decontamination_damagemultiplier", 1f, true, "Damage multiplier for the decontamination of LCZ")); + this.AddConfig(new ConfigSetting("admintoolbox_friendlyfire_damagemultiplier", 1f, true, "Damage multiplier for friendly fire")); + this.AddConfig(new ConfigSetting("admintoolbox_pocketdimention_damagemultiplier", 1f, true, "Damage multiplier for pocket dimention damage")); + #endregion + #region Cards + this.AddConfig(new ConfigSetting("admintoolbox_custom_nuke_cards", false, true, "Enables the use of custom keycards for the activation of the nuke")); + this.AddConfig(new ConfigSetting("admintoolbox_nuke_card_list", new int[] { 6, 9, 11 }, true, "List of all cards that can enable the nuke")); + #endregion + #region Log-Stuff + this.AddConfig(new ConfigSetting("admintoolbox_log_teamkills", false, true, "Writing logfiles for teamkills")); + this.AddConfig(new ConfigSetting("admintoolbox_log_kills", false, true, "Writing logfiles for regular kills")); + this.AddConfig(new ConfigSetting("admintoolbox_log_commands", false, true, "Writing logfiles for all AT command usage")); + + this.AddConfig(new ConfigSetting("admintoolbox_round_info", true, true, "Prints round count and player number on round start & end")); + this.AddConfig(new ConfigSetting("admintoolbox_player_join_info", true, true, "Writes player name in console on players joining")); + #endregion + #region Intercom //this.AddConfig(new Smod2.Config.ConfigSetting("admintoolbox_intercom_whitelist", new string[] { string.Empty }, Smod2.Config.SettingType.LIST, true, "What ServerRank can use the Intercom to your specified settings")); - this.AddConfig(new Smod2.Config.ConfigSetting("admintoolbox_intercom_steamid_blacklist", new string[] { string.Empty }, Smod2.Config.SettingType.LIST, true, "Blacklist of steamID's that cannot use the intercom")); - this.AddConfig(new Smod2.Config.ConfigSetting("admintoolbox_intercomlock", false, Smod2.Config.SettingType.BOOL, true, "If set to true, locks the command for all non-whitelist players")); + this.AddConfig(new ConfigSetting("admintoolbox_intercom_UserId_blacklist", new string[0], true, "Blacklist of UserId's that cannot use the intercom")); + this.AddConfig(new ConfigSetting("admintoolbox_intercomlock", false, true, "If set to true, locks the command for all non-whitelist players")); + #endregion - this.AddConfig(new Smod2.Config.ConfigSetting("admintoolbox_block_role_damage", new string[] { string.Empty }, Smod2.Config.SettingType.LIST, true, "What roles cannot attack other roles")); + this.AddConfig(new ConfigSetting("admintoolbox_block_role_damage", new string[0], true, "What roles cannot attack other roles")); + this.AddConfig(new ConfigSetting("admintoolbox_ban_webhooks", new string[0], true, "Links to channel webhooks for bans")); //this.AddConfig(new Smod2.Config.ConfigSetting("admintoolbox_timedrestart_automessages", new string[] { "" }, Smod2.Config.SettingType.LIST, true, "")); //this.AddConfig(new Smod2.Config.ConfigSetting("atb_timedrestart_automessages", new string[] { "" }, Smod2.Config.SettingType.LIST, true, "")); - - } - internal void UnRegisterConfigs() - { - } @@ -241,42 +241,49 @@ internal static void AddMissingPlayerVariables() AddMissingPlayerVariables(PluginManager.Manager.Server.GetPlayers()); } internal static void AddMissingPlayerVariables(Player player) - { - AddMissingPlayerVariables(new List() { player }); - } + => AddMissingPlayerVariables(new List() { player }); internal static void AddMissingPlayerVariables(List players) + => AddMissingPlayerVariables(players.ToArray()); + internal static void AddMissingPlayerVariables(Player[] players) { - if (players == null || players.Count < 1) players = PluginManager.Manager.Server.GetPlayers(); - if (players.Count > 0) - foreach(Player player in players.Where(p => p != null && !string.IsNullOrEmpty(p.SteamId))) + Player[] allPlayers = PluginManager.Manager.Server.GetPlayers().ToArray(); + if (allPlayers.Length == 0) + { + return; + } + else if (players == null || players.Length < 1) + { + players = allPlayers; + } + if (players.Length > 0) + { + foreach (Player player in players) + { + if (player != null && !string.IsNullOrEmpty(player.UserId)) + { AddToPlayerDict(player); + } + } + } } private static void AddToPlayerDict(Player player) { if (player != null && player is Player p && - !string.IsNullOrEmpty(p.SteamId) && !ATPlayerDict.ContainsKey(p.SteamId)) + !string.IsNullOrEmpty(p.UserId) && !ATPlayerDict.ContainsKey(p.UserId)) { - ATPlayerDict.Add(p.SteamId, new PlayerSettings(p.SteamId)); + ATPlayerDict.Add(p.UserId, new PlayerSettings(p.UserId)); } } - internal bool NewerVersionAvailable() - { - string thisVersion = this.Details.version.Split('-').FirstOrDefault().Replace(".", string.Empty); - string onlineVersion = this.GetGitReleaseInfo().Version.Replace(".", string.Empty); - - if (int.TryParse(thisVersion, out int thisV) - && int.TryParse(onlineVersion, out int onlineV) - && onlineV > thisV) - return true; - else return false; - } - - public void Debug(string message) + /// + /// Debugs messages when is enabled + /// + public new void Debug(string message) { if (DebugMode) this.Info(message); } + } -} \ No newline at end of file +} diff --git a/AdminToolbox/AdminToolbox/AdminToolbox.csproj b/AdminToolbox/AdminToolbox/AdminToolbox.csproj index 042abf5..d856162 100644 --- a/AdminToolbox/AdminToolbox/AdminToolbox.csproj +++ b/AdminToolbox/AdminToolbox/AdminToolbox.csproj @@ -24,6 +24,7 @@ false + AnyCPU none @@ -35,14 +36,15 @@ false ..\Builds\AdminToolbox.xml false + CS1591 OnBuildSuccess - + False - ..\..\..\..\SCP_SL_SERVER\SCPSL_Data\Managed\Assembly-CSharp.dll + ..\Builds\Assembly-CSharp.dll False @@ -50,9 +52,9 @@ ..\..\..\..\SCP_SL_SERVER\SCPSL_Data\Managed\Newtonsoft.Json.dll False - + False - ..\..\..\..\SCP_SL_SERVER\SCPSL_Data\Managed\Smod2.dll + ..\Builds\Smod2.dll False @@ -69,10 +71,6 @@ ..\..\..\..\SCP_SL_SERVER\SCPSL_Data\Managed\UnityEngine.CoreModule.dll False - - ..\..\..\..\SCP_SL_SERVER\SCPSL_Data\Managed\UnityEngine.Networking.dll - False - ..\..\..\..\SCP_SL_SERVER\SCPSL_Data\Managed\UnityEngine.PhysicsModule.dll False @@ -88,12 +86,19 @@ + - - + + + + + + + + @@ -103,15 +108,14 @@ - + - @@ -136,11 +140,13 @@ - + - + + + copy $(TargetPath) D:\SCP_SL_SERVER\sm_plugins diff --git a/AdminToolbox/AdminToolbox/Commands/AT_TemplateCommand.cs b/AdminToolbox/AdminToolbox/Commands/AT_TemplateCommand.cs index 708c656..43e7639 100644 --- a/AdminToolbox/AdminToolbox/Commands/AT_TemplateCommand.cs +++ b/AdminToolbox/AdminToolbox/Commands/AT_TemplateCommand.cs @@ -1,36 +1,41 @@ -using Smod2.Commands; +using System.Collections.Generic; +using System.Linq; using Smod2; using Smod2.API; -using System.Collections.Generic; +using Smod2.Commands; namespace AdminToolbox.Command { - class AT_TemplateCommand : ICommandHandler + public class AT_TemplateCommand : ICommandHandler { private readonly AdminToolbox plugin; - static IConfigFile Config => ConfigManager.Manager.Config; - Server Server => PluginManager.Manager.Server; + private static IConfigFile Config => ConfigManager.Manager.Config; - public AT_TemplateCommand(AdminToolbox plugin) => this.plugin = plugin; + private Server Server => PluginManager.Manager.Server; - public string GetCommandDescription() => ""; + public AT_TemplateCommand(AdminToolbox plugin) => this.plugin = plugin; - public string GetUsage() => ""; + public string GetCommandDescription() => "This is a description"; + public string GetUsage() => "(" + string.Join(" / ", CommandAliases) + ")"; + public static readonly string[] CommandAliases = new string[] { "TEMPLATE", "TEMPLATE2" }; public string[] OnCall(ICommandSender sender, string[] args) { - Player caller = (sender is Player _p) ? _p : null; + // Gets the caller as a "Player" object + Player caller = sender as Player; if (args.Length > 0) { //Get player from first arguement of OnCall - Player targetPlayer = API.GetPlayerFromString.GetPlayer(args[0]); - //If player could not be found, return + Player targetPlayer = Server.GetPlayers(args[0]).FirstOrDefault(); + + //If player could not be found, return reply to command user if (targetPlayer == null) { return new string[] { "Could not find player: " + args[0] }; ; } - //Adds player(s) to the AdminToolbox settings + //Adds player(s) to the AdminToolbox player dictionary AdminToolbox.AddMissingPlayerVariables(new List { targetPlayer, caller }); + //Do whatever with the found player return new string[] { "We did something to player: " + targetPlayer.Name + "!" }; } @@ -43,4 +48,4 @@ public string[] OnCall(ICommandSender sender, string[] args) return new string[] { GetUsage() }; } } -} \ No newline at end of file +} diff --git a/AdminToolbox/AdminToolbox/Commands/Facility/ClosestDoorCommand.cs b/AdminToolbox/AdminToolbox/Commands/Facility/ClosestDoorCommand.cs new file mode 100644 index 0000000..cad0a64 --- /dev/null +++ b/AdminToolbox/AdminToolbox/Commands/Facility/ClosestDoorCommand.cs @@ -0,0 +1,88 @@ +using System.Linq; +using Smod2; +using Smod2.API; +using Smod2.Commands; +using SMDoor = Smod2.API.Door; + +namespace AdminToolbox.Command +{ + public class ClosestDoorCommand : ICommandHandler + { + private readonly AdminToolbox plugin; + + private static IConfigFile Config => ConfigManager.Manager.Config; + + private Server Server => PluginManager.Manager.Server; + + public ClosestDoorCommand(AdminToolbox plugin) => this.plugin = plugin; + + public string GetCommandDescription() => "This is a description"; + public string GetUsage() => "(" + string.Join(" / ", CommandAliases) + ")"; + public static readonly string[] CommandAliases = new string[] { "CLOSESTDOOR", "CLSDOOR", "ATDOOR", "ATD" }; + + public string[] OnCall(ICommandSender sender, string[] args) + { + // Gets the caller as a "Player" object + + if (args.Length > 0) + { + //Get player from first arguement of OnCall + Player targetPlayer = args.Length > 1 ? Server.GetPlayers(args[0]).FirstOrDefault() : sender as Player; + + //If player could not be found, return reply to command user + if (targetPlayer == null) + return new string[] { "Could not find player" }; + + //Adds player(s) to the AdminToolbox player dictionary + AdminToolbox.AddMissingPlayerVariables(targetPlayer); + + SMDoor closestDoor = null; + float dist = float.MaxValue; + float newDist = float.MaxValue; + + foreach (SMDoor d in Server.Map.GetDoors()) + { + newDist = Vector.Distance(d.Position, targetPlayer.GetPosition()); + if (newDist < dist) + { + closestDoor = d; + dist = newDist; + } + } + + string arg = args.Length > 1 ? args[1].ToUpper() : args[0].ToUpper(); + + switch (arg) + { + case "BREAK": + case "DESTROY": + case "DESTR": + case "BRK": + closestDoor.Destroyed = true; + return new string[] { "Closest door broken." }; + case "LOCK": + case "L": + closestDoor.Locked = true; + return new string[] { "Closest door locked." }; + case "UNLOCK": + case "UL": + case "!L": + closestDoor.Locked = false; + return new string[] { "Closest door unlocked." }; + case "OPEN": + case "OP": + closestDoor.Open = true; + return new string[] { "Closest door opened." }; + case "CLOSE": + case "CL": + closestDoor.Open = false; + return new string[] { "Closest door closed." }; + default: + return new string[] { "Word: " + arg + " is not recognized" }; + } + } + else + return new string[] { GetUsage() }; + } + } +} diff --git a/AdminToolbox/AdminToolbox/Commands/Facility/DoorCommand.cs b/AdminToolbox/AdminToolbox/Commands/Facility/DoorCommand.cs deleted file mode 100644 index f8f1ae2..0000000 --- a/AdminToolbox/AdminToolbox/Commands/Facility/DoorCommand.cs +++ /dev/null @@ -1,65 +0,0 @@ -using Smod2.Commands; -using Smod2; -using Smod2.API; -using System.Collections.Generic; - -namespace AdminToolbox.Command -{ - class DoorCommand : ICommandHandler - { - private readonly AdminToolbox plugin; - - public DoorCommand(AdminToolbox plugin) - { - this.plugin = plugin; - } - - public string GetCommandDescription() - { - return ""; - } - - public string GetUsage() - { - return ""; - } - - public string[] OnCall(ICommandSender sender, string[] args) - { - Server server = PluginManager.Manager.Server; - if (args.Length > 0) - { - Player myPlayer = API.GetPlayerFromString.GetPlayer(args[0]); - if (myPlayer == null) { return new string[] { "Couldn't get player: " + args[0] }; ; } - if (args.Length > 1) - { - if (args[1].ToLower() == "open") - { - foreach (var item in server.Map.GetDoors()) - item.Open = true; - return new string[] { "Door Opened" }; - } - else if (args[1].ToLower() == "close") - { - foreach (var item in server.Map.GetDoors()) - item.Open = false; - return new string[] { "Door Closed" }; - } - else if (args[1].ToLower() == "lock") - { - return new string[] { "Door Locked" }; - } - else if (args[1].ToLower() == "unlock") - { - return new string[] { "Door UnLocked" }; - } - else - return new string[] { GetUsage() }; - } - else - return new string[] { GetUsage() }; - } - return new string[] { GetUsage() }; - } - } -} \ No newline at end of file diff --git a/AdminToolbox/AdminToolbox/Commands/Facility/IntercomLockCommand.cs b/AdminToolbox/AdminToolbox/Commands/Facility/IntercomLockCommand.cs index 10a32ee..fa58ee4 100644 --- a/AdminToolbox/AdminToolbox/Commands/Facility/IntercomLockCommand.cs +++ b/AdminToolbox/AdminToolbox/Commands/Facility/IntercomLockCommand.cs @@ -1,51 +1,47 @@ -using Smod2.Commands; -using Smod2; -using Smod2.API; +using Smod2.Commands; namespace AdminToolbox.Command { - class IntercomLockCommand : ICommandHandler + using API.Extentions; + + public class IntercomLockCommand : ICommandHandler { private readonly AdminToolbox plugin; - public IntercomLockCommand(AdminToolbox plugin) - { - this.plugin = plugin; - } - public string GetCommandDescription() - { - return "Enables/Disables the intercom for non-whitelisted players"; - } + public IntercomLockCommand(AdminToolbox plugin) => this.plugin = plugin; + public string GetCommandDescription() => "Enables/Disables the intercom for non-whitelisted players"; + public string GetUsage() => "(" + string.Join(" / ", CommandAliases) + ") "; - public string GetUsage() - { - return "(IL / ILOCK / INTERCOMLOCK) (bool)"; - } + public static readonly string[] CommandAliases = new string[] { "INTERCOMLOCK", "INTERLOCK", "ILOCK", "IL" }; public string[] OnCall(ICommandSender sender, string[] args) { - Server server = PluginManager.Manager.Server; - if (args.Length >= 1) + if (sender.IsPermitted(CommandAliases, out string[] deniedReply)) { - if (bool.TryParse(args[0], out bool x)) + if (args.Length >= 1) + { + if (bool.TryParse(args[0], out bool x)) + { + AdminToolbox.isColored = x; + if (!AdminToolbox.intercomLockChanged) AdminToolbox.intercomLockChanged = true; + plugin.Info("IntercomLock set to: " + AdminToolbox.intercomLock); + return new string[] { "IntercomLock set to: " + AdminToolbox.intercomLock }; + } + else + return new string[] { "\"ATCOLOR " + args[0] + "\" is not a valid bool" }; + } + else if (args.Length == 0) { - AdminToolbox.isColored = x; + AdminToolbox.intercomLock = !AdminToolbox.intercomLock; if (!AdminToolbox.intercomLockChanged) AdminToolbox.intercomLockChanged = true; plugin.Info("IntercomLock set to: " + AdminToolbox.intercomLock); return new string[] { "IntercomLock set to: " + AdminToolbox.intercomLock }; } else - return new string[] { "\"ATCOLOR " + args[0] + "\" is not a valid bool" }; - } - else if (args.Length == 0) - { - AdminToolbox.intercomLock = !AdminToolbox.intercomLock; - if (!AdminToolbox.intercomLockChanged) AdminToolbox.intercomLockChanged = true; - plugin.Info("IntercomLock set to: " + AdminToolbox.intercomLock); - return new string[] { "IntercomLock set to: " + AdminToolbox.intercomLock }; + return new string[] { GetUsage() }; } else - return new string[] { GetUsage() }; + return deniedReply; } } -} \ No newline at end of file +} diff --git a/AdminToolbox/AdminToolbox/Commands/Facility/JailCommand.cs b/AdminToolbox/AdminToolbox/Commands/Facility/JailCommand.cs index b4b8286..4cccd82 100644 --- a/AdminToolbox/AdminToolbox/Commands/Facility/JailCommand.cs +++ b/AdminToolbox/AdminToolbox/Commands/Facility/JailCommand.cs @@ -1,71 +1,70 @@ -using Smod2.Commands; -using Smod2; -using Smod2.API; using System; -using System.Text.RegularExpressions; -using System.Collections.Generic; -using System.Linq; +using Smod2.API; +using Smod2.Commands; namespace AdminToolbox.Command { - class JailCommand : ICommandHandler + using API; + using API.Extentions; + public class JailCommand : ICommandHandler { - public string GetCommandDescription() - { - return "Jails player for a (optional) specified time"; - } + public string GetCommandDescription() => "Jails player for a specified time"; + public string GetUsage() => "(" + string.Join(" / ", CommandAliases) + ") [PLAYER]