diff --git a/TShock.sln b/TShock.sln index db301cae..ad3df12f 100644 --- a/TShock.sln +++ b/TShock.sln @@ -1,71 +1,71 @@ - -Microsoft Visual Studio Solution File, Format Version 11.00 -# Visual Studio 2010 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TShockAPI", "TShockAPI\TShockAPI.csproj", "{49606449-072B-4CF5-8088-AA49DA586694}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TShockDBEditor", "DBEditor\TShockDBEditor.csproj", "{F1AE395C-6B4D-40E0-8BF8-0D8A126488D3}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UnitTests", "UnitTests\UnitTests.csproj", "{F3742F51-D7BF-4754-A68A-CD944D2A21FF}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{755F5B05-0924-47E9-9563-26EB20FE3F67}" - ProjectSection(SolutionItems) = preProject - Local.testsettings = Local.testsettings - Terraria.vsmdi = Terraria.vsmdi - EndProjectSection -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TShockRestTestPlugin", "TShockRestTestPlugin\TShockRestTestPlugin.csproj", "{F2FEDAFB-58DE-4611-9168-A86112C346C7}" -EndProject -Global - GlobalSection(TestCaseManagementSettings) = postSolution - CategoryFile = Terraria.vsmdi - EndGlobalSection - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Debug|Mixed Platforms = Debug|Mixed Platforms - Debug|x86 = Debug|x86 - Release|Any CPU = Release|Any CPU - Release|Mixed Platforms = Release|Mixed Platforms - Release|x86 = Release|x86 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {49606449-072B-4CF5-8088-AA49DA586694}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {49606449-072B-4CF5-8088-AA49DA586694}.Debug|Any CPU.Build.0 = Debug|Any CPU - {49606449-072B-4CF5-8088-AA49DA586694}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU - {49606449-072B-4CF5-8088-AA49DA586694}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU - {49606449-072B-4CF5-8088-AA49DA586694}.Debug|x86.ActiveCfg = Debug|Any CPU - {49606449-072B-4CF5-8088-AA49DA586694}.Release|Any CPU.ActiveCfg = Release|Any CPU - {49606449-072B-4CF5-8088-AA49DA586694}.Release|Any CPU.Build.0 = Release|Any CPU - {49606449-072B-4CF5-8088-AA49DA586694}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU - {49606449-072B-4CF5-8088-AA49DA586694}.Release|Mixed Platforms.Build.0 = Release|Any CPU - {49606449-072B-4CF5-8088-AA49DA586694}.Release|x86.ActiveCfg = Release|Any CPU - {F1AE395C-6B4D-40E0-8BF8-0D8A126488D3}.Debug|Any CPU.ActiveCfg = Debug|x86 - {F1AE395C-6B4D-40E0-8BF8-0D8A126488D3}.Debug|Mixed Platforms.ActiveCfg = Debug|x86 - {F1AE395C-6B4D-40E0-8BF8-0D8A126488D3}.Debug|Mixed Platforms.Build.0 = Debug|x86 - {F1AE395C-6B4D-40E0-8BF8-0D8A126488D3}.Debug|x86.ActiveCfg = Debug|x86 - {F1AE395C-6B4D-40E0-8BF8-0D8A126488D3}.Debug|x86.Build.0 = Debug|x86 - {F1AE395C-6B4D-40E0-8BF8-0D8A126488D3}.Release|Any CPU.ActiveCfg = Release|x86 - {F1AE395C-6B4D-40E0-8BF8-0D8A126488D3}.Release|Mixed Platforms.ActiveCfg = Release|x86 - {F1AE395C-6B4D-40E0-8BF8-0D8A126488D3}.Release|Mixed Platforms.Build.0 = Release|x86 - {F1AE395C-6B4D-40E0-8BF8-0D8A126488D3}.Release|x86.ActiveCfg = Release|x86 - {F1AE395C-6B4D-40E0-8BF8-0D8A126488D3}.Release|x86.Build.0 = Release|x86 - {F3742F51-D7BF-4754-A68A-CD944D2A21FF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {F3742F51-D7BF-4754-A68A-CD944D2A21FF}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU - {F3742F51-D7BF-4754-A68A-CD944D2A21FF}.Debug|x86.ActiveCfg = Debug|Any CPU - {F3742F51-D7BF-4754-A68A-CD944D2A21FF}.Release|Any CPU.ActiveCfg = Release|Any CPU - {F3742F51-D7BF-4754-A68A-CD944D2A21FF}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU - {F3742F51-D7BF-4754-A68A-CD944D2A21FF}.Release|x86.ActiveCfg = Release|Any CPU - {F2FEDAFB-58DE-4611-9168-A86112C346C7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {F2FEDAFB-58DE-4611-9168-A86112C346C7}.Debug|Any CPU.Build.0 = Debug|Any CPU - {F2FEDAFB-58DE-4611-9168-A86112C346C7}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU - {F2FEDAFB-58DE-4611-9168-A86112C346C7}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU - {F2FEDAFB-58DE-4611-9168-A86112C346C7}.Debug|x86.ActiveCfg = Debug|Any CPU - {F2FEDAFB-58DE-4611-9168-A86112C346C7}.Release|Any CPU.ActiveCfg = Release|Any CPU - {F2FEDAFB-58DE-4611-9168-A86112C346C7}.Release|Any CPU.Build.0 = Release|Any CPU - {F2FEDAFB-58DE-4611-9168-A86112C346C7}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU - {F2FEDAFB-58DE-4611-9168-A86112C346C7}.Release|Mixed Platforms.Build.0 = Release|Any CPU - {F2FEDAFB-58DE-4611-9168-A86112C346C7}.Release|x86.ActiveCfg = Release|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 11 +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{755F5B05-0924-47E9-9563-26EB20FE3F67}" + ProjectSection(SolutionItems) = preProject + Local.testsettings = Local.testsettings + Terraria.vsmdi = Terraria.vsmdi + EndProjectSection +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TShockAPI", "TShockAPI\TShockAPI.csproj", "{49606449-072B-4CF5-8088-AA49DA586694}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TShockDBEditor", "DBEditor\TShockDBEditor.csproj", "{F1AE395C-6B4D-40E0-8BF8-0D8A126488D3}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UnitTests", "UnitTests\UnitTests.csproj", "{F3742F51-D7BF-4754-A68A-CD944D2A21FF}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TShockRestTestPlugin", "TShockRestTestPlugin\TShockRestTestPlugin.csproj", "{F2FEDAFB-58DE-4611-9168-A86112C346C7}" +EndProject +Global + GlobalSection(TestCaseManagementSettings) = postSolution + CategoryFile = Terraria.vsmdi + EndGlobalSection + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Debug|Mixed Platforms = Debug|Mixed Platforms + Debug|x86 = Debug|x86 + Release|Any CPU = Release|Any CPU + Release|Mixed Platforms = Release|Mixed Platforms + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {49606449-072B-4CF5-8088-AA49DA586694}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {49606449-072B-4CF5-8088-AA49DA586694}.Debug|Any CPU.Build.0 = Debug|Any CPU + {49606449-072B-4CF5-8088-AA49DA586694}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {49606449-072B-4CF5-8088-AA49DA586694}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {49606449-072B-4CF5-8088-AA49DA586694}.Debug|x86.ActiveCfg = Debug|Any CPU + {49606449-072B-4CF5-8088-AA49DA586694}.Release|Any CPU.ActiveCfg = Release|Any CPU + {49606449-072B-4CF5-8088-AA49DA586694}.Release|Any CPU.Build.0 = Release|Any CPU + {49606449-072B-4CF5-8088-AA49DA586694}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {49606449-072B-4CF5-8088-AA49DA586694}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {49606449-072B-4CF5-8088-AA49DA586694}.Release|x86.ActiveCfg = Release|Any CPU + {F1AE395C-6B4D-40E0-8BF8-0D8A126488D3}.Debug|Any CPU.ActiveCfg = Debug|x86 + {F1AE395C-6B4D-40E0-8BF8-0D8A126488D3}.Debug|Mixed Platforms.ActiveCfg = Debug|x86 + {F1AE395C-6B4D-40E0-8BF8-0D8A126488D3}.Debug|Mixed Platforms.Build.0 = Debug|x86 + {F1AE395C-6B4D-40E0-8BF8-0D8A126488D3}.Debug|x86.ActiveCfg = Debug|x86 + {F1AE395C-6B4D-40E0-8BF8-0D8A126488D3}.Debug|x86.Build.0 = Debug|x86 + {F1AE395C-6B4D-40E0-8BF8-0D8A126488D3}.Release|Any CPU.ActiveCfg = Release|x86 + {F1AE395C-6B4D-40E0-8BF8-0D8A126488D3}.Release|Mixed Platforms.ActiveCfg = Release|x86 + {F1AE395C-6B4D-40E0-8BF8-0D8A126488D3}.Release|Mixed Platforms.Build.0 = Release|x86 + {F1AE395C-6B4D-40E0-8BF8-0D8A126488D3}.Release|x86.ActiveCfg = Release|x86 + {F1AE395C-6B4D-40E0-8BF8-0D8A126488D3}.Release|x86.Build.0 = Release|x86 + {F2FEDAFB-58DE-4611-9168-A86112C346C7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F2FEDAFB-58DE-4611-9168-A86112C346C7}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F2FEDAFB-58DE-4611-9168-A86112C346C7}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {F2FEDAFB-58DE-4611-9168-A86112C346C7}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {F2FEDAFB-58DE-4611-9168-A86112C346C7}.Debug|x86.ActiveCfg = Debug|Any CPU + {F2FEDAFB-58DE-4611-9168-A86112C346C7}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F2FEDAFB-58DE-4611-9168-A86112C346C7}.Release|Any CPU.Build.0 = Release|Any CPU + {F2FEDAFB-58DE-4611-9168-A86112C346C7}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {F2FEDAFB-58DE-4611-9168-A86112C346C7}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {F2FEDAFB-58DE-4611-9168-A86112C346C7}.Release|x86.ActiveCfg = Release|Any CPU + {F3742F51-D7BF-4754-A68A-CD944D2A21FF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F3742F51-D7BF-4754-A68A-CD944D2A21FF}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {F3742F51-D7BF-4754-A68A-CD944D2A21FF}.Debug|x86.ActiveCfg = Debug|Any CPU + {F3742F51-D7BF-4754-A68A-CD944D2A21FF}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F3742F51-D7BF-4754-A68A-CD944D2A21FF}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {F3742F51-D7BF-4754-A68A-CD944D2A21FF}.Release|x86.ActiveCfg = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/TShockAPI/Utils.cs b/TShockAPI/Utils.cs index 697ae2f9..e9ba843d 100644 --- a/TShockAPI/Utils.cs +++ b/TShockAPI/Utils.cs @@ -1,822 +1,822 @@ -/* -TShock, a server mod for Terraria -Copyright (C) 2011-2012 The TShock Team - -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program. If not, see . -*/ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Net; -using System.Net.Sockets; -using System.Security.Cryptography; -using System.Text; -using Terraria; - -namespace TShockAPI -{ - public class Utils - { - private readonly static int firstItemPrefix = 1; - private readonly static int lastItemPrefix = 83; - // Utils is a Singleton - private static readonly Utils instance = new Utils(); - private Utils() {} - public static Utils Instance { get { return instance; } } - - public Random Random = new Random(); - //private static List groups = new List(); - - /// - /// Provides the real IP address from a RemoteEndPoint string that contains a port and an IP - /// - /// A string IPv4 address in IP:PORT form. - /// A string IPv4 address. - public string GetRealIP(string mess) - { - return mess.Split(':')[0]; - } - - /// - /// Used for some places where a list of players might be used. - /// - /// String of players seperated by commas. - public string GetPlayers() - { - var sb = new StringBuilder(); - foreach (TSPlayer player in TShock.Players) - { - if (player != null && player.Active) - { - if (sb.Length != 0) - { - sb.Append(", "); - } - sb.Append(player.Name); - } - } - return sb.ToString(); - } - - /// - /// Used for some places where a list of players might be used. - /// - /// String of players and their id seperated by commas. - public string GetPlayersWithIds() - { - var sb = new StringBuilder(); - foreach (TSPlayer player in TShock.Players) - { - if (player != null && player.Active) - { - if (sb.Length != 0) - { - sb.Append(", "); - } - sb.Append(player.Name); - string id = "(ID: " + Convert.ToString(TShock.Users.GetUserID(player.UserAccountName)) + ", IX:" + player.Index + ")"; - sb.Append(id); - } - } - return sb.ToString(); - } - - /// - /// Finds a player and gets IP as string - /// - /// Player name - public string GetPlayerIP(string playername) - { - foreach (TSPlayer player in TShock.Players) - { - if (player != null && player.Active) - { - if (playername.ToLower() == player.Name.ToLower()) - { - return player.IP; - } - } - } - return null; - } - - /// - /// It's a clamp function - /// - /// - /// Value to clamp - /// Maximum bounds of the clamp - /// Minimum bounds of the clamp - /// - public T Clamp(T value, T max, T min) - where T : IComparable - { - T result = value; - if (value.CompareTo(max) > 0) - result = max; - if (value.CompareTo(min) < 0) - result = min; - return result; - } - - /// - /// Saves the map data - /// - public void SaveWorld() - { - SaveManager.Instance.SaveWorld(); - } - - /// - /// Broadcasts a message to all players - /// - /// string message - public void Broadcast(string msg) - { - Broadcast(msg, Color.Green); - } - - public void Broadcast(string msg, byte red, byte green, byte blue) - { - TSPlayer.All.SendMessage(msg, red, green, blue); - TSPlayer.Server.SendMessage(msg, red, green, blue); - Log.Info(string.Format("Broadcast: {0}", msg)); - } - - public void Broadcast(string msg, Color color) - { - Broadcast(msg, color.R, color.G, color.B); - } - - /// - /// Sends message to all users with 'logs' permission. - /// - /// Message to send - /// Color of the message - public void SendLogs(string log, Color color) - { - Log.Info(log); - TSPlayer.Server.SendMessage(log, color); - foreach (TSPlayer player in TShock.Players) - { - if (player != null && player.Active && player.Group.HasPermission(Permissions.logs) && player.DisplayLogs && - TShock.Config.DisableSpewLogs == false) - player.SendMessage(log, color); - } - } - - /// - /// The number of active players on the server. - /// - /// int playerCount - public int ActivePlayers() - { - return Main.player.Where(p => null != p && p.active).Count(); - } - - /// - /// Finds a TSPlayer based on name or id - /// - /// Player name - /// - public List FindPlayer(string ply) - { - var found = new List(); - // Avoid errors caused by null search - if (null == ply) - return found; - ply = ply.ToLower(); - foreach (TSPlayer player in TShock.Players) - { - if (player == null) - continue; - - try - { - if (Convert.ToInt32(ply) == player.Index && player.Active) - { - return new List { player }; - } - } - catch (Exception e) - { - // Conversion failed - } - - string name = player.Name.ToLower(); - if (name.Equals(ply)) - return new List {player}; - if (name.Contains(ply)) - found.Add(player); - } - return found; - } - - /// - /// Gets a random clear tile in range - /// - /// Bound X - /// Bound Y - /// Range on the X axis - /// Range on the Y axis - /// X location - /// Y location - public void GetRandomClearTileWithInRange(int startTileX, int startTileY, int tileXRange, int tileYRange, - out int tileX, out int tileY) - { - int j = 0; - do - { - if (j == 100) - { - tileX = startTileX; - tileY = startTileY; - break; - } - - tileX = startTileX + Random.Next(tileXRange*-1, tileXRange); - tileY = startTileY + Random.Next(tileYRange*-1, tileYRange); - j++; - } while (TileValid(tileX, tileY) && !TileClear(tileX, tileY)); - } - - /// - /// Determines if a tile is valid - /// - /// Location X - /// Location Y - /// If the tile is valid - private bool TileValid(int tileX, int tileY) - { - return tileX >= 0 && tileX <= Main.maxTilesX && tileY >= 0 && tileY <= Main.maxTilesY; - } - - /// - /// Clears a tile - /// - /// Location X - /// Location Y - /// The state of the tile - private bool TileClear(int tileX, int tileY) - { - return !Main.tile[tileX, tileY].active; - } - - /// - /// Gets a list of items by ID or name - /// - /// Item ID or name - /// List of Items - public List GetItemByIdOrName(string idOrName) - { - int type = -1; - if (int.TryParse(idOrName, out type)) - { - return new List {GetItemById(type)}; - } - return GetItemByName(idOrName); - } - - /// - /// Gets an item by ID - /// - /// ID - /// Item - public Item GetItemById(int id) - { - Item item = new Item(); - item.netDefaults(id); - return item; - } - - /// - /// Gets items by name - /// - /// name - /// List of Items - public List GetItemByName(string name) - { - //Method #1 - must be exact match, allows support for different pickaxes/hammers/swords etc - for (int i = 1; i < Main.maxItemTypes; i++) - { - Item item = new Item(); - item.SetDefaults(name); - if (item.name == name) - return new List {item}; - } - //Method #2 - allows impartial matching - var found = new List(); - for (int i = -24; i < Main.maxItemTypes; i++) - { - try - { - Item item = new Item(); - item.netDefaults(i); - if (item.name.ToLower() == name.ToLower()) - return new List {item}; - if (item.name.ToLower().StartsWith(name.ToLower())) - found.Add(item); - } - catch - { - } - } - return found; - } - - /// - /// Gets an NPC by ID or Name - /// - /// - /// List of NPCs - public List GetNPCByIdOrName(string idOrName) - { - int type = -1; - if (int.TryParse(idOrName, out type)) - { - return new List {GetNPCById(type)}; - } - return GetNPCByName(idOrName); - } - - /// - /// Gets an NPC by ID - /// - /// ID - /// NPC - public NPC GetNPCById(int id) - { - NPC npc = new NPC(); - npc.netDefaults(id); - return npc; - } - - /// - /// Gets a NPC by name - /// - /// Name - /// List of matching NPCs - public List GetNPCByName(string name) - { - //Method #1 - must be exact match, allows support for different coloured slimes - for (int i = -17; i < Main.maxNPCTypes; i++) - { - NPC npc = new NPC(); - npc.SetDefaults(name); - if (npc.name == name) - return new List {npc}; - } - //Method #2 - allows impartial matching - var found = new List(); - for (int i = 1; i < Main.maxNPCTypes; i++) - { - NPC npc = new NPC(); - npc.netDefaults(i); - if (npc.name.ToLower() == name.ToLower()) - return new List {npc}; - if (npc.name.ToLower().StartsWith(name.ToLower())) - found.Add(npc); - } - return found; - } - - /// - /// Gets a buff name by id - /// - /// ID - /// name - public string GetBuffName(int id) - { - return (id > 0 && id < Main.maxBuffs) ? Main.buffName[id] : "null"; - } - - /// - /// Gets the description of a buff - /// - /// ID - /// description - public string GetBuffDescription(int id) - { - return (id > 0 && id < Main.maxBuffs) ? Main.buffTip[id] : "null"; - } - - /// - /// Gets a list of buffs by name - /// - /// name - /// Matching list of buff ids - public List GetBuffByName(string name) - { - for (int i = 1; i < Main.maxBuffs; i++) - { - if (Main.buffName[i].ToLower() == name) - return new List {i}; - } - var found = new List(); - for (int i = 1; i < Main.maxBuffs; i++) - { - if (Main.buffName[i].ToLower().StartsWith(name.ToLower())) - found.Add(i); - } - return found; - } - - /// - /// Gets a prefix based on its id - /// - /// ID - /// Prefix name - public string GetPrefixById(int id) - { - var item = new Item(); - item.SetDefaults(0); - item.prefix = (byte) id; - item.AffixName(); - return item.name.Trim(); - } - - /// - /// Gets a list of prefixes by name - /// - /// Name - /// List of prefix IDs - public List GetPrefixByName(string name) - { - Item item = new Item(); - item.SetDefaults(0); - string lowerName = name.ToLower(); - var found = new List(); - for (int i = firstItemPrefix; i <= lastItemPrefix; i++) - { - try - { - item.prefix = (byte)i; - string trimmed = item.AffixName().Trim(); - if (trimmed == name) - { - // Exact match - found.Add(i); - return found; - } - else - { - string trimmedLower = trimmed.ToLower(); - if (trimmedLower == lowerName) - { - // Exact match (caseinsensitive) - found.Add(i); - return found; - } - else if (trimmedLower.StartsWith(lowerName)) // Partial match - found.Add(i); - } - } - catch - { - } - } - return found; - } - - /// - /// Gets a prefix by ID or name - /// - /// ID or name - /// List of prefix IDs - public List GetPrefixByIdOrName(string idOrName) - { - int type = -1; - if (int.TryParse(idOrName, out type) && type >= firstItemPrefix && type <= lastItemPrefix) - { - return new List {type}; - } - return GetPrefixByName(idOrName); - } - - /// - /// Kicks all player from the server without checking for immunetokick permission. - /// - /// int player - /// string reason - public void ForceKickAll(string reason) - { - foreach (TSPlayer player in TShock.Players) - { - if (player != null && player.Active) - { - ForceKick(player, reason); - } - } - } - - /// - /// Stops the server after kicking all players with a reason message, and optionally saving the world - /// - /// bool perform a world save before stop (default: true) - /// string reason (default: "Server shutting down!") - public void StopServer(bool save = true, string reason = "Server shutting down!") - { - ForceKickAll(reason); - if (save) - SaveManager.Instance.SaveWorld(); - - // Save takes a while so kick again - ForceKickAll(reason); - - // Broadcast so console can see we are shutting down as well - TShock.Utils.Broadcast(reason, Color.Red); - - // Disconnect after kick as that signifies server is exiting and could cause a race - Netplay.disconnect = true; - } - -#if COMPAT_SIGS - [Obsolete("This method is for signature compatibility for external code only")] - public void ForceKick(TSPlayer player, string reason) - { - Kick(player, reason, true, false, string.Empty); - } -#endif - /// - /// Kicks a player from the server without checking for immunetokick permission. - /// - /// int player - /// string reason - /// bool silent (default: false) - public void ForceKick(TSPlayer player, string reason, bool silent = false, bool saveSSI = false) - { - Kick(player, reason, true, silent, null, saveSSI); - } - -#if COMPAT_SIGS - [Obsolete("This method is for signature compatibility for external code only")] - public bool Kick(TSPlayer player, string reason, string adminUserName) - { - return Kick(player, reason, false, false, adminUserName); - } -#endif - /// - /// Kicks a player from the server.. - /// - /// int player - /// string reason - /// bool force (default: false) - /// bool silent (default: false) - /// string adminUserName (default: null) - /// bool saveSSI (default: false) - public bool Kick(TSPlayer player, string reason, bool force = false, bool silent = false, string adminUserName = null, bool saveSSI = false) - { - if (!player.ConnectionAlive) - return true; - if (force || !player.Group.HasPermission(Permissions.immunetokick)) - { - string playerName = player.Name; - player.SilentKickInProgress = silent; - if (player.IsLoggedIn && saveSSI) - player.SaveServerInventory(); - player.Disconnect(string.Format("Kicked: {0}", reason)); - Log.ConsoleInfo(string.Format("Kicked {0} for : {1}", playerName, reason)); - string verb = force ? "force " : ""; - if (!silent) - { - if (string.IsNullOrWhiteSpace(adminUserName)) - Broadcast(string.Format("{0} was {1}kicked for {2}", playerName, verb, reason.ToLower())); - else - Broadcast(string.Format("{0} {1}kicked {2} for {3}", adminUserName, verb, playerName, reason.ToLower())); - } - return true; - } - return false; - } - -#if COMPAT_SIGS - [Obsolete("This method is for signature compatibility for external code only")] - public bool Ban(TSPlayer player, string reason, string adminUserName) - { - return Ban(player, reason, false, adminUserName); - } -#endif - /// - /// Bans and kicks a player from the server. - /// - /// int player - /// string reason - /// bool force (default: false) - /// bool silent (default: null) - public bool Ban(TSPlayer player, string reason, bool force = false, string adminUserName = null) - { - if (!player.ConnectionAlive) - return true; - if (force || !player.Group.HasPermission(Permissions.immunetoban)) - { - string ip = player.IP; - string playerName = player.Name; - TShock.Bans.AddBan(ip, playerName, reason); - player.Disconnect(string.Format("Banned: {0}", reason)); - Log.ConsoleInfo(string.Format("Banned {0} for : {1}", playerName, reason)); - string verb = force ? "force " : ""; - if (string.IsNullOrWhiteSpace(adminUserName)) - Broadcast(string.Format("{0} was {1}banned for {1}", playerName, verb, reason.ToLower())); - else - Broadcast(string.Format("{0} {1}banned {1} for {2}", adminUserName, verb, playerName, reason.ToLower())); - return true; - } - return false; - } - - /// - /// Shows a file to the user. - /// - /// int player - /// string filename reletave to savedir - //Todo: Fix this - public void ShowFileToUser(TSPlayer player, string file) - { - string foo = ""; - using (var tr = new StreamReader(Path.Combine(TShock.SavePath, file))) - { - while ((foo = tr.ReadLine()) != null) - { - foo = foo.Replace("%map%", Main.worldName); - foo = foo.Replace("%players%", GetPlayers()); - //foo = SanitizeString(foo); - if (foo.Substring(0, 1) == "%" && foo.Substring(12, 1) == "%") //Look for a beginning color code. - { - string possibleColor = foo.Substring(0, 13); - foo = foo.Remove(0, 13); - float[] pC = {0, 0, 0}; - possibleColor = possibleColor.Replace("%", ""); - string[] pCc = possibleColor.Split(','); - if (pCc.Length == 3) - { - try - { - player.SendMessage(foo, (byte) Convert.ToInt32(pCc[0]), (byte) Convert.ToInt32(pCc[1]), - (byte) Convert.ToInt32(pCc[2])); - continue; - } - catch (Exception e) - { - Log.Error(e.ToString()); - } - } - } - player.SendMessage(foo); - } - } - } - - /// - /// Returns a Group from the name of the group - /// - /// string groupName - public Group GetGroup(string groupName) - { - //first attempt on cached groups - for (int i = 0; i < TShock.Groups.groups.Count; i++) - { - if (TShock.Groups.groups[i].Name.Equals(groupName)) - { - return TShock.Groups.groups[i]; - } - } - return new Group(TShock.Config.DefaultGuestGroupName); - } - - /// - /// Returns an IPv4 address from a DNS query - /// - /// string ip - public string GetIPv4Address(string hostname) - { - try - { - //Get the ipv4 address from GetHostAddresses, if an ip is passed it will return that ip - var ip = Dns.GetHostAddresses(hostname).FirstOrDefault(i => i.AddressFamily == AddressFamily.InterNetwork); - //if the dns query was successful then return it, otherwise return an empty string - return ip != null ? ip.ToString() : ""; - } - catch (SocketException) - { - } - return ""; - } - - public string HashAlgo = "sha512"; - - public readonly Dictionary> HashTypes = new Dictionary> - { - {"sha512", () => new SHA512Managed()}, - {"sha256", () => new SHA256Managed()}, - {"md5", () => new MD5Cng()}, - {"sha512-xp", () => SHA512.Create()}, - {"sha256-xp", () => SHA256.Create()}, - {"md5-xp", () => MD5.Create()}, - }; - - /// - /// Returns a Sha256 string for a given string - /// - /// bytes to hash - /// string sha256 - public string HashPassword(byte[] bytes) - { - if (bytes == null) - throw new NullReferenceException("bytes"); - Func func; - if (!HashTypes.TryGetValue(HashAlgo.ToLower(), out func)) - throw new NotSupportedException("Hashing algorithm {0} is not supported".SFormat(HashAlgo.ToLower())); - - using (var hash = func()) - { - var ret = hash.ComputeHash(bytes); - return ret.Aggregate("", (s, b) => s + b.ToString("X2")); - } - } - - /// - /// Returns a Sha256 string for a given string - /// - /// bytes to hash - /// string sha256 - public string HashPassword(string password) - { - if (string.IsNullOrEmpty(password) || password == "non-existant password") - return "non-existant password"; - return HashPassword(Encoding.UTF8.GetBytes(password)); - } - - /// - /// Checks if the string contains any unprintable characters - /// - /// String to check - /// True if the string only contains printable characters - public bool ValidString(string str) - { - foreach (var c in str) - { - if (c < 0x20 || c > 0xA9) - return false; - } - return true; - } - - /// - /// Checks if world has hit the max number of chests - /// - /// True if the entire chest array is used - public bool MaxChests() - { - for (int i = 0; i < Main.chest.Length; i++) - { - if (Main.chest[i] == null) - return false; - } - return true; - } - - /// - /// Searches for a projectile by identity and owner - /// - /// identity - /// owner - /// projectile ID - public int SearchProjectile(short identity, int owner) - { - for (int i = 0; i < Main.maxProjectiles; i++) - { - if (Main.projectile[i].identity == identity && Main.projectile[i].owner == owner) - return i; - } - return 1000; - } - - /// - /// Sanitizes input strings - /// - /// string - /// sanitized string - public string SanitizeString(string str) - { - var returnstr = str.ToCharArray(); - for (int i = 0; i < str.Length; i++) - { - if (!ValidString(str[i].ToString())) - returnstr[i] = ' '; - } - return new string(returnstr); - } - } -} +/* +TShock, a server mod for Terraria +Copyright (C) 2011-2012 The TShock Team + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*/ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Net; +using System.Net.Sockets; +using System.Security.Cryptography; +using System.Text; +using Terraria; + +namespace TShockAPI +{ + public class Utils + { + private readonly static int firstItemPrefix = 1; + private readonly static int lastItemPrefix = 83; + // Utils is a Singleton + private static readonly Utils instance = new Utils(); + private Utils() {} + public static Utils Instance { get { return instance; } } + + public Random Random = new Random(); + //private static List groups = new List(); + + /// + /// Provides the real IP address from a RemoteEndPoint string that contains a port and an IP + /// + /// A string IPv4 address in IP:PORT form. + /// A string IPv4 address. + public string GetRealIP(string mess) + { + return mess.Split(':')[0]; + } + + /// + /// Used for some places where a list of players might be used. + /// + /// String of players seperated by commas. + public string GetPlayers() + { + var sb = new StringBuilder(); + foreach (TSPlayer player in TShock.Players) + { + if (player != null && player.Active) + { + if (sb.Length != 0) + { + sb.Append(", "); + } + sb.Append(player.Name); + } + } + return sb.ToString(); + } + + /// + /// Used for some places where a list of players might be used. + /// + /// String of players and their id seperated by commas. + public string GetPlayersWithIds() + { + var sb = new StringBuilder(); + foreach (TSPlayer player in TShock.Players) + { + if (player != null && player.Active) + { + if (sb.Length != 0) + { + sb.Append(", "); + } + sb.Append(player.Name); + string id = "(ID: " + Convert.ToString(TShock.Users.GetUserID(player.UserAccountName)) + ", IX:" + player.Index + ")"; + sb.Append(id); + } + } + return sb.ToString(); + } + + /// + /// Finds a player and gets IP as string + /// + /// Player name + public string GetPlayerIP(string playername) + { + foreach (TSPlayer player in TShock.Players) + { + if (player != null && player.Active) + { + if (playername.ToLower() == player.Name.ToLower()) + { + return player.IP; + } + } + } + return null; + } + + /// + /// It's a clamp function + /// + /// + /// Value to clamp + /// Maximum bounds of the clamp + /// Minimum bounds of the clamp + /// + public T Clamp(T value, T max, T min) + where T : IComparable + { + T result = value; + if (value.CompareTo(max) > 0) + result = max; + if (value.CompareTo(min) < 0) + result = min; + return result; + } + + /// + /// Saves the map data + /// + public void SaveWorld() + { + SaveManager.Instance.SaveWorld(); + } + + /// + /// Broadcasts a message to all players + /// + /// string message + public void Broadcast(string msg) + { + Broadcast(msg, Color.Green); + } + + public void Broadcast(string msg, byte red, byte green, byte blue) + { + TSPlayer.All.SendMessage(msg, red, green, blue); + TSPlayer.Server.SendMessage(msg, red, green, blue); + Log.Info(string.Format("Broadcast: {0}", msg)); + } + + public void Broadcast(string msg, Color color) + { + Broadcast(msg, color.R, color.G, color.B); + } + + /// + /// Sends message to all users with 'logs' permission. + /// + /// Message to send + /// Color of the message + public void SendLogs(string log, Color color) + { + Log.Info(log); + TSPlayer.Server.SendMessage(log, color); + foreach (TSPlayer player in TShock.Players) + { + if (player != null && player.Active && player.Group.HasPermission(Permissions.logs) && player.DisplayLogs && + TShock.Config.DisableSpewLogs == false) + player.SendMessage(log, color); + } + } + + /// + /// The number of active players on the server. + /// + /// int playerCount + public int ActivePlayers() + { + return Main.player.Where(p => null != p && p.active).Count(); + } + + /// + /// Finds a TSPlayer based on name or id + /// + /// Player name + /// + public List FindPlayer(string ply) + { + var found = new List(); + // Avoid errors caused by null search + if (null == ply) + return found; + ply = ply.ToLower(); + foreach (TSPlayer player in TShock.Players) + { + if (player == null) + continue; + + try + { + if (Convert.ToInt32(ply) == player.Index && player.Active) + { + return new List { player }; + } + } + catch (Exception e) + { + // Conversion failed + } + + string name = player.Name.ToLower(); + if (name.Equals(ply)) + return new List {player}; + if (name.Contains(ply)) + found.Add(player); + } + return found; + } + + /// + /// Gets a random clear tile in range + /// + /// Bound X + /// Bound Y + /// Range on the X axis + /// Range on the Y axis + /// X location + /// Y location + public void GetRandomClearTileWithInRange(int startTileX, int startTileY, int tileXRange, int tileYRange, + out int tileX, out int tileY) + { + int j = 0; + do + { + if (j == 100) + { + tileX = startTileX; + tileY = startTileY; + break; + } + + tileX = startTileX + Random.Next(tileXRange*-1, tileXRange); + tileY = startTileY + Random.Next(tileYRange*-1, tileYRange); + j++; + } while (TileValid(tileX, tileY) && !TileClear(tileX, tileY)); + } + + /// + /// Determines if a tile is valid + /// + /// Location X + /// Location Y + /// If the tile is valid + private bool TileValid(int tileX, int tileY) + { + return tileX >= 0 && tileX <= Main.maxTilesX && tileY >= 0 && tileY <= Main.maxTilesY; + } + + /// + /// Clears a tile + /// + /// Location X + /// Location Y + /// The state of the tile + private bool TileClear(int tileX, int tileY) + { + return !Main.tile[tileX, tileY].active; + } + + /// + /// Gets a list of items by ID or name + /// + /// Item ID or name + /// List of Items + public List GetItemByIdOrName(string idOrName) + { + int type = -1; + if (int.TryParse(idOrName, out type)) + { + return new List {GetItemById(type)}; + } + return GetItemByName(idOrName); + } + + /// + /// Gets an item by ID + /// + /// ID + /// Item + public Item GetItemById(int id) + { + Item item = new Item(); + item.netDefaults(id); + return item; + } + + /// + /// Gets items by name + /// + /// name + /// List of Items + public List GetItemByName(string name) + { + //Method #1 - must be exact match, allows support for different pickaxes/hammers/swords etc + for (int i = 1; i < Main.maxItemTypes; i++) + { + Item item = new Item(); + item.SetDefaults(name); + if (item.name == name) + return new List {item}; + } + //Method #2 - allows impartial matching + var found = new List(); + for (int i = -24; i < Main.maxItemTypes; i++) + { + try + { + Item item = new Item(); + item.netDefaults(i); + if (item.name.ToLower() == name.ToLower()) + return new List {item}; + if (item.name.ToLower().StartsWith(name.ToLower())) + found.Add(item); + } + catch + { + } + } + return found; + } + + /// + /// Gets an NPC by ID or Name + /// + /// + /// List of NPCs + public List GetNPCByIdOrName(string idOrName) + { + int type = -1; + if (int.TryParse(idOrName, out type)) + { + return new List {GetNPCById(type)}; + } + return GetNPCByName(idOrName); + } + + /// + /// Gets an NPC by ID + /// + /// ID + /// NPC + public NPC GetNPCById(int id) + { + NPC npc = new NPC(); + npc.netDefaults(id); + return npc; + } + + /// + /// Gets a NPC by name + /// + /// Name + /// List of matching NPCs + public List GetNPCByName(string name) + { + //Method #1 - must be exact match, allows support for different coloured slimes + for (int i = -17; i < Main.maxNPCTypes; i++) + { + NPC npc = new NPC(); + npc.SetDefaults(name); + if (npc.name == name) + return new List {npc}; + } + //Method #2 - allows impartial matching + var found = new List(); + for (int i = 1; i < Main.maxNPCTypes; i++) + { + NPC npc = new NPC(); + npc.netDefaults(i); + if (npc.name.ToLower() == name.ToLower()) + return new List {npc}; + if (npc.name.ToLower().StartsWith(name.ToLower())) + found.Add(npc); + } + return found; + } + + /// + /// Gets a buff name by id + /// + /// ID + /// name + public string GetBuffName(int id) + { + return (id > 0 && id < Main.maxBuffs) ? Main.buffName[id] : "null"; + } + + /// + /// Gets the description of a buff + /// + /// ID + /// description + public string GetBuffDescription(int id) + { + return (id > 0 && id < Main.maxBuffs) ? Main.buffTip[id] : "null"; + } + + /// + /// Gets a list of buffs by name + /// + /// name + /// Matching list of buff ids + public List GetBuffByName(string name) + { + for (int i = 1; i < Main.maxBuffs; i++) + { + if (Main.buffName[i].ToLower() == name) + return new List {i}; + } + var found = new List(); + for (int i = 1; i < Main.maxBuffs; i++) + { + if (Main.buffName[i].ToLower().StartsWith(name.ToLower())) + found.Add(i); + } + return found; + } + + /// + /// Gets a prefix based on its id + /// + /// ID + /// Prefix name + public string GetPrefixById(int id) + { + var item = new Item(); + item.SetDefaults(0); + item.prefix = (byte) id; + item.AffixName(); + return item.name.Trim(); + } + + /// + /// Gets a list of prefixes by name + /// + /// Name + /// List of prefix IDs + public List GetPrefixByName(string name) + { + Item item = new Item(); + item.SetDefaults(0); + string lowerName = name.ToLower(); + var found = new List(); + for (int i = firstItemPrefix; i <= lastItemPrefix; i++) + { + try + { + item.prefix = (byte)i; + string trimmed = item.AffixName().Trim(); + if (trimmed == name) + { + // Exact match + found.Add(i); + return found; + } + else + { + string trimmedLower = trimmed.ToLower(); + if (trimmedLower == lowerName) + { + // Exact match (caseinsensitive) + found.Add(i); + return found; + } + else if (trimmedLower.StartsWith(lowerName)) // Partial match + found.Add(i); + } + } + catch + { + } + } + return found; + } + + /// + /// Gets a prefix by ID or name + /// + /// ID or name + /// List of prefix IDs + public List GetPrefixByIdOrName(string idOrName) + { + int type = -1; + if (int.TryParse(idOrName, out type) && type >= firstItemPrefix && type <= lastItemPrefix) + { + return new List {type}; + } + return GetPrefixByName(idOrName); + } + + /// + /// Kicks all player from the server without checking for immunetokick permission. + /// + /// int player + /// string reason + public void ForceKickAll(string reason) + { + foreach (TSPlayer player in TShock.Players) + { + if (player != null && player.Active) + { + ForceKick(player, reason); + } + } + } + + /// + /// Stops the server after kicking all players with a reason message, and optionally saving the world + /// + /// bool perform a world save before stop (default: true) + /// string reason (default: "Server shutting down!") + public void StopServer(bool save = true, string reason = "Server shutting down!") + { + ForceKickAll(reason); + if (save) + SaveManager.Instance.SaveWorld(); + + // Save takes a while so kick again + ForceKickAll(reason); + + // Broadcast so console can see we are shutting down as well + TShock.Utils.Broadcast(reason, Color.Red); + + // Disconnect after kick as that signifies server is exiting and could cause a race + Netplay.disconnect = true; + } + +#if COMPAT_SIGS + [Obsolete("This method is for signature compatibility for external code only")] + public void ForceKick(TSPlayer player, string reason) + { + Kick(player, reason, true, false, string.Empty); + } +#endif + /// + /// Kicks a player from the server without checking for immunetokick permission. + /// + /// int player + /// string reason + /// bool silent (default: false) + public void ForceKick(TSPlayer player, string reason, bool silent = false, bool saveSSI = false) + { + Kick(player, reason, true, silent, null, saveSSI); + } + +#if COMPAT_SIGS + [Obsolete("This method is for signature compatibility for external code only")] + public bool Kick(TSPlayer player, string reason, string adminUserName) + { + return Kick(player, reason, false, false, adminUserName); + } +#endif + /// + /// Kicks a player from the server.. + /// + /// int player + /// string reason + /// bool force (default: false) + /// bool silent (default: false) + /// string adminUserName (default: null) + /// bool saveSSI (default: false) + public bool Kick(TSPlayer player, string reason, bool force = false, bool silent = false, string adminUserName = null, bool saveSSI = false) + { + if (!player.ConnectionAlive) + return true; + if (force || !player.Group.HasPermission(Permissions.immunetokick)) + { + string playerName = player.Name; + player.SilentKickInProgress = silent; + if (player.IsLoggedIn && saveSSI) + player.SaveServerInventory(); + player.Disconnect(string.Format("Kicked: {0}", reason)); + Log.ConsoleInfo(string.Format("Kicked {0} for : {1}", playerName, reason)); + string verb = force ? "force " : ""; + if (!silent) + { + if (string.IsNullOrWhiteSpace(adminUserName)) + Broadcast(string.Format("{0} was {1}kicked for {2}", playerName, verb, reason.ToLower())); + else + Broadcast(string.Format("{0} {1}kicked {2} for {3}", adminUserName, verb, playerName, reason.ToLower())); + } + return true; + } + return false; + } + +#if COMPAT_SIGS + [Obsolete("This method is for signature compatibility for external code only")] + public bool Ban(TSPlayer player, string reason, string adminUserName) + { + return Ban(player, reason, false, adminUserName); + } +#endif + /// + /// Bans and kicks a player from the server. + /// + /// int player + /// string reason + /// bool force (default: false) + /// bool silent (default: null) + public bool Ban(TSPlayer player, string reason, bool force = false, string adminUserName = null) + { + if (!player.ConnectionAlive) + return true; + if (force || !player.Group.HasPermission(Permissions.immunetoban)) + { + string ip = player.IP; + string playerName = player.Name; + TShock.Bans.AddBan(ip, playerName, reason); + player.Disconnect(string.Format("Banned: {0}", reason)); + Log.ConsoleInfo(string.Format("Banned {0} for : {1}", playerName, reason)); + string verb = force ? "force " : ""; + if (string.IsNullOrWhiteSpace(adminUserName)) + Broadcast(string.Format("{0} was {1}banned for {1}", playerName, verb, reason.ToLower())); + else + Broadcast(string.Format("{0} {1}banned {1} for {2}", adminUserName, verb, playerName, reason.ToLower())); + return true; + } + return false; + } + + /// + /// Shows a file to the user. + /// + /// int player + /// string filename reletave to savedir + //Todo: Fix this + public void ShowFileToUser(TSPlayer player, string file) + { + string foo = ""; + using (var tr = new StreamReader(Path.Combine(TShock.SavePath, file))) + { + while ((foo = tr.ReadLine()) != null) + { + foo = foo.Replace("%map%", Main.worldName); + foo = foo.Replace("%players%", GetPlayers()); + //foo = SanitizeString(foo); + if (foo.Substring(0, 1) == "%" && foo.Substring(12, 1) == "%") //Look for a beginning color code. + { + string possibleColor = foo.Substring(0, 13); + foo = foo.Remove(0, 13); + float[] pC = {0, 0, 0}; + possibleColor = possibleColor.Replace("%", ""); + string[] pCc = possibleColor.Split(','); + if (pCc.Length == 3) + { + try + { + player.SendMessage(foo, (byte) Convert.ToInt32(pCc[0]), (byte) Convert.ToInt32(pCc[1]), + (byte) Convert.ToInt32(pCc[2])); + continue; + } + catch (Exception e) + { + Log.Error(e.ToString()); + } + } + } + player.SendMessage(foo); + } + } + } + + /// + /// Returns a Group from the name of the group + /// + /// string groupName + public Group GetGroup(string groupName) + { + //first attempt on cached groups + for (int i = 0; i < TShock.Groups.groups.Count; i++) + { + if (TShock.Groups.groups[i].Name.Equals(groupName)) + { + return TShock.Groups.groups[i]; + } + } + return new Group(TShock.Config.DefaultGuestGroupName); + } + + /// + /// Returns an IPv4 address from a DNS query + /// + /// string ip + public string GetIPv4Address(string hostname) + { + try + { + //Get the ipv4 address from GetHostAddresses, if an ip is passed it will return that ip + var ip = Dns.GetHostAddresses(hostname).FirstOrDefault(i => i.AddressFamily == AddressFamily.InterNetwork); + //if the dns query was successful then return it, otherwise return an empty string + return ip != null ? ip.ToString() : ""; + } + catch (SocketException) + { + } + return ""; + } + + public string HashAlgo = "sha512"; + + public readonly Dictionary> HashTypes = new Dictionary> + { + {"sha512", () => new SHA512Managed()}, + {"sha256", () => new SHA256Managed()}, + {"md5", () => new MD5Cng()}, + {"sha512-xp", () => SHA512.Create()}, + {"sha256-xp", () => SHA256.Create()}, + {"md5-xp", () => MD5.Create()}, + }; + + /// + /// Returns a Sha256 string for a given string + /// + /// bytes to hash + /// string sha256 + public string HashPassword(byte[] bytes) + { + if (bytes == null) + throw new NullReferenceException("bytes"); + Func func; + if (!HashTypes.TryGetValue(HashAlgo.ToLower(), out func)) + throw new NotSupportedException("Hashing algorithm {0} is not supported".SFormat(HashAlgo.ToLower())); + + using (var hash = func()) + { + var ret = hash.ComputeHash(bytes); + return ret.Aggregate("", (s, b) => s + b.ToString("X2")); + } + } + + /// + /// Returns a Sha256 string for a given string + /// + /// bytes to hash + /// string sha256 + public string HashPassword(string password) + { + if (string.IsNullOrEmpty(password) || password == "non-existant password") + return "non-existant password"; + return HashPassword(Encoding.UTF8.GetBytes(password)); + } + + /// + /// Checks if the string contains any unprintable characters + /// + /// String to check + /// True if the string only contains printable characters + public bool ValidString(string str) + { + foreach (var c in str) + { + if (c < 0x20 || c > 0xA9) + return false; + } + return true; + } + + /// + /// Checks if world has hit the max number of chests + /// + /// True if the entire chest array is used + public bool MaxChests() + { + for (int i = 0; i < Main.chest.Length; i++) + { + if (Main.chest[i] == null) + return false; + } + return true; + } + + /// + /// Searches for a projectile by identity and owner + /// + /// identity + /// owner + /// projectile ID + public int SearchProjectile(short identity, int owner) + { + for (int i = 0; i < Main.maxProjectiles; i++) + { + if (Main.projectile[i].identity == identity && Main.projectile[i].owner == owner) + return i; + } + return 1000; + } + + /// + /// Sanitizes input strings + /// + /// string + /// sanitized string + public string SanitizeString(string str) + { + var returnstr = str.ToCharArray(); + for (int i = 0; i < str.Length; i++) + { + if (!ValidString(str[i].ToString())) + returnstr[i] = ' '; + } + return new string(returnstr); + } + } +} diff --git a/UnitTests/UnitTests.csproj b/UnitTests/UnitTests.csproj index 923856ac..bf71afcf 100644 --- a/UnitTests/UnitTests.csproj +++ b/UnitTests/UnitTests.csproj @@ -1,147 +1,176 @@ - - - - Debug - AnyCPU - - - 2.0 - {F3742F51-D7BF-4754-A68A-CD944D2A21FF} - Library - Properties - UnitTests - UnitTests - v4.0 - 512 - {3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} - false - publish\ - true - Disk - false - Foreground - 7 - Days - false - false - true - 0 - 1.0.0.%2a - false - true - - - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - - - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - - - - - - ..\SqlBins\Mono.Data.Sqlite.dll - - - ..\SqlBins\MySql.Data.dll - - - ..\SqlBins\MySql.Web.dll - - - - 3.5 - - - - - False - .exe - ..\TerrariaServerBins\TerrariaServer.exe - - - - - False - - - - - - - - - - - - {49606449-072B-4CF5-8088-AA49DA586694} - TShockAPI - - - {F2FEDAFB-58DE-4611-9168-A86112C346C7} - TShockRestTestPlugin - - - - - Always - - - Always - - - Always - - - Always - - - - Always - - - - - False - Microsoft .NET Framework 4 %28x86 and x64%29 - true - - - False - .NET Framework 3.5 SP1 Client Profile - false - - - False - .NET Framework 3.5 SP1 - false - - - False - Windows Installer 3.1 - true - - - - - xcopy .\..\..\..\SqlBins\sqlite3.dll . /Y - - + + + + Debug + AnyCPU + + + 2.0 + {F3742F51-D7BF-4754-A68A-CD944D2A21FF} + Library + Properties + UnitTests + UnitTests + v4.0 + 512 + {3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + false + publish\ + true + Disk + false + Foreground + 7 + Days + false + false + true + 0 + 1.0.0.%2a + false + true + 10.0 + $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) + $(ProgramFiles)\Common Files\microsoft shared\VSTT\$(VisualStudioVersion)\UITestExtensionPackages + False + WebTest + + + + + 4.0 + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + + + ..\SqlBins\Mono.Data.Sqlite.dll + + + ..\SqlBins\MySql.Data.dll + + + ..\SqlBins\MySql.Web.dll + + + + 3.5 + + + + + False + .exe + ..\TerrariaServerBins\TerrariaServer.exe + + + + + False + + + + + + + + + + + + {49606449-072B-4CF5-8088-AA49DA586694} + TShockAPI + + + {F2FEDAFB-58DE-4611-9168-A86112C346C7} + TShockRestTestPlugin + + + + + Always + + + Always + + + Always + + + Always + + + + Always + + + + + False + Microsoft .NET Framework 4 %28x86 and x64%29 + true + + + False + .NET Framework 3.5 SP1 Client Profile + false + + + False + .NET Framework 3.5 SP1 + false + + + False + Windows Installer 3.1 + true + + + + + + + False + + + False + + + False + + + False + + + + + + + + xcopy .\..\..\..\SqlBins\sqlite3.dll . /Y + + \ No newline at end of file