servuo/Server/Utility.cs
VitaNex f840e50340 Updated .editorconfig file with advanced configuration settings that will help maintain user code style and best practices with most IDE's.
Complete core housekeeping operation using "Profile 1" with new .editorconfig settings.
2021-01-15 12:51:10 -08:00

1767 lines
36 KiB
C#

#region References
using System;
using System.Collections;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Text.RegularExpressions;
using System.Xml;
#endregion
namespace Server
{
public static class Utility
{
private static Encoding m_UTF8, m_UTF8WithEncoding;
public static Encoding UTF8
{
get
{
if (m_UTF8 == null)
{
m_UTF8 = new UTF8Encoding(false, false);
}
return m_UTF8;
}
}
public static Encoding UTF8WithEncoding
{
get
{
if (m_UTF8WithEncoding == null)
{
m_UTF8WithEncoding = new UTF8Encoding(true, false);
}
return m_UTF8WithEncoding;
}
}
public static void Separate(StringBuilder sb, string value, string separator)
{
if (sb.Length > 0)
{
sb.Append(separator);
}
sb.Append(value);
}
public static string Intern(string str)
{
if (str == null)
{
return null;
}
else if (str.Length == 0)
{
return String.Empty;
}
return String.Intern(str);
}
public static void Intern(ref string str)
{
str = Intern(str);
}
private static Dictionary<IPAddress, IPAddress> _ipAddressTable;
public static IPAddress Intern(IPAddress ipAddress)
{
if (_ipAddressTable == null)
{
_ipAddressTable = new Dictionary<IPAddress, IPAddress>();
}
if (!_ipAddressTable.TryGetValue(ipAddress, out var interned))
{
interned = ipAddress;
_ipAddressTable[ipAddress] = interned;
}
return interned;
}
public static void Intern(ref IPAddress ipAddress)
{
ipAddress = Intern(ipAddress);
}
public static bool IsValidIP(string text)
{
var valid = true;
IPMatch(text, IPAddress.None, ref valid);
return valid;
}
public static bool IPMatch(string val, IPAddress ip)
{
var valid = true;
return IPMatch(val, ip, ref valid);
}
public static string FixHtml(string str)
{
if (str == null)
{
return "";
}
var hasOpen = str.IndexOf('<') >= 0;
var hasClose = str.IndexOf('>') >= 0;
var hasPound = str.IndexOf('#') >= 0;
if (!hasOpen && !hasClose && !hasPound)
{
return str;
}
var sb = new StringBuilder(str);
if (hasOpen)
{
sb.Replace('<', '(');
}
if (hasClose)
{
sb.Replace('>', ')');
}
if (hasPound)
{
sb.Replace('#', '-');
}
return sb.ToString();
}
public static bool IPMatchCIDR(string cidr, IPAddress ip)
{
if (ip == null || ip.AddressFamily == AddressFamily.InterNetworkV6)
{
return false; //Just worry about IPv4 for now
}
/*
string[] str = cidr.Split( '/' );
if ( str.Length != 2 )
return false;
/* **************************************************
IPAddress cidrPrefix;
if ( !IPAddress.TryParse( str[0], out cidrPrefix ) )
return false;
* */
/*
string[] dotSplit = str[0].Split( '.' );
if ( dotSplit.Length != 4 ) //At this point and time, and for speed sake, we'll only worry about IPv4
return false;
byte[] bytes = new byte[4];
for ( int i = 0; i < 4; i++ )
{
byte.TryParse( dotSplit[i], out bytes[i] );
}
uint cidrPrefix = OrderedAddressValue( bytes );
int cidrLength = Utility.ToInt32( str[1] );
//The below solution is the fastest solution of the three
*/
var bytes = new byte[4];
var split = cidr.Split('.');
var cidrBits = false;
var cidrLength = 0;
for (var i = 0; i < 4; i++)
{
var part = 0;
var partBase = 10;
var pattern = split[i];
for (var j = 0; j < pattern.Length; j++)
{
var c = pattern[j];
if (c == 'x' || c == 'X')
{
partBase = 16;
}
else if (c >= '0' && c <= '9')
{
var offset = c - '0';
if (cidrBits)
{
cidrLength *= partBase;
cidrLength += offset;
}
else
{
part *= partBase;
part += offset;
}
}
else if (c >= 'a' && c <= 'f')
{
var offset = 10 + (c - 'a');
if (cidrBits)
{
cidrLength *= partBase;
cidrLength += offset;
}
else
{
part *= partBase;
part += offset;
}
}
else if (c >= 'A' && c <= 'F')
{
var offset = 10 + (c - 'A');
if (cidrBits)
{
cidrLength *= partBase;
cidrLength += offset;
}
else
{
part *= partBase;
part += offset;
}
}
else if (c == '/')
{
if (cidrBits || i != 3) //If there's two '/' or the '/' isn't in the last byte
{
return false;
}
partBase = 10;
cidrBits = true;
}
else
{
return false;
}
}
bytes[i] = (byte)part;
}
var cidrPrefix = OrderedAddressValue(bytes);
return IPMatchCIDR(cidrPrefix, ip, cidrLength);
}
public static bool IPMatchCIDR(IPAddress cidrPrefix, IPAddress ip, int cidrLength)
{
if (cidrPrefix == null || ip == null || cidrPrefix.AddressFamily == AddressFamily.InterNetworkV6)
//Ignore IPv6 for now
{
return false;
}
var cidrValue = SwapUnsignedInt((uint)GetLongAddressValue(cidrPrefix));
var ipValue = SwapUnsignedInt((uint)GetLongAddressValue(ip));
return IPMatchCIDR(cidrValue, ipValue, cidrLength);
}
public static bool IPMatchCIDR(uint cidrPrefixValue, IPAddress ip, int cidrLength)
{
if (ip == null || ip.AddressFamily == AddressFamily.InterNetworkV6)
{
return false;
}
var ipValue = SwapUnsignedInt((uint)GetLongAddressValue(ip));
return IPMatchCIDR(cidrPrefixValue, ipValue, cidrLength);
}
public static bool IPMatchCIDR(uint cidrPrefixValue, uint ipValue, int cidrLength)
{
if (cidrLength <= 0 || cidrLength >= 32) //if invalid cidr Length, just compare IPs
{
return cidrPrefixValue == ipValue;
}
var mask = UInt32.MaxValue << 32 - cidrLength;
return (cidrPrefixValue & mask) == (ipValue & mask);
}
private static uint OrderedAddressValue(byte[] bytes)
{
if (bytes.Length != 4)
{
return 0;
}
return (uint)((bytes[0] << 0x18) | (bytes[1] << 0x10) | (bytes[2] << 8) | bytes[3]) & (0xffffffff);
}
private static uint SwapUnsignedInt(uint source)
{
return ((source & 0x000000FF) << 0x18) | ((source & 0x0000FF00) << 8) | ((source & 0x00FF0000) >> 8) |
((source & 0xFF000000) >> 0x18);
}
public static bool TryConvertIPv6toIPv4(ref IPAddress address)
{
if (!Socket.OSSupportsIPv6 || address.AddressFamily == AddressFamily.InterNetwork)
{
return true;
}
var addr = address.GetAddressBytes();
if (addr.Length == 16) //sanity 0 - 15 //10 11 //12 13 14 15
{
if (addr[10] != 0xFF || addr[11] != 0xFF)
{
return false;
}
for (var i = 0; i < 10; i++)
{
if (addr[i] != 0)
{
return false;
}
}
var v4Addr = new byte[4];
for (var i = 0; i < 4; i++)
{
v4Addr[i] = addr[12 + i];
}
address = new IPAddress(v4Addr);
return true;
}
return false;
}
public static bool IPMatch(string val, IPAddress ip, ref bool valid)
{
valid = true;
var split = val.Split('.');
for (var i = 0; i < 4; ++i)
{
int lowPart, highPart;
if (i >= split.Length)
{
lowPart = 0;
highPart = 255;
}
else
{
var pattern = split[i];
if (pattern == "*")
{
lowPart = 0;
highPart = 255;
}
else
{
lowPart = 0;
highPart = 0;
var highOnly = false;
var lowBase = 10;
var highBase = 10;
for (var j = 0; j < pattern.Length; ++j)
{
var c = pattern[j];
if (c == '?')
{
if (!highOnly)
{
lowPart *= lowBase;
lowPart += 0;
}
highPart *= highBase;
highPart += highBase - 1;
}
else if (c == '-')
{
highOnly = true;
highPart = 0;
}
else if (c == 'x' || c == 'X')
{
lowBase = 16;
highBase = 16;
}
else if (c >= '0' && c <= '9')
{
var offset = c - '0';
if (!highOnly)
{
lowPart *= lowBase;
lowPart += offset;
}
highPart *= highBase;
highPart += offset;
}
else if (c >= 'a' && c <= 'f')
{
var offset = 10 + (c - 'a');
if (!highOnly)
{
lowPart *= lowBase;
lowPart += offset;
}
highPart *= highBase;
highPart += offset;
}
else if (c >= 'A' && c <= 'F')
{
var offset = 10 + (c - 'A');
if (!highOnly)
{
lowPart *= lowBase;
lowPart += offset;
}
highPart *= highBase;
highPart += offset;
}
else
{
valid = false; //high & lowpart would be 0 if it got to here.
}
}
}
}
int b = (byte)(GetAddressValue(ip) >> (i * 8));
if (b < lowPart || b > highPart)
{
return false;
}
}
return true;
}
public static bool IPMatchClassC(IPAddress ip1, IPAddress ip2)
{
return (GetAddressValue(ip1) & 0xFFFFFF) == (GetAddressValue(ip2) & 0xFFFFFF);
}
public static int InsensitiveCompare(string first, string second)
{
return Insensitive.Compare(first, second);
}
public static bool InsensitiveStartsWith(string first, string second)
{
return Insensitive.StartsWith(first, second);
}
#region To[Something]
public static bool ToBoolean(string value)
{
Boolean.TryParse(value, out var b);
return b;
}
public static double ToDouble(string value)
{
Double.TryParse(value, out var d);
return d;
}
public static TimeSpan ToTimeSpan(string value)
{
TimeSpan.TryParse(value, out var t);
return t;
}
public static int ToInt32(string value)
{
int i;
if (value.StartsWith("0x"))
{
Int32.TryParse(value.Substring(2), NumberStyles.HexNumber, null, out i);
}
else
{
Int32.TryParse(value, out i);
}
return i;
}
public static long ToInt64(string value)
{
long i;
if (value.StartsWith("0x"))
Int64.TryParse(value.Substring(2), NumberStyles.HexNumber, null, out i);
else
Int64.TryParse(value, out i);
return i;
}
#endregion
#region Get[Something]
public static double GetXMLDouble(string doubleString, double defaultValue)
{
try
{
return XmlConvert.ToDouble(doubleString);
}
catch
{
if (Double.TryParse(doubleString, out var val))
{
return val;
}
return defaultValue;
}
}
public static int GetXMLInt32(string intString, int defaultValue)
{
try
{
return XmlConvert.ToInt32(intString);
}
catch
{
if (Int32.TryParse(intString, out var val))
{
return val;
}
return defaultValue;
}
}
public static DateTime GetXMLDateTime(string dateTimeString, DateTime defaultValue)
{
try
{
return XmlConvert.ToDateTime(dateTimeString, XmlDateTimeSerializationMode.Utc);
}
catch
{
if (DateTime.TryParse(dateTimeString, out var d))
{
return d;
}
return defaultValue;
}
}
public static DateTimeOffset GetXMLDateTimeOffset(string dateTimeOffsetString, DateTimeOffset defaultValue)
{
try
{
return XmlConvert.ToDateTimeOffset(dateTimeOffsetString);
}
catch
{
if (DateTimeOffset.TryParse(dateTimeOffsetString, out var d))
{
return d;
}
return defaultValue;
}
}
public static TimeSpan GetXMLTimeSpan(string timeSpanString, TimeSpan defaultValue)
{
try
{
return XmlConvert.ToTimeSpan(timeSpanString);
}
catch
{
return defaultValue;
}
}
public static string GetAttribute(XmlElement node, string attributeName)
{
return GetAttribute(node, attributeName, null);
}
public static string GetAttribute(XmlElement node, string attributeName, string defaultValue)
{
if (node == null)
{
return defaultValue;
}
var attr = node.Attributes[attributeName];
if (attr == null)
{
return defaultValue;
}
return attr.Value;
}
public static string GetText(XmlElement node, string defaultValue)
{
if (node == null)
{
return defaultValue;
}
return node.InnerText;
}
public static int GetAddressValue(IPAddress address)
{
#pragma warning disable 618
return (int)address.Address;
#pragma warning restore 618
}
public static long GetLongAddressValue(IPAddress address)
{
#pragma warning disable 618
return address.Address;
#pragma warning restore 618
}
#endregion
#region In[...]Range
public static bool InRange(Point3D p1, Point3D p2, int range)
{
return (p1.m_X >= (p2.m_X - range)) && (p1.m_X <= (p2.m_X + range)) && (p1.m_Y >= (p2.m_Y - range)) &&
(p1.m_Y <= (p2.m_Y + range));
}
public static bool InUpdateRange(Point3D p1, Point3D p2)
{
var range = Core.GlobalUpdateRange;
return (p1.m_X >= (p2.m_X - range)) && (p1.m_X <= (p2.m_X + range)) && (p1.m_Y >= (p2.m_Y - range)) &&
(p1.m_Y <= (p2.m_Y + range));
}
public static bool InUpdateRange(Point2D p1, Point2D p2)
{
var range = Core.GlobalUpdateRange;
return (p1.m_X >= (p2.m_X - range)) && (p1.m_X <= (p2.m_X + range)) && (p1.m_Y >= (p2.m_Y - range)) &&
(p1.m_Y <= (p2.m_Y + range));
}
public static bool InUpdateRange(Mobile m, IPoint3D p)
{
return InUpdateRange(m, m, p);
}
public static bool InUpdateRange(Mobile m, IPoint3D p1, IPoint3D p2)
{
var range = Core.GlobalUpdateRange;
if (m.NetState != null)
{
range = m.NetState.UpdateRange;
}
if (p1 is Item)
{
p1 = ((Item)p1).GetWorldLocation();
}
if (p2 is Item)
{
p2 = ((Item)p2).GetWorldLocation();
}
return (p1.X >= (p2.X - range)) && (p1.X <= (p2.X + range)) && (p1.Y >= (p2.Y - range)) && (p1.Y <= (p2.Y + range));
}
#endregion
public static Direction GetDirection(IPoint2D from, IPoint2D to)
{
var dx = to.X - from.X;
var dy = to.Y - from.Y;
var adx = Math.Abs(dx);
var ady = Math.Abs(dy);
if (adx >= ady * 3)
{
if (dx > 0)
{
return Direction.East;
}
else
{
return Direction.West;
}
}
else if (ady >= adx * 3)
{
if (dy > 0)
{
return Direction.South;
}
else
{
return Direction.North;
}
}
else if (dx > 0)
{
if (dy > 0)
{
return Direction.Down;
}
else
{
return Direction.Right;
}
}
else
{
if (dy > 0)
{
return Direction.Left;
}
else
{
return Direction.Up;
}
}
}
public static object GetArrayCap(Array array, int index)
{
return GetArrayCap(array, index, null);
}
public static object GetArrayCap(Array array, int index, object emptyValue)
{
if (array.Length > 0)
{
if (index < 0)
{
index = 0;
}
else if (index >= array.Length)
{
index = array.Length - 1;
}
return array.GetValue(index);
}
else
{
return emptyValue;
}
}
#region Random
/// <summary>
/// Enables or disables floating dice.
/// Floating dice uses a double to obtain a lower average value range.
/// Consistent average values for [1,000,000 x 1d6+0] rolls: [Integral: 3.50] [Floating: 2.25]
/// </summary>
public static bool FloatingDice = false;
//4d6+8 would be: Utility.Dice( 4, 6, 8 )
public static int Dice(int numDice, int numSides, int bonus)
{
return Dice(numDice, numSides, bonus, FloatingDice);
}
public static int Dice(int numDice, int numSides, int bonus, bool floating)
{
if (floating)
{
double min = numDice, max = min;
for (var i = 0; i < numDice; ++i)
{
max += Random(numSides);
}
return (int)Math.Round(RandomMinMax(min, max)) + bonus;
}
var total = 0;
for (var i = 0; i < numDice; ++i)
{
total += Random(numSides) + 1;
}
return total + bonus;
}
public static T RandomList<T>(params T[] list)
{
return list[RandomImpl.Next(list.Length)];
}
public static bool RandomBool()
{
return RandomImpl.NextBool();
}
#if MONO
public static TEnum RandomEnum<TEnum>() where TEnum : struct, IConvertible
#else
public static TEnum RandomEnum<TEnum>() where TEnum : Enum
#endif
{
if (Enum.GetValues(typeof(TEnum)) is TEnum[] values && values.Length > 0)
return RandomList(values);
return default(TEnum);
}
#if MONO
public static TEnum RandomMinMax<TEnum>(TEnum min, TEnum max) where TEnum : struct, IConvertible
#else
public static TEnum RandomMinMax<TEnum>(TEnum min, TEnum max) where TEnum : Enum
#endif
{
if (Enum.GetValues(typeof(TEnum)) is TEnum[] values && values.Length > 0)
{
var curIdx = -1;
var minIdx = -1;
var maxIdx = -1;
foreach (var val in values)
{
++curIdx;
if (Equals(val, min))
minIdx = curIdx;
else if (Equals(val, max))
maxIdx = curIdx;
}
if (minIdx == 0 && maxIdx == values.Length - 1)
return RandomList(values);
curIdx = -1;
if (minIdx >= 0)
{
if (minIdx == maxIdx)
curIdx = minIdx;
else if (maxIdx > minIdx)
curIdx = RandomMinMax(minIdx, maxIdx);
}
if (curIdx >= 0 && curIdx < values.Length)
return values[curIdx];
return RandomList(min, max);
}
return default(TEnum);
}
public static double RandomMinMax(double min, double max)
{
if (min > max)
{
var copy = min;
min = max;
max = copy;
}
else if (min == max)
{
return min;
}
return min + (RandomImpl.NextDouble() * (max - min));
}
public static int RandomMinMax(int min, int max)
{
if (min > max)
{
var copy = min;
min = max;
max = copy;
}
else if (min == max)
{
return min;
}
return min + RandomImpl.Next(max - min + 1);
}
public static int Random(int from, int count)
{
if (count == 0)
{
return from;
}
else if (count > 0)
{
return from + RandomImpl.Next(count);
}
else
{
return from - RandomImpl.Next(-count);
}
}
public static int Random(int count)
{
return RandomImpl.Next(count);
}
public static void RandomBytes(byte[] buffer)
{
RandomImpl.NextBytes(buffer);
}
public static double RandomDouble()
{
return RandomImpl.NextDouble();
}
#endregion
#region FixValues
public static void FixMin(ref int value, int min)
{
if (value < min)
value = min;
}
public static void FixMin(ref double value, double min)
{
if (value < min)
value = min;
}
public static void FixMax(ref int value, int max)
{
if (value > max)
value = max;
}
public static void FixMax(ref double value, double max)
{
if (value > max)
value = max;
}
public static void FixMinMax(ref int value, int min, int max)
{
FixMin(ref value, min);
FixMax(ref value, max);
}
public static void FixMinMax(ref double value, double min, double max)
{
FixMin(ref value, min);
FixMax(ref value, max);
}
#endregion
#region Random Hues
/// <summary>
/// Random pink, blue, green, orange, red or yellow hue
/// </summary>
public static int RandomNondyedHue()
{
switch (Random(6))
{
case 0:
return RandomPinkHue();
case 1:
return RandomBlueHue();
case 2:
return RandomGreenHue();
case 3:
return RandomOrangeHue();
case 4:
return RandomRedHue();
case 5:
return RandomYellowHue();
}
return 0;
}
/// <summary>
/// Random hue in the range 1201-1254
/// </summary>
public static int RandomPinkHue()
{
return Random(1201, 54);
}
/// <summary>
/// Random hue in the range 1301-1354
/// </summary>
public static int RandomBlueHue()
{
return Random(1301, 54);
}
/// <summary>
/// Random hue in the range 1401-1454
/// </summary>
public static int RandomGreenHue()
{
return Random(1401, 54);
}
/// <summary>
/// Random hue in the range 1501-1554
/// </summary>
public static int RandomOrangeHue()
{
return Random(1501, 54);
}
/// <summary>
/// Random hue in the range 1601-1654
/// </summary>
public static int RandomRedHue()
{
return Random(1601, 54);
}
/// <summary>
/// Random hue in the range 1701-1754
/// </summary>
public static int RandomYellowHue()
{
return Random(1701, 54);
}
/// <summary>
/// Random hue in the range 1801-1908
/// </summary>
public static int RandomNeutralHue()
{
return Random(1801, 108);
}
/// <summary>
/// Random hue in the range 2001-2018
/// </summary>
public static int RandomSnakeHue()
{
return Random(2001, 18);
}
/// <summary>
/// Random hue in the range 2101-2130
/// </summary>
public static int RandomBirdHue()
{
return Random(2101, 30);
}
/// <summary>
/// Random hue in the range 2201-2224
/// </summary>
public static int RandomSlimeHue()
{
return Random(2201, 24);
}
/// <summary>
/// Random hue in the range 2301-2318
/// </summary>
public static int RandomAnimalHue()
{
return Random(2301, 18);
}
/// <summary>
/// Random hue in the range 2401-2430
/// </summary>
public static int RandomMetalHue()
{
return Random(2401, 30);
}
public static int ClipDyedHue(int hue)
{
if (hue < 2)
{
return 2;
}
else if (hue > 1001)
{
return 1001;
}
else
{
return hue;
}
}
/// <summary>
/// Random hue in the range 2-1001
/// </summary>
public static int RandomDyedHue()
{
return Random(2, 1000);
}
/// <summary>
/// Random hue from 0x62, 0x71, 0x03, 0x0D, 0x13, 0x1C, 0x21, 0x30, 0x37, 0x3A, 0x44, 0x59
/// </summary>
public static int RandomBrightHue()
{
if (RandomDouble() < 0.1)
{
return RandomList(0x62, 0x71);
}
return RandomList(0x03, 0x0D, 0x13, 0x1C, 0x21, 0x30, 0x37, 0x3A, 0x44, 0x59);
}
//[Obsolete( "Depreciated, use the methods for the Mobile's race", false )]
public static int ClipSkinHue(int hue)
{
if (hue < 1002)
{
return 1002;
}
else if (hue > 1058)
{
return 1058;
}
else
{
return hue;
}
}
//[Obsolete( "Depreciated, use the methods for the Mobile's race", false )]
public static int RandomSkinHue()
{
return Random(1002, 57) | 0x8000;
}
//[Obsolete( "Depreciated, use the methods for the Mobile's race", false )]
public static int ClipHairHue(int hue)
{
if (hue < 1102)
{
return 1102;
}
else if (hue > 1149)
{
return 1149;
}
else
{
return hue;
}
}
//[Obsolete( "Depreciated, use the methods for the Mobile's race", false )]
public static int RandomHairHue()
{
return Random(1102, 48);
}
#endregion
private static readonly SkillName[] m_AllSkills = new[]
{
SkillName.Alchemy, SkillName.Anatomy, SkillName.AnimalLore, SkillName.ItemID, SkillName.ArmsLore, SkillName.Parry,
SkillName.Begging, SkillName.Blacksmith, SkillName.Fletching, SkillName.Peacemaking, SkillName.Camping,
SkillName.Carpentry, SkillName.Cartography, SkillName.Cooking, SkillName.DetectHidden, SkillName.Discordance,
SkillName.EvalInt, SkillName.Healing, SkillName.Fishing, SkillName.Forensics, SkillName.Herding, SkillName.Hiding,
SkillName.Provocation, SkillName.Inscribe, SkillName.Lockpicking, SkillName.Magery, SkillName.MagicResist,
SkillName.Tactics, SkillName.Snooping, SkillName.Musicianship, SkillName.Poisoning, SkillName.Archery,
SkillName.SpiritSpeak, SkillName.Stealing, SkillName.Tailoring, SkillName.AnimalTaming, SkillName.TasteID,
SkillName.Tinkering, SkillName.Tracking, SkillName.Veterinary, SkillName.Swords, SkillName.Macing, SkillName.Fencing,
SkillName.Wrestling, SkillName.Lumberjacking, SkillName.Mining, SkillName.Meditation, SkillName.Stealth,
SkillName.RemoveTrap, SkillName.Necromancy, SkillName.Focus, SkillName.Chivalry, SkillName.Bushido,
SkillName.Ninjitsu, SkillName.Spellweaving, SkillName.Mysticism, SkillName.Imbuing, SkillName.Throwing
};
private static readonly SkillName[] m_CombatSkills = new[]
{SkillName.Archery, SkillName.Swords, SkillName.Macing, SkillName.Fencing, SkillName.Wrestling};
private static readonly SkillName[] m_CraftSkills = new[]
{
SkillName.Alchemy, SkillName.Blacksmith, SkillName.Fletching, SkillName.Carpentry, SkillName.Cartography,
SkillName.Cooking, SkillName.Inscribe, SkillName.Tailoring, SkillName.Tinkering
};
public static SkillName RandomSkill()
{
return m_AllSkills[Random(m_AllSkills.Length)];
}
public static SkillName RandomCombatSkill()
{
return m_CombatSkills[Random(m_CombatSkills.Length)];
}
public static SkillName RandomCraftSkill()
{
return m_CraftSkills[Random(m_CraftSkills.Length)];
}
public static void FixPoints(ref Point3D top, ref Point3D bottom)
{
if (bottom.m_X < top.m_X)
{
var swap = top.m_X;
top.m_X = bottom.m_X;
bottom.m_X = swap;
}
if (bottom.m_Y < top.m_Y)
{
var swap = top.m_Y;
top.m_Y = bottom.m_Y;
bottom.m_Y = swap;
}
if (bottom.m_Z < top.m_Z)
{
var swap = top.m_Z;
top.m_Z = bottom.m_Z;
bottom.m_Z = swap;
}
}
public static ArrayList BuildArrayList(IEnumerable enumerable)
{
var e = enumerable.GetEnumerator();
var list = new ArrayList();
while (e.MoveNext())
{
list.Add(e.Current);
}
return list;
}
public static bool RangeCheck(IPoint2D p1, IPoint2D p2, int range)
{
return (p1.X >= (p2.X - range)) && (p1.X <= (p2.X + range)) && (p1.Y >= (p2.Y - range)) && (p2.Y <= (p2.Y + range));
}
public static void FormatBuffer(TextWriter output, Stream input, int length)
{
output.WriteLine(" 0 1 2 3 4 5 6 7 8 9 A B C D E F");
output.WriteLine(" -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --");
var byteIndex = 0;
var whole = length >> 4;
var rem = length & 0xF;
for (var i = 0; i < whole; ++i, byteIndex += 16)
{
var bytes = new StringBuilder(49);
var chars = new StringBuilder(16);
for (var j = 0; j < 16; ++j)
{
var c = input.ReadByte();
bytes.Append(c.ToString("X2"));
if (j != 7)
{
bytes.Append(' ');
}
else
{
bytes.Append(" ");
}
if (c >= 0x20 && c < 0x80)
{
chars.Append((char)c);
}
else
{
chars.Append('.');
}
}
output.Write(byteIndex.ToString("X4"));
output.Write(" ");
output.Write(bytes.ToString());
output.Write(" ");
output.WriteLine(chars.ToString());
}
if (rem != 0)
{
var bytes = new StringBuilder(49);
var chars = new StringBuilder(rem);
for (var j = 0; j < 16; ++j)
{
if (j < rem)
{
var c = input.ReadByte();
bytes.Append(c.ToString("X2"));
if (j != 7)
{
bytes.Append(' ');
}
else
{
bytes.Append(" ");
}
if (c >= 0x20 && c < 0x80)
{
chars.Append((char)c);
}
else
{
chars.Append('.');
}
}
else
{
bytes.Append(" ");
}
}
output.Write(byteIndex.ToString("X4"));
output.Write(" ");
output.Write(bytes.ToString());
output.Write(" ");
output.WriteLine(chars.ToString());
}
}
public static string FormatDelegate(Delegate callback)
{
if (callback == null)
{
return "null";
}
if (callback.Method.DeclaringType == null)
{
return callback.Method.Name;
}
return String.Format("{0}.{1}", callback.Method.DeclaringType.FullName, callback.Method.Name);
}
private static readonly Stack<ConsoleColor> m_ConsoleColors = new Stack<ConsoleColor>();
public static void WriteConsoleColor(ConsoleColor color, string format, params object[] args)
{
lock (((ICollection)m_ConsoleColors).SyncRoot)
{
PushColor(color);
Console.WriteLine(format, args);
PopColor();
}
}
public static void WriteConsoleColor(ConsoleColor color, string str)
{
lock (((ICollection)m_ConsoleColors).SyncRoot)
{
PushColor(color);
Console.WriteLine(str);
PopColor();
}
}
public static void PushColor(ConsoleColor color)
{
try
{
lock (((ICollection)m_ConsoleColors).SyncRoot)
{
m_ConsoleColors.Push(Console.ForegroundColor);
Console.ForegroundColor = color;
}
}
catch (Exception e)
{
Diagnostics.ExceptionLogging.LogException(e);
}
}
public static void PopColor()
{
try
{
lock (((ICollection)m_ConsoleColors).SyncRoot)
{
Console.ForegroundColor = m_ConsoleColors.Pop();
}
}
catch (Exception e)
{
Diagnostics.ExceptionLogging.LogException(e);
}
}
public static bool NumberBetween(double num, int bound1, int bound2, double allowance)
{
if (bound1 > bound2)
{
var i = bound1;
bound1 = bound2;
bound2 = i;
}
return num < bound2 + allowance && num > bound1 - allowance;
}
public static double GetDistanceToSqrt(Point3D p1, Point3D p2)
{
var xDelta = p1.X - p2.X;
var yDelta = p1.Y - p2.Y;
return Math.Sqrt((xDelta * xDelta) + (yDelta * yDelta));
}
public static void AssignRandomHair(Mobile m)
{
AssignRandomHair(m, true);
}
public static void AssignRandomHair(Mobile m, int hue)
{
m.HairItemID = m.Race.RandomHair(m);
m.HairHue = hue;
}
public static void AssignRandomHair(Mobile m, bool randomHue)
{
m.HairItemID = m.Race.RandomHair(m);
if (randomHue)
{
m.HairHue = m.Race.RandomHairHue();
}
}
public static void AssignRandomFacialHair(Mobile m)
{
AssignRandomFacialHair(m, true);
}
public static void AssignRandomFacialHair(Mobile m, int hue)
{
m.FacialHairItemID = m.Race.RandomFacialHair(m);
m.FacialHairHue = hue;
}
public static void AssignRandomFacialHair(Mobile m, bool randomHue)
{
m.FacialHairItemID = m.Race.RandomFacialHair(m);
if (randomHue)
{
m.FacialHairHue = m.Race.RandomHairHue();
}
}
public static List<TOutput> CastConvertList<TInput, TOutput>(List<TInput> list) where TOutput : TInput
{
return list.ConvertAll(delegate (TInput value) { return (TOutput)value; });
}
public static List<TOutput> SafeConvertList<TInput, TOutput>(List<TInput> list) where TOutput : class
{
var output = new List<TOutput>(list.Capacity);
for (var i = 0; i < list.Count; i++)
{
var t = list[i] as TOutput;
if (t != null)
{
output.Add(t);
}
}
return output;
}
public static string RemoveHtml(string str)
{
return str.Replace("<", "").Replace(">", "").Trim();
}
public static bool IsNumeric(string str)
{
return !Regex.IsMatch(str, "[^0-9]");
}
public static bool IsAlpha(string str)
{
return !Regex.IsMatch(str, "[^a-z]", RegexOptions.IgnoreCase);
}
public static bool IsAlphaNumeric(string str)
{
return !Regex.IsMatch(str, "[^a-z0-9]", RegexOptions.IgnoreCase);
}
}
public static class ColUtility
{
public static void Free<T>(List<T> l)
{
if (l == null)
return;
l.Clear();
l.TrimExcess();
}
public static void ForEach<T>(IEnumerable<T> list, Action<T> action)
{
if (list == null || action == null)
return;
var l = list.ToList();
foreach (var o in l)
action(o);
Free(l);
}
public static void ForEach<TKey, TValue>(
IDictionary<TKey, TValue> dictionary, Action<KeyValuePair<TKey, TValue>> action)
{
if (dictionary == null || dictionary.Count == 0 || action == null)
return;
var l = dictionary.ToList();
foreach (var kvp in l)
action(kvp);
Free(l);
}
public static void ForEach<TKey, TValue>(IDictionary<TKey, TValue> dictionary, Action<TKey, TValue> action)
{
if (dictionary == null || dictionary.Count == 0 || action == null)
return;
var l = dictionary.ToList();
foreach (var kvp in l)
action(kvp.Key, kvp.Value);
Free(l);
}
public static void For<T>(IEnumerable<T> list, Action<int, T> action)
{
if (list == null || action == null)
return;
var l = list.ToList();
for (var i = 0; i < l.Count; i++)
action(i, l[i]);
Free(l);
}
public static void For<TKey, TValue>(IDictionary<TKey, TValue> list, Action<int, TKey, TValue> action)
{
if (list == null || action == null)
return;
var l = list.ToList();
for (var i = 0; i < l.Count; i++)
action(i, l[i].Key, l[i].Value);
Free(l);
}
public static void IterateReverse<T>(this T[] list, Action<T> action)
{
if (list == null || action == null)
{
return;
}
var i = list.Length;
while (--i >= 0)
{
if (i < list.Length)
{
action(list[i]);
}
}
}
public static void IterateReverse<T>(this List<T> list, Action<T> action)
{
if (list == null || action == null)
{
return;
}
var i = list.Count;
while (--i >= 0)
{
if (i < list.Count)
{
action(list[i]);
}
}
}
public static void IterateReverse<T>(this IEnumerable<T> list, Action<T> action)
{
if (list == null || action == null)
{
return;
}
if (list is T[])
{
IterateReverse((T[])list, action);
return;
}
if (list is List<T>)
{
IterateReverse((List<T>)list, action);
return;
}
var toList = list.ToList();
foreach (var o in toList)
{
action(o);
}
Free(toList);
}
public static void SafeDelete<T>(List<T> list)
{
SafeDelete(list, null);
}
/// <summary>
/// Safely deletes any entities based on predicate from a list that by deleting such entity would cause the collection to be modified.
/// ie item.Items or mobile.Items. Omitting the predicate will delete all items in the collection.
/// </summary>
/// <param name="list"></param>
/// <param name="predicate"></param>
public static void SafeDelete<T>(List<T> list, Func<T, bool> predicate)
{
if (list == null)
{
return;
}
var i = list.Count;
while (--i >= 0)
{
if (i < list.Count)
{
var entity = list[i] as IEntity;
if (entity != null && !entity.Deleted && (predicate == null || predicate((T)entity)))
{
entity.Delete();
}
}
}
}
public static void Shuffle<T>(List<T> list)
{
if (list == null || list.Count < 2)
{
return;
}
for (var i = 0; i < list.Count * 2; i++)
{
var select = list[0];
list.RemoveAt(0);
list.Insert(Utility.RandomMinMax(0, list.Count - 1), select);
}
}
}
}