Ported .Net Core commits:
hondacrx: - Initial commit: Switch to .Net Core 2.0 - Fix build and removed not needed files Fabi: - Updated solution platforms. - Changed folder structure. - Change library target framework to netstandard2.0. - Updated solution platforms again... - Removed windows specific kernel32 function usage (Ctrl-C handler).
This commit is contained in:
@@ -0,0 +1,176 @@
|
||||
/*
|
||||
* Copyright (C) 2012-2017 CypherCore <http://github.com/CypherCore>
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
using System.Linq;
|
||||
|
||||
namespace System.Collections.Generic
|
||||
{
|
||||
public static class CollectionExtensions
|
||||
{
|
||||
public static bool Empty<TValue>(this ICollection<TValue> collection)
|
||||
{
|
||||
return collection.Count == 0;
|
||||
}
|
||||
|
||||
public static bool Empty<Tkey, TValue>(this IDictionary<Tkey, TValue> dictionary)
|
||||
{
|
||||
return dictionary.Count == 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the entry in this list at the given index, or the default value of the element
|
||||
/// type if the index was out of bounds.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of the elements in the list.</typeparam>
|
||||
/// <param name="list">The list to retrieve from.</param>
|
||||
/// <param name="index">The index to try to retrieve at.</param>
|
||||
/// <returns>The value, or the default value of the element type.</returns>
|
||||
public static T LookupByIndex<T>(this IList<T> list, int index)
|
||||
{
|
||||
return index >= list.Count ? default(T) : list[index];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the entry in this dictionary at the given key, or the default value of the key
|
||||
/// if none.
|
||||
/// </summary>
|
||||
/// <typeparam name="TKey">The key type.</typeparam>
|
||||
/// <typeparam name="TValue">The value type.</typeparam>
|
||||
/// <param name="dict">The dictionary to operate on.</param>
|
||||
/// <param name="key">The key of the element to retrieve.</param>
|
||||
/// <returns>The value (if any).</returns>
|
||||
public static TValue LookupByKey<TKey, TValue>(this IDictionary<TKey, TValue> dict, object key)
|
||||
{
|
||||
TValue val;
|
||||
TKey newkey = (TKey)Convert.ChangeType(key, typeof(TKey));
|
||||
return dict.TryGetValue(newkey, out val) ? val : default(TValue);
|
||||
}
|
||||
public static TValue LookupByKey<TKey, TValue>(this IDictionary<TKey, TValue> dict, TKey key)
|
||||
{
|
||||
TValue val;
|
||||
return dict.TryGetValue(key, out val) ? val : default(TValue);
|
||||
}
|
||||
public static KeyValuePair<TKey, TValue> Find<TKey, TValue>(this IDictionary<TKey, TValue> dict, TKey key)
|
||||
{
|
||||
return new KeyValuePair<TKey, TValue>(key, dict[key]);
|
||||
}
|
||||
|
||||
public static bool ContainsKey<TKey, TValue>(this IDictionary<TKey, TValue> dict, object key)
|
||||
{
|
||||
TKey newkey = (TKey)Convert.ChangeType(key, typeof(TKey));
|
||||
return dict.ContainsKey(newkey);
|
||||
}
|
||||
|
||||
public static void RemoveAll<T>(this List<T> collection, ICheck<T> check)
|
||||
{
|
||||
collection.RemoveAll(check.Invoke);
|
||||
}
|
||||
|
||||
public static IEnumerable<T> Shuffle<T>(this IEnumerable<T> source)
|
||||
{
|
||||
return source.OrderBy(x => Guid.NewGuid());
|
||||
}
|
||||
|
||||
public static void Swap<T>(this T[] array, int position1, int position2)
|
||||
{
|
||||
//
|
||||
// Swaps elements in an array. Doesn't need to return a reference.
|
||||
//
|
||||
T temp = array[position1]; // Copy the first position's element
|
||||
array[position1] = array[position2]; // Assign to the second element
|
||||
array[position2] = temp; // Assign to the first element
|
||||
}
|
||||
|
||||
public static void Resize<T>(this List<T> list, uint size)
|
||||
{
|
||||
int cur = list.Count;
|
||||
if (size < cur)
|
||||
list.RemoveRange((int)size, cur - (int)size);
|
||||
}
|
||||
|
||||
public static void RandomResize<T>(this IList<T> list, uint size)
|
||||
{
|
||||
int listSize = list.Count;
|
||||
|
||||
while (listSize > size)
|
||||
{
|
||||
list.RemoveAt(RandomHelper.IRand(0, listSize));
|
||||
--listSize;
|
||||
}
|
||||
}
|
||||
|
||||
public static void RandomResize<T>(this ICollection<T> list, Predicate<T> predicate, uint size)
|
||||
{
|
||||
List<T> listCopy = new List<T>();
|
||||
foreach (var obj in list)
|
||||
if (predicate(obj))
|
||||
listCopy.Add(obj);
|
||||
|
||||
if (size != 0)
|
||||
listCopy.Resize(size);
|
||||
|
||||
list = listCopy;
|
||||
}
|
||||
|
||||
public static T SelectRandom<T>(this IEnumerable<T> source)
|
||||
{
|
||||
return source.SelectRandom(1).Single();
|
||||
}
|
||||
|
||||
public static IEnumerable<T> SelectRandom<T>(this IEnumerable<T> source, uint count)
|
||||
{
|
||||
return source.Shuffle().Take((int)count);
|
||||
}
|
||||
|
||||
public static T SelectRandomElementByWeight<T>(this IEnumerable<T> sequence, Func<T, float> weightSelector)
|
||||
{
|
||||
float totalWeight = sequence.Sum(weightSelector);
|
||||
// The weight we are after...
|
||||
float itemWeightIndex = (float)RandomHelper.NextDouble() * totalWeight;
|
||||
float currentWeightIndex = 0;
|
||||
|
||||
foreach (var item in from weightedItem in sequence select new { Value = weightedItem, Weight = weightSelector(weightedItem) })
|
||||
{
|
||||
currentWeightIndex += item.Weight;
|
||||
|
||||
// If we've hit or passed the weight we are after for this item then it's the one we want....
|
||||
if (currentWeightIndex >= itemWeightIndex)
|
||||
return item.Value;
|
||||
|
||||
}
|
||||
|
||||
return default(T);
|
||||
}
|
||||
|
||||
public static uint[] ToBlockRange(this BitSet array)
|
||||
{
|
||||
uint[] blockValues = new uint[array.Length / 32 + 1];
|
||||
array.CopyTo(blockValues, 0);
|
||||
return blockValues;
|
||||
}
|
||||
}
|
||||
|
||||
public interface ICheck<T>
|
||||
{
|
||||
bool Invoke(T obj);
|
||||
}
|
||||
|
||||
public interface IDoWork<T>
|
||||
{
|
||||
void Invoke(T obj);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,370 @@
|
||||
/*
|
||||
* Copyright (C) 2012-2017 CypherCore <http://github.com/CypherCore>
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Linq.Expressions;
|
||||
using System.Numerics;
|
||||
using System.Reflection;
|
||||
using System.Reflection.Emit;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace System
|
||||
{
|
||||
public static class Extensions
|
||||
{
|
||||
public static bool HasAnyFlag<T>(this T value, T flag) where T : struct
|
||||
{
|
||||
long lValue = Convert.ToInt64(value);
|
||||
long lFlag = Convert.ToInt64(flag);
|
||||
return (lValue & lFlag) != 0;
|
||||
}
|
||||
|
||||
public static string ToHexString(this byte[] byteArray)
|
||||
{
|
||||
return byteArray.Aggregate("", (current, b) => current + b.ToString("X2"));
|
||||
}
|
||||
|
||||
public static byte[] ToByteArray(this string str)
|
||||
{
|
||||
str = str.Replace(" ", String.Empty);
|
||||
|
||||
var res = new byte[str.Length / 2];
|
||||
for (int i = 0; i < res.Length; ++i)
|
||||
{
|
||||
string temp = String.Concat(str[i * 2], str[i * 2 + 1]);
|
||||
res[i] = Convert.ToByte(temp, 16);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
public static byte[] ToByteArray(this string value, char separator)
|
||||
{
|
||||
return Array.ConvertAll(value.Split(separator), s => byte.Parse(s));
|
||||
}
|
||||
|
||||
static uint LeftRotate(this uint value, int shiftCount)
|
||||
{
|
||||
return (value << shiftCount) | (value >> (0x20 - shiftCount));
|
||||
}
|
||||
|
||||
public static byte[] GenerateRandomKey(this byte[] s, int length)
|
||||
{
|
||||
var random = new Random((int)((uint)(Guid.NewGuid().GetHashCode() ^ 1 >> 89 << 2 ^ 42)).LeftRotate(13));
|
||||
var key = new byte[length];
|
||||
|
||||
for (int i = 0; i < length; i++)
|
||||
{
|
||||
int randValue = -1;
|
||||
|
||||
do
|
||||
{
|
||||
randValue = (int)((uint)random.Next(0xFF)).LeftRotate(1) ^ i;
|
||||
} while (randValue > 0xFF && randValue <= 0);
|
||||
|
||||
key[i] = (byte)randValue;
|
||||
}
|
||||
|
||||
return key;
|
||||
}
|
||||
|
||||
public static bool Compare(this byte[] b, byte[] b2)
|
||||
{
|
||||
for (int i = 0; i < b2.Length; i++)
|
||||
if (b[i] != b2[i])
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static byte[] Combine(this byte[] data, params byte[][] pData)
|
||||
{
|
||||
var combined = data;
|
||||
|
||||
foreach (var arr in pData)
|
||||
{
|
||||
var currentSize = combined.Length;
|
||||
|
||||
Array.Resize(ref combined, currentSize + arr.Length);
|
||||
|
||||
Buffer.BlockCopy(arr, 0, combined, currentSize, arr.Length);
|
||||
}
|
||||
|
||||
return combined;
|
||||
}
|
||||
|
||||
public static object[] Combine(this object[] data, params object[][] pData)
|
||||
{
|
||||
var combined = data;
|
||||
|
||||
foreach (var arr in pData)
|
||||
{
|
||||
var currentSize = combined.Length;
|
||||
|
||||
Array.Resize(ref combined, currentSize + arr.Length);
|
||||
|
||||
Array.Copy(arr, 0, combined, currentSize, arr.Length);
|
||||
}
|
||||
|
||||
return combined;
|
||||
}
|
||||
|
||||
public static BigInteger ToBigInteger<T>(this T value, bool isBigEndian = false)
|
||||
{
|
||||
var ret = BigInteger.Zero;
|
||||
|
||||
switch (typeof(T).Name)
|
||||
{
|
||||
case "Byte[]":
|
||||
var data = value as byte[];
|
||||
|
||||
if (isBigEndian)
|
||||
Array.Reverse(data);
|
||||
|
||||
ret = new BigInteger(data.Combine(new byte[] { 0 }));
|
||||
break;
|
||||
case "BigInteger":
|
||||
ret = (BigInteger)Convert.ChangeType(value, typeof(BigInteger));
|
||||
break;
|
||||
default:
|
||||
throw new NotSupportedException(string.Format("'{0}' conversion to 'BigInteger' not supported.", typeof(T).Name));
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
public static void Swap<T>(ref T left, ref T right)
|
||||
{
|
||||
T temp = left;
|
||||
left = right;
|
||||
right = temp;
|
||||
}
|
||||
|
||||
public static Func<object, object> CompileGetter(this FieldInfo field)
|
||||
{
|
||||
string methodName = field.ReflectedType.FullName + ".get_" + field.Name;
|
||||
DynamicMethod setterMethod = new DynamicMethod(methodName, typeof(object), new[] { typeof(object) }, true);
|
||||
ILGenerator gen = setterMethod.GetILGenerator();
|
||||
if (field.IsStatic)
|
||||
{
|
||||
gen.Emit(OpCodes.Ldsfld, field);
|
||||
gen.Emit(field.FieldType.IsClass ? OpCodes.Castclass : OpCodes.Box, field.FieldType);
|
||||
}
|
||||
else
|
||||
{
|
||||
gen.Emit(OpCodes.Ldarg_0);
|
||||
gen.Emit(OpCodes.Castclass, field.DeclaringType);
|
||||
gen.Emit(OpCodes.Ldfld, field);
|
||||
gen.Emit(field.FieldType.IsClass ? OpCodes.Castclass : OpCodes.Box, field.FieldType);
|
||||
}
|
||||
gen.Emit(OpCodes.Ret);
|
||||
return (Func<object, object>)setterMethod.CreateDelegate(typeof(Func<object, object>));
|
||||
}
|
||||
|
||||
public static Action<object, object> CompileSetter(this FieldInfo field)
|
||||
{
|
||||
string methodName = field.ReflectedType.FullName + ".set_" + field.Name;
|
||||
DynamicMethod setterMethod = new DynamicMethod(methodName, null, new[] { typeof(object), typeof(object) }, true);
|
||||
ILGenerator gen = setterMethod.GetILGenerator();
|
||||
if (field.IsStatic)
|
||||
{
|
||||
gen.Emit(OpCodes.Ldarg_1);
|
||||
gen.Emit(field.FieldType.IsClass ? OpCodes.Castclass : OpCodes.Unbox_Any, field.FieldType);
|
||||
gen.Emit(OpCodes.Stsfld, field);
|
||||
}
|
||||
else
|
||||
{
|
||||
gen.Emit(OpCodes.Ldarg_0);
|
||||
gen.Emit(OpCodes.Castclass, field.DeclaringType);
|
||||
gen.Emit(OpCodes.Ldarg_1);
|
||||
gen.Emit(field.FieldType.IsClass ? OpCodes.Castclass : OpCodes.Unbox_Any, field.FieldType);
|
||||
gen.Emit(OpCodes.Stfld, field);
|
||||
}
|
||||
gen.Emit(OpCodes.Ret);
|
||||
return (Action<object, object>)setterMethod.CreateDelegate(typeof(Action<object, object>));
|
||||
}
|
||||
|
||||
public static Func<T, object> GetGetter<T>(this FieldInfo fieldInfo)
|
||||
{
|
||||
var paramExpression = Expression.Parameter(typeof(T));
|
||||
var propertyExpression = Expression.Field(paramExpression, fieldInfo);
|
||||
var convertExpression = Expression.TypeAs(propertyExpression, typeof(object));
|
||||
|
||||
return Expression.Lambda<Func<T, object>>(convertExpression, paramExpression).Compile();
|
||||
}
|
||||
|
||||
public static Action<T, object> GetSetter<T>(this FieldInfo fieldInfo)
|
||||
{
|
||||
var paramExpression = Expression.Parameter(typeof(T));
|
||||
var propertyExpression = Expression.Field(paramExpression, fieldInfo);
|
||||
var valueExpression = Expression.Parameter(typeof(object));
|
||||
var convertExpression = Expression.Convert(valueExpression, fieldInfo.FieldType);
|
||||
var assignExpression = Expression.Assign(propertyExpression, convertExpression);
|
||||
|
||||
return Expression.Lambda<Action<T, object>>(assignExpression, paramExpression, valueExpression).Compile();
|
||||
}
|
||||
|
||||
public static uint[] SerializeObject<T>(this T obj)
|
||||
{
|
||||
//if (obj.GetType()<StructLayoutAttribute>() == null)
|
||||
//return null;
|
||||
|
||||
var size = Marshal.SizeOf(typeof(T));
|
||||
var ptr = Marshal.AllocHGlobal(size);
|
||||
byte[] array = new byte[size];
|
||||
|
||||
Marshal.StructureToPtr(obj, ptr, true);
|
||||
Marshal.Copy(ptr, array, 0, size);
|
||||
|
||||
Marshal.FreeHGlobal(ptr);
|
||||
|
||||
uint[] result = new uint[size / 4];
|
||||
Buffer.BlockCopy(array, 0, result, 0, array.Length);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public static List<T> DeserializeObjects<T>(this ICollection<uint> data)
|
||||
{
|
||||
List<T> list = new List<T>();
|
||||
|
||||
if (data.Count == 0)
|
||||
return list;
|
||||
|
||||
if (typeof(T).GetCustomAttribute<StructLayoutAttribute>() == null)
|
||||
return list;
|
||||
|
||||
byte[] result = new byte[data.Count * sizeof(uint)];
|
||||
Buffer.BlockCopy(data.ToArray(), 0, result, 0, result.Length);
|
||||
|
||||
var typeSize = Marshal.SizeOf(typeof(T));
|
||||
var objCount = data.Count / (typeSize / sizeof(uint));
|
||||
|
||||
for (var i = 0; i < objCount; ++i)
|
||||
{
|
||||
var ptr = Marshal.AllocHGlobal(typeSize);
|
||||
Marshal.Copy(result, typeSize * i, ptr, typeSize);
|
||||
list.Add((T)Marshal.PtrToStructure(ptr, typeof(T)));
|
||||
Marshal.FreeHGlobal(ptr);
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
#region Strings
|
||||
public static bool IsEmpty(this string str)
|
||||
{
|
||||
return string.IsNullOrEmpty(str);
|
||||
}
|
||||
|
||||
public static T ToEnum<T>(this string str) where T : struct
|
||||
{
|
||||
T value;
|
||||
if (!Enum.TryParse(str, out value))
|
||||
return default(T);
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
public static string ConvertFormatSyntax(this string str)
|
||||
{
|
||||
string pattern = @"(%\W*\d*[a-zA-Z]*)";
|
||||
|
||||
int count = 0;
|
||||
string result = Regex.Replace(str, pattern, m =>
|
||||
{
|
||||
return string.Concat("{", count++, "}");
|
||||
});
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public static bool Like(this string toSearch, string toFind)
|
||||
{
|
||||
return toSearch.ToLower().Contains(toFind.ToLower());
|
||||
}
|
||||
|
||||
public static bool IsNumber(this string str)
|
||||
{
|
||||
double value;
|
||||
return double.TryParse(str, out value);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region BinaryReader
|
||||
public static T ReadStruct<T>(this BinaryReader reader) where T : struct
|
||||
{
|
||||
byte[] data = reader.ReadBytes(Marshal.SizeOf(typeof(T)));
|
||||
GCHandle handle = GCHandle.Alloc(data, GCHandleType.Pinned);
|
||||
T returnObject = (T)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(T));
|
||||
|
||||
handle.Free();
|
||||
return returnObject;
|
||||
}
|
||||
|
||||
public static T ReadStruct<T>(this BinaryReader reader, uint offset) where T : struct
|
||||
{
|
||||
reader.BaseStream.Position = offset;
|
||||
byte[] data = reader.ReadBytes(Marshal.SizeOf(typeof(T)));
|
||||
GCHandle handle = GCHandle.Alloc(data, GCHandleType.Pinned);
|
||||
T returnObject = (T)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(T));
|
||||
|
||||
handle.Free();
|
||||
return returnObject;
|
||||
}
|
||||
|
||||
public static string ReadCString(this BinaryReader reader)
|
||||
{
|
||||
byte num;
|
||||
List<byte> temp = new List<byte>();
|
||||
|
||||
while ((num = reader.ReadByte()) != 0)
|
||||
temp.Add(num);
|
||||
|
||||
return Encoding.UTF8.GetString(temp.ToArray());
|
||||
}
|
||||
|
||||
public static string ReadString(this BinaryReader reader, int count)
|
||||
{
|
||||
var array = reader.ReadBytes(count);
|
||||
return Encoding.ASCII.GetString(array);
|
||||
}
|
||||
|
||||
public static string ReadStringFromChars(this BinaryReader reader, int count)
|
||||
{
|
||||
return new string(reader.ReadChars(count));
|
||||
}
|
||||
|
||||
public static byte[] ToByteArray(this BinaryReader reader)
|
||||
{
|
||||
var data = new byte[reader.BaseStream.Length];
|
||||
|
||||
long pos = reader.BaseStream.Position;
|
||||
reader.BaseStream.Seek(0, SeekOrigin.Begin);
|
||||
for (int i = 0; i < data.Length; i++)
|
||||
data[i] = (byte)reader.BaseStream.ReadByte();
|
||||
|
||||
reader.BaseStream.Seek(pos, SeekOrigin.Begin);
|
||||
return data;
|
||||
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,264 @@
|
||||
/*
|
||||
* Copyright (C) 2012-2017 CypherCore <http://github.com/CypherCore>
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
using Framework.Constants;
|
||||
using System;
|
||||
|
||||
public static class MathFunctions
|
||||
{
|
||||
public const float E = 2.71828f;
|
||||
public const float Log10E = 0.434294f;
|
||||
public const float Log2E = 1.4427f;
|
||||
public const float PI = 3.14159f;
|
||||
public const float PiOver2 = 1.5708f;
|
||||
public const float PiOver4 = 0.785398f;
|
||||
public const float TwoPi = 6.28319f;
|
||||
public const float Epsilon = 4.76837158203125E-7f;
|
||||
|
||||
public static float wrap(float t, float lo, float hi)
|
||||
{
|
||||
if ((t >= lo) && (t < hi))
|
||||
{
|
||||
return t;
|
||||
}
|
||||
|
||||
float interval = hi - lo;
|
||||
return (float)(t - interval * Math.Floor((t - lo) / interval));
|
||||
}
|
||||
|
||||
public static void Swap<T>(ref T lhs, ref T rhs)
|
||||
{
|
||||
T temp = lhs;
|
||||
lhs = rhs;
|
||||
rhs = temp;
|
||||
}
|
||||
|
||||
#region Clamp
|
||||
/// <summary>
|
||||
/// Clamp a <paramref name="value"/> to <paramref name="calmpedValue"/> if it is withon the <paramref name="tolerance"/> range.
|
||||
/// </summary>
|
||||
/// <param name="value">The value to clamp.</param>
|
||||
/// <param name="calmpedValue">The clamped value.</param>
|
||||
/// <param name="tolerance">The tolerance value.</param>
|
||||
/// <returns>
|
||||
/// Returns the clamped value.
|
||||
/// result = (tolerance > Abs(value-calmpedValue)) ? calmpedValue : value;
|
||||
/// </returns>
|
||||
public static float Clamp(float value, float calmpedValue, float tolerance)
|
||||
{
|
||||
return (tolerance > Math.Abs(value - calmpedValue)) ? calmpedValue : value;
|
||||
}
|
||||
/// <summary>
|
||||
/// Clamp a <paramref name="value"/> to <paramref name="calmpedValue"/> using the default tolerance value.
|
||||
/// </summary>
|
||||
/// <param name="value">The value to clamp.</param>
|
||||
/// <param name="calmpedValue">The clamped value.</param>
|
||||
/// <returns>
|
||||
/// Returns the clamped value.
|
||||
/// result = (EpsilonF > Abs(value-calmpedValue)) ? calmpedValue : value;
|
||||
/// </returns>
|
||||
/// <remarks><see cref="MathFunctions.EpsilonF"/> is used for tolerance.</remarks>
|
||||
public static float Clamp(float value, float calmpedValue)
|
||||
{
|
||||
return (Epsilon > Math.Abs(value - calmpedValue)) ? calmpedValue : value;
|
||||
}
|
||||
#endregion
|
||||
|
||||
static double eps(double a, double b)
|
||||
{
|
||||
double aa = Math.Abs(a) + 1.0;
|
||||
if (aa == double.PositiveInfinity)
|
||||
return double.Epsilon;
|
||||
else
|
||||
return double.Epsilon * aa;
|
||||
}
|
||||
|
||||
public static float lerp(float a, float b, float f)
|
||||
{
|
||||
return a + (b - a) * f;
|
||||
}
|
||||
|
||||
public static float DegToRad(float degrees)
|
||||
{
|
||||
return degrees * (2.0f * PI / 360.0f);
|
||||
}
|
||||
|
||||
#region Fuzzy
|
||||
public static bool fuzzyEq(double a, double b)
|
||||
{
|
||||
return (a == b) || (Math.Abs(a - b) <= eps(a, b));
|
||||
}
|
||||
public static bool fuzzyGt(double a, double b)
|
||||
{
|
||||
return a > b + eps(a, b);
|
||||
}
|
||||
public static bool fuzzyLt(double a, double b)
|
||||
{
|
||||
return a < b - eps(a, b);
|
||||
}
|
||||
public static bool fuzzyNe(double a, double b)
|
||||
{
|
||||
return !fuzzyEq(a, b);
|
||||
}
|
||||
public static bool fuzzyLe(double a, double b)
|
||||
{
|
||||
return a < b + eps(a, b);
|
||||
}
|
||||
public static bool fuzzyGe(double a, double b)
|
||||
{
|
||||
return a > b - eps(a, b);
|
||||
}
|
||||
#endregion
|
||||
|
||||
public static int ApplyPct(ref int Base, float pct)
|
||||
{
|
||||
return Base = CalculatePct(Base, pct);
|
||||
}
|
||||
public static uint ApplyPct(ref uint Base, float pct)
|
||||
{
|
||||
return Base = CalculatePct(Base, pct);
|
||||
}
|
||||
public static float ApplyPct(ref float Base, float pct)
|
||||
{
|
||||
return Base = CalculatePct(Base, pct);
|
||||
}
|
||||
|
||||
public static long AddPct(ref long value, float pct)
|
||||
{
|
||||
return value += (long)CalculatePct(value, pct);
|
||||
}
|
||||
public static int AddPct(ref int value, float pct)
|
||||
{
|
||||
return value += CalculatePct(value, pct);
|
||||
}
|
||||
public static uint AddPct(ref uint value, float pct)
|
||||
{
|
||||
return value += CalculatePct(value, pct);
|
||||
}
|
||||
public static float AddPct(ref float value, float pct)
|
||||
{
|
||||
return value += CalculatePct(value, pct);
|
||||
}
|
||||
|
||||
public static int CalculatePct(int value, float pct)
|
||||
{
|
||||
return (int)(value * Convert.ToSingle(pct) / 100.0f);
|
||||
}
|
||||
public static uint CalculatePct(uint value, float pct)
|
||||
{
|
||||
return (uint)(value * Convert.ToSingle(pct) / 100.0f);
|
||||
}
|
||||
public static float CalculatePct(float value, float pct)
|
||||
{
|
||||
return value * pct / 100.0f;
|
||||
}
|
||||
public static ulong CalculatePct(ulong value, float pct)
|
||||
{
|
||||
return (ulong)(value * pct / 100.0f);
|
||||
}
|
||||
|
||||
public static int RoundToInterval(ref int num, dynamic floor, dynamic ceil)
|
||||
{
|
||||
return num = (int)Math.Min(Math.Max(num, floor), ceil);
|
||||
}
|
||||
public static uint RoundToInterval(ref uint num, dynamic floor, dynamic ceil)
|
||||
{
|
||||
return num = Math.Min(Math.Max(num, floor), ceil);
|
||||
}
|
||||
public static float RoundToInterval(ref float num, dynamic floor, dynamic ceil)
|
||||
{
|
||||
return num = Math.Min(Math.Max(num, floor), ceil);
|
||||
}
|
||||
|
||||
public static void ApplyPercentModFloatVar(ref float value, float val, bool apply)
|
||||
{
|
||||
if (val == -100.0f) // prevent set var to zero
|
||||
val = -99.99f;
|
||||
value *= (apply ? (100.0f + val) / 100.0f : 100.0f / (100.0f + val));
|
||||
}
|
||||
|
||||
public static bool CompareValues(ComparisionType type, uint val1, uint val2)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case ComparisionType.EQ:
|
||||
return val1 == val2;
|
||||
case ComparisionType.High:
|
||||
return val1 > val2;
|
||||
case ComparisionType.Low:
|
||||
return val1 < val2;
|
||||
case ComparisionType.HighEQ:
|
||||
return val1 >= val2;
|
||||
case ComparisionType.LowEQ:
|
||||
return val1 <= val2;
|
||||
default:
|
||||
// incorrect parameter
|
||||
//Contract.Assert(false);
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
public static bool CompareValues(ComparisionType type, float val1, float val2)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case ComparisionType.EQ:
|
||||
return val1 == val2;
|
||||
case ComparisionType.High:
|
||||
return val1 > val2;
|
||||
case ComparisionType.Low:
|
||||
return val1 < val2;
|
||||
case ComparisionType.HighEQ:
|
||||
return val1 >= val2;
|
||||
case ComparisionType.LowEQ:
|
||||
return val1 <= val2;
|
||||
default:
|
||||
// incorrect parameter
|
||||
//Contract.Assert(false);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static ulong MakePair64(uint l, uint h)
|
||||
{
|
||||
return (ulong)l | ((ulong)h << 32);
|
||||
}
|
||||
public static uint Pair64_HiPart(ulong x)
|
||||
{
|
||||
return (uint)((x >> 32) & 0x00000000FFFFFFFF);
|
||||
}
|
||||
public static uint Pair64_LoPart(ulong x)
|
||||
{
|
||||
return (uint)(x & 0x00000000FFFFFFFF);
|
||||
}
|
||||
public static ushort Pair32_HiPart(uint x)
|
||||
{
|
||||
return (ushort)((x >> 16) & 0x0000FFFF);
|
||||
}
|
||||
public static ushort Pair32_LoPart(uint x)
|
||||
{
|
||||
return (ushort)(x & 0x0000FFFF);
|
||||
}
|
||||
public static uint MakePair32(uint l, uint h)
|
||||
{
|
||||
return (ushort)l | (h << 16);
|
||||
}
|
||||
public static ushort MakePair16(uint l, uint h)
|
||||
{
|
||||
return (ushort)((byte)l | (ushort)h << 8);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright (C) 2012-2017 CypherCore <http://github.com/CypherCore>
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Net;
|
||||
|
||||
public static class NetworkExtensions
|
||||
{
|
||||
public static IPAddress GetNetworkAddress(this IPAddress address, IPAddress subnetMask)
|
||||
{
|
||||
byte[] ipAdressBytes = address.GetAddressBytes();
|
||||
byte[] subnetMaskBytes = subnetMask.GetAddressBytes();
|
||||
|
||||
if (ipAdressBytes.Length != subnetMaskBytes.Length)
|
||||
throw new ArgumentException("Lengths of IP address and subnet mask do not match.");
|
||||
|
||||
byte[] broadcastAddress = new byte[ipAdressBytes.Length];
|
||||
for (int i = 0; i < broadcastAddress.Length; i++)
|
||||
{
|
||||
broadcastAddress[i] = (byte)(ipAdressBytes[i] & (subnetMaskBytes[i]));
|
||||
}
|
||||
return new IPAddress(broadcastAddress);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,108 @@
|
||||
/*
|
||||
* Copyright (C) 2012-2017 CypherCore <http://github.com/CypherCore>
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
using System;
|
||||
using System.Diagnostics.Contracts;
|
||||
|
||||
public class RandomHelper
|
||||
{
|
||||
private readonly static Random rand;
|
||||
|
||||
static RandomHelper()
|
||||
{
|
||||
rand = new Random();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a random number between 0.0 and 1.0.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public static double NextDouble()
|
||||
{
|
||||
return rand.NextDouble();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a nonnegative random number.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public static uint Rand32()
|
||||
{
|
||||
return (uint)rand.Next();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a nonnegative random number less than the specified maximum.
|
||||
/// </summary>
|
||||
/// <param name="maxValue"></param>
|
||||
/// <returns></returns>
|
||||
public static uint Rand32(dynamic maxValue)
|
||||
{
|
||||
return (uint)rand.Next(maxValue);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a random number within a specified range.
|
||||
/// </summary>
|
||||
/// <param name="minValue"></param>
|
||||
/// <param name="maxValue"></param>
|
||||
/// <returns></returns>
|
||||
public static int IRand(int minValue, int maxValue)
|
||||
{
|
||||
return rand.Next(minValue, maxValue);
|
||||
}
|
||||
public static uint URand(dynamic minValue, dynamic maxValue)
|
||||
{
|
||||
return (uint)rand.Next(Convert.ToInt32(minValue), Convert.ToInt32(maxValue));
|
||||
}
|
||||
public static float FRand(float min, float max)
|
||||
{
|
||||
Contract.Assert(max >= min);
|
||||
return (float)(rand.NextDouble() * (max - min) + min);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if rand.Next less then i
|
||||
/// </summary>
|
||||
/// <param name="i"></param>
|
||||
/// <returns></returns>
|
||||
public static bool randChance(float i)
|
||||
{
|
||||
return i > rand.Next(0, 100);
|
||||
}
|
||||
|
||||
public static double randChance()
|
||||
{
|
||||
return rand.NextDouble() * 100.0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Fills the elements of a specified array of bytes with random numbers.
|
||||
/// </summary>
|
||||
/// <param name="buffer"></param>
|
||||
public static void NextBytes(byte[] buffer)
|
||||
{
|
||||
rand.NextBytes(buffer);
|
||||
}
|
||||
|
||||
public static T RAND<T>(params T[] args)
|
||||
{
|
||||
int rand = IRand(0, args.Length - 1);
|
||||
|
||||
return args[rand];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,351 @@
|
||||
/*
|
||||
* Copyright (C) 2012-2017 CypherCore <http://github.com/CypherCore>
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
using System;
|
||||
|
||||
public static class Time
|
||||
{
|
||||
public const int Minute = 60;
|
||||
public const int Hour = Minute * 60;
|
||||
public const int Day = Hour * 24;
|
||||
public const int Week = Day * 7;
|
||||
public const int Month = Day * 30;
|
||||
public const int Year = Month * 12;
|
||||
public const int InMilliseconds = 1000;
|
||||
|
||||
public static readonly DateTime Epoch = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc);
|
||||
public static readonly DateTime ApplicationStartTime = DateTime.Now;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the current Unix time.
|
||||
/// </summary>
|
||||
public static long UnixTime
|
||||
{
|
||||
get
|
||||
{
|
||||
return (long)(DateTime.Now - Epoch).TotalSeconds;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the current Unix time, in milliseconds.
|
||||
/// </summary>
|
||||
public static long UnixTimeMilliseconds
|
||||
{
|
||||
get
|
||||
{
|
||||
var ts = (DateTime.Now - Epoch);
|
||||
return ts.ToMilliseconds();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts a TimeSpan to its equivalent representation in milliseconds (Int64).
|
||||
/// </summary>
|
||||
/// <param name="span">The time span value to convert.</param>
|
||||
public static long ToMilliseconds(this TimeSpan span)
|
||||
{
|
||||
return (long)span.TotalMilliseconds;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the system uptime.
|
||||
/// </summary>
|
||||
/// <returns>the system uptime in milliseconds</returns>
|
||||
public static uint GetSystemTime()
|
||||
{
|
||||
return (uint)Environment.TickCount;
|
||||
}
|
||||
|
||||
public static uint GetMSTime()
|
||||
{
|
||||
return (uint)(DateTime.Now - ApplicationStartTime).ToMilliseconds();
|
||||
}
|
||||
|
||||
public static uint GetMSTimeDiff(uint oldMSTime, uint newMSTime)
|
||||
{
|
||||
if (oldMSTime > newMSTime)
|
||||
return (0xFFFFFFFF - oldMSTime) + newMSTime;
|
||||
else
|
||||
return newMSTime - oldMSTime;
|
||||
}
|
||||
|
||||
public static uint GetMSTimeDiffToNow(uint oldMSTime)
|
||||
{
|
||||
var newMSTime = GetMSTime();
|
||||
if (oldMSTime > newMSTime)
|
||||
return (0xFFFFFFFF - oldMSTime) + newMSTime;
|
||||
else
|
||||
return newMSTime - oldMSTime;
|
||||
}
|
||||
|
||||
public static DateTime UnixTimeToDateTime(long unixTime)
|
||||
{
|
||||
return Epoch.AddSeconds(unixTime);
|
||||
}
|
||||
public static long DateTimeToUnixTime(DateTime dateTime)
|
||||
{
|
||||
return (long)(dateTime - Epoch).TotalSeconds;
|
||||
}
|
||||
|
||||
public static long GetNextResetUnixTime(int hours)
|
||||
{
|
||||
return DateTimeToUnixTime((DateTime.Now.Date + new TimeSpan(hours, 0, 0)));
|
||||
}
|
||||
public static long GetNextResetUnixTime(int days, int hours)
|
||||
{
|
||||
return DateTimeToUnixTime((DateTime.Now.Date + new TimeSpan(days, hours, 0, 0)));
|
||||
}
|
||||
public static long GetNextResetUnixTime(int months, int days, int hours)
|
||||
{
|
||||
return DateTimeToUnixTime((DateTime.Now.Date + new TimeSpan(months + days, hours, 0)));
|
||||
}
|
||||
|
||||
public static string secsToTimeString(ulong timeInSecs, bool shortText = false, bool hoursOnly = false)
|
||||
{
|
||||
ulong secs = timeInSecs % Minute;
|
||||
ulong minutes = timeInSecs % Hour / Minute;
|
||||
ulong hours = timeInSecs % Day / Hour;
|
||||
ulong days = timeInSecs / Day;
|
||||
|
||||
string ss = "";
|
||||
if (days != 0)
|
||||
ss += days + (shortText ? "d" : " Day(s) ");
|
||||
if (hours != 0 || hoursOnly)
|
||||
ss += hours + (shortText ? "h" : " Hour(s) ");
|
||||
if (!hoursOnly)
|
||||
{
|
||||
if (minutes != 0)
|
||||
ss += minutes + (shortText ? "m" : " Minute(s) ");
|
||||
if (secs != 0 || (days == 0 && hours == 0 && minutes == 0))
|
||||
ss += secs + (shortText ? "s" : " Second(s).");
|
||||
}
|
||||
|
||||
return ss;
|
||||
}
|
||||
|
||||
public static uint TimeStringToSecs(string timestring)
|
||||
{
|
||||
int secs = 0;
|
||||
int buffer = 0;
|
||||
int multiplier;
|
||||
|
||||
foreach (var c in timestring)
|
||||
{
|
||||
if (char.IsDigit(c))
|
||||
{
|
||||
buffer *= 10;
|
||||
buffer += c - '0';
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (c)
|
||||
{
|
||||
case 'd':
|
||||
multiplier = Day;
|
||||
break;
|
||||
case 'h':
|
||||
multiplier = Hour;
|
||||
break;
|
||||
case 'm':
|
||||
multiplier = Minute;
|
||||
break;
|
||||
case 's':
|
||||
multiplier = 1;
|
||||
break;
|
||||
default:
|
||||
return 0; //bad format
|
||||
}
|
||||
buffer *= multiplier;
|
||||
secs += buffer;
|
||||
buffer = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return (uint)secs;
|
||||
}
|
||||
|
||||
public static string GetTimeString(long time)
|
||||
{
|
||||
long days = time / Day;
|
||||
long hours = (time % Day) / Hour;
|
||||
long minute = (time % Hour) / Minute;
|
||||
|
||||
return string.Format("Days: {0} Hours: {1} Minutes: {2}", days, hours, minute);
|
||||
}
|
||||
|
||||
public static void Profile(string description, int iterations, Action func)
|
||||
{
|
||||
//Run at highest priority to minimize fluctuations caused by other processes/threads
|
||||
System.Diagnostics.Process.GetCurrentProcess().PriorityClass = System.Diagnostics.ProcessPriorityClass.High;
|
||||
System.Threading.Thread.CurrentThread.Priority = System.Threading.ThreadPriority.Highest;
|
||||
|
||||
// warm up
|
||||
func();
|
||||
|
||||
var watch = new System.Diagnostics.Stopwatch();
|
||||
|
||||
// clean up
|
||||
GC.Collect();
|
||||
GC.WaitForPendingFinalizers();
|
||||
GC.Collect();
|
||||
|
||||
watch.Start();
|
||||
for (int i = 0; i < iterations; i++)
|
||||
{
|
||||
func();
|
||||
}
|
||||
watch.Stop();
|
||||
Console.Write(description);
|
||||
Console.WriteLine(" Time Elapsed {0} ms", watch.Elapsed.TotalMilliseconds);
|
||||
}
|
||||
}
|
||||
|
||||
public class TimeTrackerSmall
|
||||
{
|
||||
public TimeTrackerSmall(int expiry = 0)
|
||||
{
|
||||
i_expiryTime = expiry;
|
||||
}
|
||||
|
||||
public void Update(int diff)
|
||||
{
|
||||
i_expiryTime -= diff;
|
||||
}
|
||||
|
||||
public bool Passed()
|
||||
{
|
||||
return i_expiryTime <= 0;
|
||||
}
|
||||
|
||||
public void Reset(int interval)
|
||||
{
|
||||
i_expiryTime = interval;
|
||||
}
|
||||
|
||||
public int GetExpiry()
|
||||
{
|
||||
return i_expiryTime;
|
||||
}
|
||||
int i_expiryTime;
|
||||
}
|
||||
|
||||
public class TimeTracker
|
||||
{
|
||||
public TimeTracker(long expiry = 0)
|
||||
{
|
||||
i_expiryTime = expiry;
|
||||
}
|
||||
|
||||
public void Update(long diff)
|
||||
{
|
||||
i_expiryTime -= diff;
|
||||
}
|
||||
|
||||
public bool Passed()
|
||||
{
|
||||
return i_expiryTime <= 0;
|
||||
}
|
||||
|
||||
public void Reset(long interval)
|
||||
{
|
||||
i_expiryTime = interval;
|
||||
}
|
||||
|
||||
public long GetExpiry()
|
||||
{
|
||||
return i_expiryTime;
|
||||
}
|
||||
|
||||
long i_expiryTime;
|
||||
}
|
||||
|
||||
public class IntervalTimer
|
||||
{
|
||||
public void Update(long diff)
|
||||
{
|
||||
_current += diff;
|
||||
if (_current < 0)
|
||||
_current = 0;
|
||||
}
|
||||
|
||||
public bool Passed()
|
||||
{
|
||||
return _current >= _interval;
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
if (_current >= _interval)
|
||||
_current %= _interval;
|
||||
}
|
||||
|
||||
public void SetCurrent(long current)
|
||||
{
|
||||
_current = current;
|
||||
}
|
||||
|
||||
public void SetInterval(long interval)
|
||||
{
|
||||
_interval = interval;
|
||||
}
|
||||
|
||||
public long GetInterval()
|
||||
{
|
||||
return _interval;
|
||||
}
|
||||
|
||||
public long GetCurrent()
|
||||
{
|
||||
return _current;
|
||||
}
|
||||
|
||||
long _interval;
|
||||
long _current;
|
||||
}
|
||||
|
||||
public class PeriodicTimer
|
||||
{
|
||||
public PeriodicTimer(int period, int start_time)
|
||||
{
|
||||
i_period = period;
|
||||
i_expireTime = start_time;
|
||||
}
|
||||
|
||||
public bool Update(int diff)
|
||||
{
|
||||
if ((i_expireTime -= diff) > 0)
|
||||
return false;
|
||||
|
||||
i_expireTime += i_period > diff ? i_period : diff;
|
||||
return true;
|
||||
}
|
||||
|
||||
public void SetPeriodic(int period, int start_time)
|
||||
{
|
||||
i_expireTime = start_time;
|
||||
i_period = period;
|
||||
}
|
||||
|
||||
// Tracker interface
|
||||
public void TUpdate(int diff) { i_expireTime -= diff; }
|
||||
public bool TPassed() { return i_expireTime <= 0; }
|
||||
public void TReset(int diff, int period) { i_expireTime += period > diff ? period : diff; }
|
||||
|
||||
int i_period;
|
||||
int i_expireTime;
|
||||
}
|
||||
Reference in New Issue
Block a user