diff --git a/Admin/IW4M ADMIN.csproj b/Admin/Application.csproj similarity index 99% rename from Admin/IW4M ADMIN.csproj rename to Admin/Application.csproj index 3251bc47..599b29c8 100644 --- a/Admin/IW4M ADMIN.csproj +++ b/Admin/Application.csproj @@ -122,14 +122,12 @@ - - True diff --git a/Admin/Commands.cs b/Admin/Commands.cs deleted file mode 100644 index 37b65645..00000000 --- a/Admin/Commands.cs +++ /dev/null @@ -1,24 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Text; -using SharedLibrary; -using SharedLibrary.Network; -using System.Threading.Tasks; - -namespace IW4MAdmin -{ - class Plugins : Command - { - public Plugins(String N, String D, String U, Player.Permission P, int args, bool nT) : base(N, D, U, P, args, nT) { } - - public override async Task ExecuteAsync(Event E) - { - await E.Origin.Tell("^5Loaded Plugins:"); - foreach (SharedLibrary.Interfaces.IPlugin P in PluginImporter.potentialPlugins) - { - await E.Origin.Tell(String.Format("^3{0} ^7[v^3{1}^7] by ^5{2}^7", P.Name, P.Version, P.Author)); - } - } - } -} - \ No newline at end of file diff --git a/Admin/Kayak.cs b/Admin/Kayak.cs index 432b9d91..82d7ceda 100644 --- a/Admin/Kayak.cs +++ b/Admin/Kayak.cs @@ -42,7 +42,7 @@ namespace IW4MAdmin NameValueCollection querySet = new NameValueCollection(); if (request.QueryString != null) - querySet = System.Web.HttpUtility.ParseQueryString(SharedLibrary.Utilities.removeNastyChars(request.QueryString)); + querySet = System.Web.HttpUtility.ParseQueryString(SharedLibrary.Utilities.StripIllegalCharacters(request.QueryString)); querySet.Set("IP", IP); SharedLibrary.HttpResponse requestedPage = WebService.GetPage(request.Path, querySet, request.Headers); diff --git a/Admin/Manager.cs b/Admin/Manager.cs index 1641f451..84e8f8b1 100644 --- a/Admin/Manager.cs +++ b/Admin/Manager.cs @@ -1,14 +1,9 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Text; -using System.Diagnostics; -using System.Runtime.InteropServices; -using System.Net; using System.Threading; using SharedLibrary; using System.IO; -using SharedLibrary.Network; using System.Threading.Tasks; namespace IW4MAdmin @@ -17,12 +12,12 @@ namespace IW4MAdmin { static Manager Instance; public List Servers { get; private set; } - List TaskStatuses; + List TaskStatuses; Database ClientDatabase; Database AliasesDatabase; SharedLibrary.Interfaces.IPenaltyList ClientPenalties; List Commands; - List MessageTokens; + List MessageTokens; Kayak.IScheduler webServiceTask; Thread WebThread; public SharedLibrary.Interfaces.ILogger Logger { get; private set; } @@ -38,8 +33,8 @@ namespace IW4MAdmin Logger = new Logger("Logs/IW4MAdmin.log"); Servers = new List(); Commands = new List(); - TaskStatuses = new List(); - MessageTokens = new List(); + TaskStatuses = new List(); + MessageTokens = new List(); ClientDatabase = new ClientsDB("Database/clients.rm"); AliasesDatabase = new AliasesDB("Database/aliases.rm"); @@ -69,7 +64,7 @@ namespace IW4MAdmin ServerConfig.Generate(); SharedLibrary.WebService.Init(); - PluginImporter.Load(); + SharedLibrary.Plugins.PluginImporter.Load(this); foreach (var file in Configs) { @@ -84,9 +79,12 @@ namespace IW4MAdmin Servers.Add(ServerInstance); // this way we can keep track of execution time and see if problems arise. - var Status = new AsyncStatus(ServerInstance, UPDATE_FREQUENCY); + var Status = new SharedLibrary.Helpers.AsyncStatus(ServerInstance, UPDATE_FREQUENCY); TaskStatuses.Add(Status); + foreach (var Plugin in SharedLibrary.Plugins.PluginImporter.ActivePlugins) + await Plugin.OnLoadAsync(ServerInstance); + Logger.WriteVerbose($"Now monitoring {ServerInstance.Hostname}"); } @@ -114,7 +112,6 @@ namespace IW4MAdmin Running = true; } - public void Start() { while (Running) @@ -166,7 +163,7 @@ namespace IW4MAdmin return Logger; } - public IList GetMessageTokens() + public IList GetMessageTokens() { return MessageTokens; } diff --git a/Admin/Plugins.cs b/Admin/Plugins.cs deleted file mode 100644 index 25d3c56a..00000000 --- a/Admin/Plugins.cs +++ /dev/null @@ -1,117 +0,0 @@ -using System; -using System.IO; -using System.Collections.Generic; -using System.Reflection; -using SharedLibrary; -using SharedLibrary.Interfaces; - -namespace IW4MAdmin -{ - public class PluginImporter - { - public static List potentialCommands = new List(); - public static List potentialPlugins = new List(); - public static IPlugin webFront = null; - //private static AppDomain pluginDomain; - - public static bool Load() - { - //pluginDomain = AppDomain.CreateDomain("Plugins"); - string[] dllFileNames = null; - - if (Directory.Exists(Path.GetDirectoryName(Assembly.GetEntryAssembly().Location) + "\\plugins")) - dllFileNames = Directory.GetFiles(Path.GetDirectoryName(Assembly.GetEntryAssembly().Location) + "\\plugins", "*.dll"); - - else - { - Manager.GetInstance().Logger.WriteWarning("Plugin folder does not exist!"); - return false; - } - - if (dllFileNames == null || dllFileNames.Length == 0) - { - Manager.GetInstance().Logger.WriteDebug("No plugins to load"); - return true; - } - - ICollection assemblies = new List(dllFileNames.Length); - foreach (string dllFile in dllFileNames) - { - byte[] rawDLL = File.ReadAllBytes(dllFile); // because we want to update the plugin without restarting - Assembly assembly = Assembly.Load(rawDLL); - assemblies.Add(assembly); - } - - int LoadedPlugins = 0; - int LoadedCommands = 0; - foreach (Assembly Plugin in assemblies) - { - if (Plugin != null) - { - Type[] types = Plugin.GetTypes(); - foreach(Type assemblyType in types) - { - if (assemblyType.IsClass && assemblyType.BaseType.Name == "Command") - { - Object commandObject = Activator.CreateInstance(assemblyType); - Command newCommand = (Command)commandObject; - potentialCommands.Add(newCommand); - Manager.GetInstance().Logger.WriteDebug("Registered command \"" + newCommand.Name + "\""); - LoadedCommands++; - continue; - } - - try - { - if (assemblyType.GetInterface("IPlugin", false) == null) - continue; - - Object notifyObject = Activator.CreateInstance(assemblyType); - IPlugin newNotify = (IPlugin)notifyObject; - if (potentialPlugins.Find(x => x.Name == newNotify.Name) == null) - { - potentialPlugins.Add(newNotify); - newNotify.OnLoadAsync(); - Manager.GetInstance().Logger.WriteDebug($"Loaded plugin \"{ newNotify.Name }\" [{newNotify.Version}]"); - LoadedPlugins++; - } - } - - catch (Exception E) - { - Manager.GetInstance().Logger.WriteWarning($"Could not load plugin {Plugin.Location} - {E.Message}"); - } - } - } - } - - Manager.GetInstance().Logger.WriteInfo($"Loaded {LoadedPlugins} plugins and registered {LoadedCommands} commands."); - return true; - } - - /* - public static void Unload() - { - - foreach (IPlugin P in potentialPlugins) - { - try - { - P.onUnload(); - } - - catch (Exception E) - { - Manager.GetInstance().mainLog.Write("There was an error unloading \"" + P.Name + "\" plugin", Log.Level.Debug); - Manager.GetInstance().mainLog.Write("Error Message: " + E.Message, Log.Level.Debug); - Manager.GetInstance().mainLog.Write("Error Trace: " + E.StackTrace, Log.Level.Debug); - continue; - } - } - - potentialCommands = new List(); - potentialPlugins = new List(); - AppDomain.Unload(pluginDomain); - }*/ - } -} diff --git a/Admin/Server.cs b/Admin/Server.cs index a9d2ce60..a93c3138 100644 --- a/Admin/Server.cs +++ b/Admin/Server.cs @@ -313,7 +313,7 @@ namespace IW4MAdmin { await ProcessEvent(E); - foreach (SharedLibrary.Interfaces.IPlugin P in PluginImporter.potentialPlugins) + foreach (SharedLibrary.Interfaces.IPlugin P in SharedLibrary.Plugins.PluginImporter.ActivePlugins) { try { @@ -386,7 +386,7 @@ namespace IW4MAdmin if ((DateTime.Now - tickTime).TotalMilliseconds >= 1000) { // We don't want to await here, just in case user plugins are really slow :c - foreach (var Plugin in PluginImporter.potentialPlugins) + foreach (var Plugin in SharedLibrary.Plugins.PluginImporter.ActivePlugins) #if !DEBUG Plugin.OnTickAsync(this); #else @@ -400,7 +400,7 @@ namespace IW4MAdmin { while (PlayerHistory.Count > 144) // 12 times a minute for 12 hours PlayerHistory.Dequeue(); - PlayerHistory.Enqueue(new PlayerHistory(lastCount, ClientNum)); + PlayerHistory.Enqueue(new SharedLibrary.Helpers.PlayerHistory(lastCount, ClientNum)); playerCountStart = DateTime.Now; } @@ -786,16 +786,8 @@ namespace IW4MAdmin override public void InitializeTokens() { - Manager.GetMessageTokens().Add(new MessageToken("TOTALPLAYERS", Manager.GetClientDatabase().TotalPlayers().ToString)); - Manager.GetMessageTokens().Add(new MessageToken("VERSION", Program.Version.ToString)); - } - - override public void InitializeCommands() - { - foreach (Command C in PluginImporter.potentialCommands) - Manager.GetCommands().Add(C); - - Manager.GetCommands().Add(new Plugins("plugins", "view all loaded plugins. syntax: !plugins", "p", Player.Permission.Administrator, 0, false)); + Manager.GetMessageTokens().Add(new SharedLibrary.Helpers.MessageToken("TOTALPLAYERS", Manager.GetClientDatabase().TotalPlayers().ToString)); + Manager.GetMessageTokens().Add(new SharedLibrary.Helpers.MessageToken("VERSION", Program.Version.ToString)); } } } diff --git a/Admin/WebService.cs b/Admin/WebService.cs index 4acddff2..4c0ff6fc 100644 --- a/Admin/WebService.cs +++ b/Admin/WebService.cs @@ -202,7 +202,7 @@ namespace IW4MAdmin serverPort = S.GetPort(), maxPlayers = S.MaxClients, mapName = S.CurrentMap.Alias, - gameType = Utilities.gametypeLocalized(S.Gametype), + gameType = Utilities.GetLocalizedGametype(S.Gametype), currentPlayers = S.GetPlayersAsList().Count, chatHistory = S.ChatHistory, players = new List() @@ -406,7 +406,7 @@ namespace IW4MAdmin adminName = admin.Name, adminLevel = admin.Level.ToString(), penaltyReason = p.Reason, - penaltyTime = SharedLibrary.Utilities.timePassed(p.When), + penaltyTime = SharedLibrary.Utilities.GetTimePassed(p.When), penaltyType = p.BType.ToString(), playerName = penalized.Name, playerID = penalized.DatabaseID @@ -683,7 +683,7 @@ namespace IW4MAdmin } eachPlayer.playerConnections = pp.Connections; - eachPlayer.lastSeen = Utilities.timePassed(pp.LastConnection); + eachPlayer.lastSeen = Utilities.GetTimePassed(pp.LastConnection); pInfo.Add(eachPlayer); } diff --git a/Admin/lib/SharedLibrary.dll b/Admin/lib/SharedLibrary.dll index ad3b75ce..215d2676 100644 Binary files a/Admin/lib/SharedLibrary.dll and b/Admin/lib/SharedLibrary.dll differ diff --git a/IW4M Admin.sln b/IW4MAdmin.sln similarity index 97% rename from IW4M Admin.sln rename to IW4MAdmin.sln index 6ed66584..51c859a6 100644 --- a/IW4M Admin.sln +++ b/IW4MAdmin.sln @@ -1,9 +1,9 @@  Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 15 -VisualStudioVersion = 15.0.26403.7 +VisualStudioVersion = 15.0.26430.12 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "IW4M ADMIN", "Admin\IW4M ADMIN.csproj", "{DD5DCDA2-51DB-4B1A-922F-5705546E6115}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Application", "Admin\Application.csproj", "{DD5DCDA2-51DB-4B1A-922F-5705546E6115}" ProjectSection(ProjectDependencies) = postProject {AF097E6B-48D5-4452-9CCF-0A81A21F341D} = {AF097E6B-48D5-4452-9CCF-0A81A21F341D} {4785AB75-66F3-4391-985D-63A5A049A0FA} = {4785AB75-66F3-4391-985D-63A5A049A0FA} @@ -13,19 +13,19 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "IW4M ADMIN", "Admin\IW4M AD {D51EECEB-438A-47DA-870F-7D7B41BC24D6} = {D51EECEB-438A-47DA-870F-7D7B41BC24D6} EndProjectSection EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Stats Plugin", "Plugins\SimpleStats\Stats Plugin.csproj", "{4785AB75-66F3-4391-985D-63A5A049A0FA}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StatsPlugin", "Plugins\SimpleStats\StatsPlugin.csproj", "{4785AB75-66F3-4391-985D-63A5A049A0FA}" ProjectSection(ProjectDependencies) = postProject {D51EECEB-438A-47DA-870F-7D7B41BC24D6} = {D51EECEB-438A-47DA-870F-7D7B41BC24D6} EndProjectSection EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SharedLibrary", "SharedLibrary\SharedLibrary.csproj", "{D51EECEB-438A-47DA-870F-7D7B41BC24D6}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Welcome Plugin", "Plugins\Welcome\Welcome Plugin.csproj", "{AF097E6B-48D5-4452-9CCF-0A81A21F341D}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WelcomePlugin", "Plugins\Welcome\WelcomePlugin.csproj", "{AF097E6B-48D5-4452-9CCF-0A81A21F341D}" ProjectSection(ProjectDependencies) = postProject {D51EECEB-438A-47DA-870F-7D7B41BC24D6} = {D51EECEB-438A-47DA-870F-7D7B41BC24D6} EndProjectSection EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Votemap Plugin", "Plugins\VoteMap\Votemap Plugin.csproj", "{428D8EB9-ECA3-4A66-AA59-3A944378C33F}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VotemapPlugin", "Plugins\VoteMap\VotemapPlugin.csproj", "{428D8EB9-ECA3-4A66-AA59-3A944378C33F}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MessageboardPlugin", "Plugins\MessageBoard\MessageboardPlugin.csproj", "{E46C85BD-A99C-484E-BCCE-0F1831C5925E}" EndProject diff --git a/Plugins/EventAPI/Plugin.cs b/Plugins/EventAPI/Plugin.cs index aa76d99a..a9c64d2d 100644 --- a/Plugins/EventAPI/Plugin.cs +++ b/Plugins/EventAPI/Plugin.cs @@ -35,7 +35,7 @@ namespace EventAPI { StringBuilder s = new StringBuilder(); foreach (var S in Events.ActiveServers) - s.Append(String.Format("{0} has {1}/{4} players playing {2} on {3}\n", S.Hostname, S.GetPlayersAsList().Count, Utilities.gametypeLocalized(S.Gametype), S.CurrentMap.Name, S.MaxClients)); + s.Append(String.Format("{0} has {1}/{4} players playing {2} on {3}\n", S.Hostname, S.GetPlayersAsList().Count, Utilities.GetLocalizedGametype(S.Gametype), S.CurrentMap.Name, S.MaxClients)); requestedEvent.Event = new RestEvent(RestEvent.EventType.STATUS, RestEvent.EventVersion.IW4MAdmin, s.ToString(), "Status", "", ""); requestedEvent.eventCount = 1; } @@ -95,7 +95,7 @@ namespace EventAPI } } - public async Task OnLoadAsync() + public async Task OnLoadAsync(Server S) { APIEvents = new Queue(); flaggedMessagesText = new List(); @@ -103,7 +103,7 @@ namespace EventAPI WebService.PageList.Add(new EventsJSON()); } - public async Task OnUnloadAsync() + public async Task OnUnloadAsync(Server S) { APIEvents.Clear(); ActiveServers.Clear(); diff --git a/Plugins/FastRestart/Plugin.cs b/Plugins/FastRestart/Plugin.cs index 5fc3ff82..8137a786 100644 --- a/Plugins/FastRestart/Plugin.cs +++ b/Plugins/FastRestart/Plugin.cs @@ -1,12 +1,10 @@ using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; using System.Threading.Tasks; using SharedLibrary; using SharedLibrary.Interfaces; using SharedLibrary.Network; +using SharedLibrary.Helpers; namespace Plugin { @@ -21,9 +19,11 @@ namespace Plugin public override async Task ExecuteAsync(Event E) { - FastRestartPlugin.Config = new FastRestartConfig() { Enabled = true }; - Serialize.Write($"config/fastrestartconfig_{E.Owner}.cfg", FastRestartPlugin.Config); - await E.Origin.Tell("Fast restarting is now enabled for this server"); + var Config = new FastRestartConfig() { Enabled = true }; + if (!new Configuration(E.Owner).Write(Config)) + await E.Origin.Tell("Failed to save the configuration file for fast restart"); + else + await E.Origin.Tell("Fast restarting is now enabled for this server"); } } @@ -33,9 +33,11 @@ namespace Plugin public override async Task ExecuteAsync(Event E) { - FastRestartPlugin.Config = new FastRestartConfig() { Enabled = false }; - Serialize.Write($"config/fastrestartconfig_{E.Owner}.cfg", FastRestartPlugin.Config); - await E.Origin.Tell("Fast restarting is now disabled for this server"); + var Config = new FastRestartConfig() { Enabled = false }; + if (!new Configuration(E.Owner).Write(Config)) + await E.Origin.Tell("Failed to save the configuration file for fast restart"); + else + await E.Origin.Tell("Fast restarting is now disabled for this server"); } } @@ -43,7 +45,6 @@ namespace Plugin { bool MatchEnded; DateTime MatchEndTime; - public static FastRestartConfig Config; public string Name { get { return "Fast Restarter"; } } @@ -58,30 +59,24 @@ namespace Plugin try { await S.GetDvarAsync("scr_intermission_time"); - Config = Serialize.Read($"config/fastrestartconfig_{E.Owner}.cfg"); } catch (SharedLibrary.Exceptions.DvarException) { - await S.ExecuteCommandAsync("set scr_intermission_time 20"); - } - - catch (SharedLibrary.Exceptions.SerializeException) - { - Config = new FastRestartConfig() { Enabled = false }; - Serialize.Write($"config/fastrestartconfig_{E.Owner}.cfg", Config); + await S.SetDvarAsync("scr_intermission_time", 20); } } } - public Task OnLoadAsync() + public async Task OnLoadAsync(Server S) { - return null; + // this initializes the file if it doesn't exist already + new Configuration(S).Read(); } public async Task OnTickAsync(Server S) { - if (!Config.Enabled) + if (!new Configuration(S).Read().Enabled) return; MatchEnded = (await S.GetDvarAsync("scr_gameended")).Value == 1; @@ -97,7 +92,7 @@ namespace Plugin } } - public Task OnUnloadAsync() + public Task OnUnloadAsync(Server S) { return null; } diff --git a/Plugins/MessageBoard/Thread.cs b/Plugins/MessageBoard/Thread.cs index 2959479d..e52172c6 100644 --- a/Plugins/MessageBoard/Thread.cs +++ b/Plugins/MessageBoard/Thread.cs @@ -24,7 +24,7 @@ namespace MessageBoard public Post(int id, int threadid, bool visible, string title, string content, User author, DateTime creationDate, DateTime updatedDate) : base(id, title, visible, content, 0, author, null, creationDate, updatedDate) { - this.lastModificationString = SharedLibrary.Utilities.timePassed(creationDate); + this.lastModificationString = SharedLibrary.Utilities.GetTimePassed(creationDate); this.threadid = threadid; } @@ -118,7 +118,7 @@ namespace MessageBoard this.threadCategory = threadCategory; this.creationDate = creationDate; this.updatedDate = updatedDate; - this.lastModificationString = SharedLibrary.Utilities.timePassed(updatedDate); + this.lastModificationString = SharedLibrary.Utilities.GetTimePassed(updatedDate); this.visible = visible; } diff --git a/Plugins/MessageBoard/User.cs b/Plugins/MessageBoard/User.cs index db4ceeba..51d3f5b1 100644 --- a/Plugins/MessageBoard/User.cs +++ b/Plugins/MessageBoard/User.cs @@ -77,7 +77,7 @@ namespace MessageBoard this.avatarURL = avatarURL; this.posts = posts; - this.lastLoginString = SharedLibrary.Utilities.timePassed(lastLogin); + this.lastLoginString = SharedLibrary.Utilities.GetTimePassed(lastLogin); } public int getID() diff --git a/Plugins/SimpleStats/Plugin.cs b/Plugins/SimpleStats/Plugin.cs index 547656d6..1dc94c0f 100644 --- a/Plugins/SimpleStats/Plugin.cs +++ b/Plugins/SimpleStats/Plugin.cs @@ -133,12 +133,12 @@ namespace StatsPlugin get { return "RaidMax"; } } - public async Task OnLoadAsync() + public async Task OnLoadAsync(Server S) { statLists = new List(); } - public async Task OnUnloadAsync() + public async Task OnUnloadAsync(Server S) { statLists.Clear(); } @@ -155,8 +155,8 @@ namespace StatsPlugin statLists.Add(new StatTracking(S.GetPort())); if (statLists.Count == 1) { - S.Manager.GetMessageTokens().Add(new MessageToken("TOTALKILLS", GetTotalKills)); - S.Manager.GetMessageTokens().Add(new MessageToken("TOTALPLAYTIME", GetTotalPlaytime)); + S.Manager.GetMessageTokens().Add(new SharedLibrary.Helpers.MessageToken("TOTALKILLS", GetTotalKills)); + S.Manager.GetMessageTokens().Add(new SharedLibrary.Helpers.MessageToken("TOTALPLAYTIME", GetTotalPlaytime)); } } diff --git a/Plugins/SimpleStats/Stats Plugin.csproj b/Plugins/SimpleStats/StatsPlugin.csproj similarity index 100% rename from Plugins/SimpleStats/Stats Plugin.csproj rename to Plugins/SimpleStats/StatsPlugin.csproj diff --git a/Plugins/VoteMap/Plugin.cs b/Plugins/VoteMap/Plugin.cs index e3c3ec20..f8a1afe2 100644 --- a/Plugins/VoteMap/Plugin.cs +++ b/Plugins/VoteMap/Plugin.cs @@ -205,12 +205,12 @@ namespace Votemap_Plugin } } - public async Task OnLoadAsync() + public async Task OnLoadAsync(Server S) { serverVotingList = new List(); } - public async Task OnUnloadAsync() + public async Task OnUnloadAsync(Server S) { serverVotingList.Clear(); } diff --git a/Plugins/VoteMap/Votemap Plugin.csproj b/Plugins/VoteMap/VotemapPlugin.csproj similarity index 100% rename from Plugins/VoteMap/Votemap Plugin.csproj rename to Plugins/VoteMap/VotemapPlugin.csproj diff --git a/Plugins/Welcome/Plugin.cs b/Plugins/Welcome/Plugin.cs index 64ec163d..099766df 100644 --- a/Plugins/Welcome/Plugin.cs +++ b/Plugins/Welcome/Plugin.cs @@ -13,6 +13,53 @@ namespace Welcome_Plugin Dictionary PlayerPings; int PingAverageCount; + String TimesConnected(Player P) + { + int connection = P.Connections; + String Prefix = String.Empty; + if (connection % 10 > 3 || connection % 10 == 0 || (connection % 100 > 9 && connection % 100 < 19)) + Prefix = "th"; + else + { + switch (connection % 10) + { + case 1: + Prefix = "st"; + break; + case 2: + Prefix = "nd"; + break; + case 3: + Prefix = "rd"; + break; + } + } + + switch (connection) + { + case 0: + case 1: + return "first"; + case 2: + return "second"; + case 3: + return "third"; + case 4: + return "fourth"; + case 5: + return "fifth"; + case 100: + return "One-Hundreth (amazing!)"; + case 500: + return "you're really ^5dedicated ^7to this server! This is your ^5500th^7"; + case 1000: + return "you deserve a medal. it's your ^11000th^7"; + + default: + return connection.ToString() + Prefix; + } + } + public string Author { get @@ -37,13 +84,13 @@ namespace Welcome_Plugin } } - public async Task OnLoadAsync() + public async Task OnLoadAsync(Server S) { PlayerPings = new Dictionary(); PingAverageCount = 1; } - public async Task OnUnloadAsync() + public async Task OnUnloadAsync(Server S) { PlayerPings.Clear(); PlayerPings = null; @@ -75,9 +122,9 @@ namespace Welcome_Plugin Player newPlayer = E.Origin; if (newPlayer.Level >= Player.Permission.Trusted && !E.Origin.Masked) - await E.Owner.Broadcast(Utilities.levelToColor(newPlayer.Level) + " ^5" + newPlayer.Name + " ^7has joined the server."); + await E.Owner.Broadcast(Utilities.ConvertLevelToColor(newPlayer.Level) + " ^5" + newPlayer.Name + " ^7has joined the server."); - await newPlayer.Tell($"Welcome ^5{newPlayer.Name}^7, this your ^5{newPlayer.TimesConnected()} ^7time connecting!"); + await newPlayer.Tell($"Welcome ^5{newPlayer.Name}^7, this your ^5{TimesConnected(newPlayer)} ^7time connecting!"); if (newPlayer.Level == Player.Permission.Flagged) await E.Owner.ToAdmins($"^1NOTICE: ^7Flagged player ^5{newPlayer.Name}^7 has joined!"); diff --git a/Plugins/Welcome/Welcome Plugin.csproj b/Plugins/Welcome/WelcomePlugin.csproj similarity index 100% rename from Plugins/Welcome/Welcome Plugin.csproj rename to Plugins/Welcome/WelcomePlugin.csproj diff --git a/SharedLibrary/Commands/NativeCommands.cs b/SharedLibrary/Commands/NativeCommands.cs index 2c199395..88a3785c 100644 --- a/SharedLibrary/Commands/NativeCommands.cs +++ b/SharedLibrary/Commands/NativeCommands.cs @@ -18,8 +18,7 @@ namespace SharedLibrary.Commands } class COwner : Command - { - + { public COwner(String N, String D, String U, Player.Permission P, int args, bool nT) : base(N, D, U, P, args, nT) { } public override async Task ExecuteAsync(Event E) @@ -145,7 +144,7 @@ namespace SharedLibrary.Commands public override async Task ExecuteAsync(Event E) { - String You = String.Format("{0} [^3#{1}^7] {2} [^3@{3}^7] [{4}^7] IP: {5}", E.Origin.Name, E.Origin.ClientID, E.Origin.NetworkID, E.Origin.DatabaseID, SharedLibrary.Utilities.levelToColor(E.Origin.Level), E.Origin.IP); + String You = String.Format("{0} [^3#{1}^7] {2} [^3@{3}^7] [{4}^7] IP: {5}", E.Origin.Name, E.Origin.ClientID, E.Origin.NetworkID, E.Origin.DatabaseID, SharedLibrary.Utilities.ConvertLevelToColor(E.Origin.Level), E.Origin.IP); await E.Origin.Tell(You); } } @@ -166,9 +165,9 @@ namespace SharedLibrary.Commands continue; if (P.Masked) - playerList.AppendFormat("[^3{0}^7]{3}[^3{1}^7] {2}", Utilities.levelToColor(Player.Permission.User), P.ClientID, P.Name, SharedLibrary.Utilities.getSpaces(Player.Permission.SeniorAdmin.ToString().Length - Player.Permission.User.ToString().Length)); + playerList.AppendFormat("[^3{0}^7]{3}[^3{1}^7] {2}", Utilities.ConvertLevelToColor(Player.Permission.User), P.ClientID, P.Name, SharedLibrary.Utilities.GetSpaces(Player.Permission.SeniorAdmin.ToString().Length - Player.Permission.User.ToString().Length)); else - playerList.AppendFormat("[^3{0}^7]{3}[^3{1}^7] {2}", Utilities.levelToColor(P.Level), P.ClientID, P.Name, SharedLibrary.Utilities.getSpaces(Player.Permission.SeniorAdmin.ToString().Length - P.Level.ToString().Length)); + playerList.AppendFormat("[^3{0}^7]{3}[^3{1}^7] {2}", Utilities.ConvertLevelToColor(P.Level), P.ClientID, P.Name, SharedLibrary.Utilities.GetSpaces(Player.Permission.SeniorAdmin.ToString().Length - P.Level.ToString().Length)); if (count == 2 || E.Owner.GetPlayersAsList().Count == 1) { @@ -278,7 +277,7 @@ namespace SharedLibrary.Commands return; } - Player.Permission newPerm = Utilities.matchPermission(Utilities.RemoveWords(E.Data, 1)); + Player.Permission newPerm = Utilities.MatchPermission(Utilities.RemoveWords(E.Data, 1)); if (newPerm == Player.Permission.Owner && E.Origin.Level != Player.Permission.Console) newPerm = Player.Permission.Banned; @@ -333,9 +332,9 @@ namespace SharedLibrary.Commands if (P != null && P.Level > Player.Permission.Flagged && !P.Masked) { if (E.Message[0] == '@') - await E.Owner.Broadcast(String.Format("[^3{0}^7] {1}", Utilities.levelToColor(P.Level), P.Name)); + await E.Owner.Broadcast(String.Format("[^3{0}^7] {1}", Utilities.ConvertLevelToColor(P.Level), P.Name)); else - await E.Origin.Tell(String.Format("[^3{0}^7] {1}", Utilities.levelToColor(P.Level), P.Name)); + await E.Origin.Tell(String.Format("[^3{0}^7] {1}", Utilities.ConvertLevelToColor(P.Level), P.Name)); } } } @@ -381,7 +380,7 @@ namespace SharedLibrary.Commands foreach (Player P in db_players) { - String mesg = String.Format("[^3{0}^7] [^3@{1}^7] - [{2}^7] - {3} | last seen {4} ago", P.Name, P.DatabaseID, SharedLibrary.Utilities.levelToColor(P.Level), P.IP, P.GetLastConnection()); + String mesg = String.Format("[^3{0}^7] [^3@{1}^7] - [{2}^7] - {3} | last seen {4} ago", P.Name, P.DatabaseID, SharedLibrary.Utilities.ConvertLevelToColor(P.Level), P.IP, P.GetLastConnection()); await E.Origin.Tell(mesg); } } @@ -679,5 +678,19 @@ namespace SharedLibrary.Commands await E.Origin.Tell("Successfully sent RCON command!"); } } + + class CPlugins : Command + { + public CPlugins(String N, String D, String U, Player.Permission P, int args, bool nT) : base(N, D, U, P, args, nT) { } + + public override async Task ExecuteAsync(Event E) + { + await E.Origin.Tell("^5Loaded Plugins:"); + foreach (var P in Plugins.PluginImporter.ActivePlugins) + { + await E.Origin.Tell(String.Format("^3{0} ^7[v^3{1}^7] by ^5{2}^7", P.Name, P.Version, P.Author)); + } + } + } } \ No newline at end of file diff --git a/SharedLibrary/Database.cs b/SharedLibrary/Database.cs index 47d013be..7d29d065 100644 --- a/SharedLibrary/Database.cs +++ b/SharedLibrary/Database.cs @@ -509,7 +509,7 @@ namespace SharedLibrary { Dictionary newPlayer = new Dictionary { - { "Name", Utilities.removeNastyChars(P.Name) }, + { "Name", Utilities.StripIllegalCharacters(P.Name) }, { "npID", P.NetworkID }, { "Level", (int)P.Level }, { "LastOffense", "" }, @@ -546,7 +546,7 @@ namespace SharedLibrary { Dictionary newBan = new Dictionary { - { "Reason", Utilities.removeNastyChars(B.Reason) }, + { "Reason", Utilities.StripIllegalCharacters(B.Reason) }, { "npID", B.OffenderID }, { "bannedByID", B.PenaltyOriginID }, { "IP", B.IP }, @@ -656,7 +656,7 @@ namespace SharedLibrary Dictionary newPlayer = new Dictionary { { "Number", Alias.Number }, - { "NAMES", Utilities.removeNastyChars(String.Join(";", Alias.Names)) }, + { "NAMES", Utilities.StripIllegalCharacters(String.Join(";", Alias.Names)) }, { "IPS", String.Join(";", Alias.IPS) } }; Insert("ALIASES", newPlayer); diff --git a/SharedLibrary/Event.cs b/SharedLibrary/Event.cs index d182d72e..245c9503 100644 --- a/SharedLibrary/Event.cs +++ b/SharedLibrary/Event.cs @@ -119,7 +119,7 @@ namespace SharedLibrary { Regex rgx = new Regex("[^a-zA-Z0-9 -! -_]"); string message = rgx.Replace(line[4], ""); - return new Event(GType.Say, Utilities.removeNastyChars(message).StripColors(), SV.ParseClientFromString(line, 2), null, SV) { Message = Utilities.removeNastyChars(message).StripColors() }; + return new Event(GType.Say, Utilities.StripIllegalCharacters(message).StripColors(), SV.ParseClientFromString(line, 2), null, SV) { Message = Utilities.StripIllegalCharacters(message).StripColors() }; } if (eventType == ":") diff --git a/SharedLibrary/AsyncStatus.cs b/SharedLibrary/Helpers/AsyncStatus.cs similarity index 97% rename from SharedLibrary/AsyncStatus.cs rename to SharedLibrary/Helpers/AsyncStatus.cs index 543a2077..384c303c 100644 --- a/SharedLibrary/AsyncStatus.cs +++ b/SharedLibrary/Helpers/AsyncStatus.cs @@ -5,7 +5,7 @@ using System.Text; using System.Threading; using System.Threading.Tasks; -namespace SharedLibrary +namespace SharedLibrary.Helpers { public sealed class AsyncStatus { diff --git a/SharedLibrary/Helpers/Configuration.cs b/SharedLibrary/Helpers/Configuration.cs new file mode 100644 index 00000000..d8bdec09 --- /dev/null +++ b/SharedLibrary/Helpers/Configuration.cs @@ -0,0 +1,50 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace SharedLibrary.Helpers +{ + public class Configuration : Interfaces.Serialize + { + string FilePostfix; + public Configuration(Server S) + { + FilePostfix = $"_{S.GetIP()}_{S.GetPort()}.cfg"; + } + + public T Read() + { + try + { + return Read(); + } + + catch (Exceptions.SerializeException) + { + return default(T); + } + } + + public bool Write(T Data) + { + try + { + Write(Filename(), Data); + return true; + } + + catch(Exceptions.SerializeException) + { + return false; + } + } + + public override string Filename() + { + return $"config/{typeof(T).ToString()}_{FilePostfix}"; + } + + } +} diff --git a/SharedLibrary/MessageToken.cs b/SharedLibrary/Helpers/MessageToken.cs similarity index 92% rename from SharedLibrary/MessageToken.cs rename to SharedLibrary/Helpers/MessageToken.cs index 2cc88d34..285ba9c7 100644 --- a/SharedLibrary/MessageToken.cs +++ b/SharedLibrary/Helpers/MessageToken.cs @@ -1,6 +1,6 @@ using System; -namespace SharedLibrary +namespace SharedLibrary.Helpers { public class MessageToken { diff --git a/SharedLibrary/Miscellaneous.cs b/SharedLibrary/Helpers/PlayerHistory.cs similarity index 89% rename from SharedLibrary/Miscellaneous.cs rename to SharedLibrary/Helpers/PlayerHistory.cs index 10ac37aa..427f4a11 100644 --- a/SharedLibrary/Miscellaneous.cs +++ b/SharedLibrary/Helpers/PlayerHistory.cs @@ -1,6 +1,6 @@ using System; -namespace SharedLibrary +namespace SharedLibrary.Helpers { public class PlayerHistory { diff --git a/SharedLibrary/Interfaces/IManager.cs b/SharedLibrary/Interfaces/IManager.cs index b5d80ea1..27f8ea4d 100644 --- a/SharedLibrary/Interfaces/IManager.cs +++ b/SharedLibrary/Interfaces/IManager.cs @@ -13,7 +13,7 @@ namespace SharedLibrary.Interfaces IPenaltyList GetClientPenalties(); ClientsDB GetClientDatabase(); AliasesDB GetAliasesDatabase(); - IList GetMessageTokens(); + IList GetMessageTokens(); IList GetActiveClients(); } } diff --git a/SharedLibrary/Interfaces/IPlugin.cs b/SharedLibrary/Interfaces/IPlugin.cs index f6e5d752..32e37d50 100644 --- a/SharedLibrary/Interfaces/IPlugin.cs +++ b/SharedLibrary/Interfaces/IPlugin.cs @@ -5,8 +5,8 @@ namespace SharedLibrary.Interfaces { public interface IPlugin { - Task OnLoadAsync(); - Task OnUnloadAsync(); + Task OnLoadAsync(Server S); + Task OnUnloadAsync(Server S); Task OnEventAsync(Event E, Server S); Task OnTickAsync(Server S); diff --git a/SharedLibrary/Penalty.cs b/SharedLibrary/Penalty.cs index 45d116cd..dceccf32 100644 --- a/SharedLibrary/Penalty.cs +++ b/SharedLibrary/Penalty.cs @@ -1,4 +1,5 @@ using System; +using SharedLibrary; namespace SharedLibrary { @@ -6,7 +7,7 @@ namespace SharedLibrary { public Penalty(Type BType, String Reas, String TargID, String From, DateTime time, String ip) { - Reason = Reas.Replace("!",""); + Reason = Reas.CleanChars().StripColors(); OffenderID = TargID; PenaltyOriginID = From; When = time; @@ -36,4 +37,18 @@ namespace SharedLibrary public String IP { get; private set; } public Type BType { get; private set; } } + + public class Report + { + public Report(Player T, Player O, String R) + { + Target = T; + Origin = O; + Reason = R; + } + + public Player Target { get; private set; } + public Player Origin { get; private set; } + public String Reason { get; private set; } + } } diff --git a/SharedLibrary/Player.cs b/SharedLibrary/Player.cs index df986b9d..c9f51837 100644 --- a/SharedLibrary/Player.cs +++ b/SharedLibrary/Player.cs @@ -124,7 +124,7 @@ namespace SharedLibrary public String GetLastConnection() { - return Utilities.timePassed(LastConnection); + return Utilities.GetTimePassed(LastConnection); } public void UpdateName(String n) diff --git a/SharedLibrary/PluginImporter.cs b/SharedLibrary/PluginImporter.cs new file mode 100644 index 00000000..8696d5ce --- /dev/null +++ b/SharedLibrary/PluginImporter.cs @@ -0,0 +1,78 @@ +using System; +using System.IO; +using System.Collections.Generic; +using System.Reflection; +using SharedLibrary.Interfaces; + +namespace SharedLibrary.Plugins +{ + public class PluginImporter + { + public static List ActiveCommands = new List(); + public static List ActivePlugins = new List(); + + public static bool Load(IManager Manager) + { + string[] dllFileNames = Directory.GetFiles(Path.GetDirectoryName(Assembly.GetEntryAssembly().Location) + "\\plugins", "*.dll"); + + if (dllFileNames.Length == 0) + { + Manager.GetLogger().WriteDebug("No plugins found to load"); + return true; + } + + ICollection assemblies = new List(dllFileNames.Length); + foreach (string dllFile in dllFileNames) + { + byte[] rawDLL = File.ReadAllBytes(dllFile); + Assembly assembly = Assembly.Load(rawDLL); + assemblies.Add(assembly); + } + + int LoadedPlugins = 0; + int LoadedCommands = 0; + foreach (Assembly Plugin in assemblies) + { + if (Plugin != null) + { + Type[] types = Plugin.GetTypes(); + foreach (Type assemblyType in types) + { + if (assemblyType.IsClass && assemblyType.BaseType.Name == "Command") + { + Object commandObject = Activator.CreateInstance(assemblyType); + Command newCommand = (Command)commandObject; + ActiveCommands.Add(newCommand); + Manager.GetLogger().WriteDebug("Registered command \"" + newCommand.Name + "\""); + LoadedCommands++; + continue; + } + + try + { + if (assemblyType.GetInterface("IPlugin", false) == null) + continue; + + Object notifyObject = Activator.CreateInstance(assemblyType); + IPlugin newNotify = (IPlugin)notifyObject; + if (ActivePlugins.Find(x => x.Name == newNotify.Name) == null) + { + ActivePlugins.Add(newNotify); + Manager.GetLogger().WriteDebug($"Loaded plugin \"{ newNotify.Name }\" [{newNotify.Version}]"); + LoadedPlugins++; + } + } + + catch (Exception E) + { + Manager.GetLogger().WriteWarning($"Could not load plugin {Plugin.Location} - {E.Message}"); + } + } + } + } + + Manager.GetLogger().WriteInfo($"Loaded {LoadedPlugins} plugins and registered {LoadedCommands} commands."); + return true; + } + } +} diff --git a/SharedLibrary/RCON.cs b/SharedLibrary/RCON.cs index 07eef67b..4df31b5d 100644 --- a/SharedLibrary/RCON.cs +++ b/SharedLibrary/RCON.cs @@ -114,7 +114,7 @@ namespace SharedLibrary.Network public static async Task SetDvarAsync(this Server server, string dvarName, object dvarValue) { - await Task.FromResult(SendQuery(QueryType.DVAR, server, $"{dvarName} {dvarValue}")); + await Task.FromResult(SendQuery(QueryType.DVAR, server, $"set {dvarName} {dvarValue}")); } public static async Task ExecuteCommandAsync(this Server server, string commandName) @@ -139,7 +139,6 @@ namespace SharedLibrary.Network fixedRequest[i / 2] = initialRequestBytes[i]; return fixedRequest; - } } } diff --git a/SharedLibrary/Report.cs b/SharedLibrary/Report.cs deleted file mode 100644 index ff50854f..00000000 --- a/SharedLibrary/Report.cs +++ /dev/null @@ -1,18 +0,0 @@ -using System; - -namespace SharedLibrary -{ - public class Report - { - public Report(Player T, Player O, String R) - { - Target = T; - Origin = O; - Reason = R; - } - - public Player Target { get; private set; } - public Player Origin { get; private set; } - public String Reason { get; private set; } - } -} diff --git a/SharedLibrary/Server.cs b/SharedLibrary/Server.cs index ae77ffd0..2081baff 100644 --- a/SharedLibrary/Server.cs +++ b/SharedLibrary/Server.cs @@ -26,7 +26,7 @@ namespace SharedLibrary Players = new List(new Player[18]); events = new Queue(); Reports = new List(); - PlayerHistory = new Queue(); + PlayerHistory = new Queue(); ChatHistory = new List(); lastWebChat = DateTime.Now; nextMessage = 0; @@ -71,6 +71,7 @@ namespace SharedLibrary commands.Add(new CListAlias("alias", "get past aliases and ips of a player. syntax: !alias ", "known", Player.Permission.Moderator, 1, true)); commands.Add(new CExecuteRCON("rcon", "send rcon command to server. syntax: !rcon ", "rcon", Player.Permission.Owner, 1, false)); commands.Add(new CFindAllPlayers("findall", "find a player by their aliase(s). syntax: !findall ", "fa", Player.Permission.Moderator, 1, false)); + commands.Add(new CPlugins("plugins", "view all loaded plugins. syntax: !plugins", "p", Player.Permission.Administrator, 0, false)); } //Returns current server IP set by `net_ip` -- *STRING* @@ -375,7 +376,11 @@ namespace SharedLibrary /// /// Load up the built in commands /// - abstract public void InitializeCommands(); + public void InitializeCommands() + { + foreach (Command C in Plugins.PluginImporter.ActiveCommands) + Manager.GetCommands().Add(C); + } //Objects public Interfaces.IManager Manager { get; protected set; } @@ -389,7 +394,7 @@ namespace SharedLibrary public int totalKills = 0; public List Reports; public List ChatHistory; - public Queue PlayerHistory { get; private set; } + public Queue PlayerHistory { get; private set; } protected int ConnectionErrors; protected DateTime LastPoll; diff --git a/SharedLibrary/SharedLibrary.csproj b/SharedLibrary/SharedLibrary.csproj index e677ad20..9715bf8f 100644 --- a/SharedLibrary/SharedLibrary.csproj +++ b/SharedLibrary/SharedLibrary.csproj @@ -66,18 +66,19 @@ - + + - + @@ -85,12 +86,12 @@ - + + - diff --git a/SharedLibrary/Utilities.cs b/SharedLibrary/Utilities.cs index 5cefe7c3..ebd518f7 100644 --- a/SharedLibrary/Utilities.cs +++ b/SharedLibrary/Utilities.cs @@ -10,7 +10,7 @@ namespace SharedLibrary public static class Utilities { //Get string with specified number of spaces -- really only for visual output - public static String getSpaces(int Num) + public static String GetSpaces(int Num) { String SpaceString = String.Empty; while (Num > 0) @@ -22,12 +22,6 @@ namespace SharedLibrary return SpaceString; } - //Sleep for x amount of seconds - public static void Wait(double time) - { - Thread.Sleep((int)Math.Ceiling(time * 1000)); - } - //Remove words from a space delimited string public static String RemoveWords(this string str, int num) { @@ -74,14 +68,11 @@ namespace SharedLibrary return StatusPlayers; } - public static Player.Permission matchPermission(String str) + public static Player.Permission MatchPermission(String str) { String lookingFor = str.ToLower(); -#if REPZ_BUILD - for (Player.Permission Perm = Player.Permission.User; Perm <= Player.Permission.Owner; Perm++) -#else + for (Player.Permission Perm = Player.Permission.User; Perm < Player.Permission.Owner; Perm++) -#endif { if (lookingFor.Contains(Perm.ToString().ToLower())) return Perm; @@ -90,12 +81,10 @@ namespace SharedLibrary return Player.Permission.Banned; } - public static String removeNastyChars(String str) + public static String StripIllegalCharacters(String str) { if (str != null) - { return str.Replace("`", "").Replace("\\", "").Replace("\"", "").Replace(""", "").Replace("&", "&").Replace("\"", "''").Replace("'", "").Replace("?", ""); - } else return String.Empty; @@ -130,7 +119,7 @@ namespace SharedLibrary /// /// Specified player level /// - public static String levelToColor(Player.Permission level) + public static String ConvertLevelToColor(Player.Permission level) { switch (level) { @@ -149,7 +138,7 @@ namespace SharedLibrary } } - public static String ProcessMessageToken(IList tokens, String str) + public static String ProcessMessageToken(IList tokens, String str) { MatchCollection RegexMatches = Regex.Matches(str, @"\{\{[A-Z]+\}\}", RegexOptions.IgnoreCase); foreach (Match M in RegexMatches) @@ -176,7 +165,7 @@ namespace SharedLibrary /// /// Shorthand gametype reported from server /// - public static String gametypeLocalized(String input) + public static String GetLocalizedGametype(String input) { switch (input) { @@ -232,7 +221,7 @@ namespace SharedLibrary return datetime.ToString("yyyy-MM-dd H:mm:ss"); } - public static String timePassed(DateTime start) + public static String GetTimePassed(DateTime start) { TimeSpan Elapsed = DateTime.Now - start; @@ -259,52 +248,5 @@ namespace SharedLibrary else return "a very long time"; } - - public static String TimesConnected(this Player P) - { - int connection = P.Connections; - String Prefix = String.Empty; - if (connection % 10 > 3 || connection % 10 == 0 || (connection % 100 > 9 && connection % 100 < 19)) - Prefix = "th"; - else - { - switch (connection % 10) - { - case 1: - Prefix = "st"; - break; - case 2: - Prefix = "nd"; - break; - case 3: - Prefix = "rd"; - break; - } - } - - switch (connection) - { - case 0: - case 1: - return "first"; - case 2: - return "second"; - case 3: - return "third"; - case 4: - return "fourth"; - case 5: - return "fifth"; - case 100: - return "One-Hundreth (amazing!)"; - case 500: - return "you're really ^5dedicated ^7to this server! This is your ^5500th^7"; - case 1000: - return "you deserve a medal. it's your ^11000th^7"; - - default: - return connection.ToString() + Prefix; - } - } } }