Initial commit: Client Doc docs Server Tools
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,526 @@
|
||||
using Microsoft.CSharp;
|
||||
using System;
|
||||
using System.CodeDom.Compiler;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
|
||||
namespace XGame
|
||||
{
|
||||
public class Type_Null
|
||||
{
|
||||
public static int Reserve = 0;
|
||||
}
|
||||
public static partial class Utility
|
||||
{
|
||||
//private static float FLOAT_PRECISION = 1e-5f;
|
||||
|
||||
private static Dictionary<string, int> sActorIdDic = new Dictionary<string, int>();
|
||||
private static Dictionary<string, Type> sTypeDic = new Dictionary<string, Type>();
|
||||
private static Dictionary<string, Assembly> Asms = new Dictionary<string, Assembly>();
|
||||
private static Type typeNull = typeof(Type_Null);
|
||||
|
||||
public static int GenClientNameId(string actorTypeName)
|
||||
{
|
||||
if (sActorIdDic.ContainsKey(actorTypeName) == false)
|
||||
{
|
||||
sActorIdDic.Add(actorTypeName, 0);
|
||||
}
|
||||
++sActorIdDic[actorTypeName];
|
||||
|
||||
return sActorIdDic[actorTypeName];
|
||||
}
|
||||
|
||||
static Type SuperGetType(string sTypeName)
|
||||
{
|
||||
Type typeValue;
|
||||
if (sTypeDic.TryGetValue(sTypeName, out typeValue))
|
||||
{
|
||||
if (typeValue == typeNull)
|
||||
return null;
|
||||
else
|
||||
return typeValue;
|
||||
}
|
||||
else
|
||||
{
|
||||
typeValue = Type.GetType(sTypeName);//底包的类型有就不用下面的麻烦代码
|
||||
if (typeValue != null)
|
||||
{
|
||||
sTypeDic[sTypeName] = typeValue;
|
||||
//Debug.Log($"SuperGetType sTypeDic 1 : {sTypeName}");
|
||||
return typeValue;
|
||||
}
|
||||
|
||||
Assembly[] foundAsms = null;
|
||||
if (Asms.Count == 0)
|
||||
{
|
||||
foundAsms = AppDomain.CurrentDomain.GetAssemblies();
|
||||
foreach (var asm in foundAsms)
|
||||
{
|
||||
//只检查GYFramework 和Assembly-CSharp 热更相关的dll
|
||||
//Debug.Log($"SuperGetType : {sTypeName} ({asm.GetName().Name})");
|
||||
string asmName = asm.GetName().Name;
|
||||
if (asmName == "GYFramework" || asmName == "Assembly-CSharp")
|
||||
{
|
||||
Asms[asmName] = asm;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var asm in Asms)
|
||||
{
|
||||
typeValue = asm.Value.GetType(sTypeName);
|
||||
if (typeValue != null)
|
||||
{
|
||||
sTypeDic[sTypeName] = typeValue;
|
||||
//Debug.Log($"SuperGetType sTypeDic 2 : {sTypeName}");
|
||||
return typeValue;
|
||||
}
|
||||
}
|
||||
|
||||
//最后全量查找
|
||||
if (null == foundAsms)
|
||||
{
|
||||
foundAsms = AppDomain.CurrentDomain.GetAssemblies();
|
||||
}
|
||||
|
||||
foreach (var asm in foundAsms)
|
||||
{
|
||||
string asmName = asm.GetName().Name;
|
||||
typeValue = asm.GetType(sTypeName);
|
||||
if (typeValue != null)
|
||||
{
|
||||
Asms[asmName] = asm;
|
||||
sTypeDic[sTypeName] = typeValue;
|
||||
//Debug.Log($"SuperGetType sTypeDic 3: {sTypeName}");
|
||||
return typeValue;
|
||||
}
|
||||
|
||||
}
|
||||
sTypeDic[sTypeName] = typeNull;
|
||||
//Debug.Log($"SuperGetType Error : {sTypeName} == null");
|
||||
}
|
||||
return null;
|
||||
|
||||
}
|
||||
public static Type GetTypeByTypeName(string typeName)
|
||||
{
|
||||
System.Type type = SuperGetType(typeName);//Type.GetType(typeName);//
|
||||
|
||||
if (null == type)
|
||||
{
|
||||
string newTypeName = "XGame" + "." + typeName;
|
||||
type = SuperGetType(newTypeName); //Type.GetType(newTypeName);//
|
||||
|
||||
//if (null == type)
|
||||
//{
|
||||
// newTypeName = "XGame" + "." + typeName;
|
||||
// type = SuperGetType(newTypeName); //Type.GetType(newTypeName);//
|
||||
|
||||
//}
|
||||
}
|
||||
|
||||
return type;
|
||||
}
|
||||
|
||||
public static Type GetTypeByTypeName<BaseType>(string typeName) where BaseType : class
|
||||
{
|
||||
System.Type type = Type.GetType(typeName);
|
||||
|
||||
if (type == null)
|
||||
{
|
||||
string newTypeName = "XGame" + "." + typeName;
|
||||
type = Type.GetType(newTypeName);
|
||||
|
||||
//if (type == null)
|
||||
//{
|
||||
// newTypeName = "XGame" + "." + typeName;
|
||||
// type = Type.GetType(newTypeName);
|
||||
//}
|
||||
}
|
||||
|
||||
if (type == null)
|
||||
{
|
||||
Debug.LogError("GetTypeByTypeName typeName:{0} get type return null");
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!typeof(BaseType).IsAssignableFrom(type))
|
||||
{
|
||||
Debug.LogError($"GetTypeByTypeName typeName:{typeName} is not subclass of {typeof(BaseType).FullName}");
|
||||
return null;
|
||||
}
|
||||
|
||||
return type;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 判断指定的类型 <paramref name="type"/> 是否是指定泛型类型的子类型,或实现了指定泛型接口。
|
||||
/// </summary>
|
||||
/// <param name="type">需要测试的类型。</param>
|
||||
/// <param name="generic">泛型接口类型,传入 typeof(IXxx)</param>
|
||||
/// <returns>如果是泛型接口的子类型,则返回 true,否则返回 false。</returns>
|
||||
public static bool HasImplementedRawGeneric(this Type type, Type generic)
|
||||
{
|
||||
if (type == null) throw new ArgumentNullException(nameof(type));
|
||||
if (generic == null) throw new ArgumentNullException(nameof(generic));
|
||||
|
||||
// 测试接口。
|
||||
var isTheRawGenericType = type.GetInterfaces().Any(IsTheRawGenericType);
|
||||
if (isTheRawGenericType) return true;
|
||||
|
||||
// 测试类型。
|
||||
while (type != null && type != typeof(object))
|
||||
{
|
||||
isTheRawGenericType = IsTheRawGenericType(type);
|
||||
if (isTheRawGenericType) return true;
|
||||
type = type.BaseType;
|
||||
}
|
||||
|
||||
// 没有找到任何匹配的接口或类型。
|
||||
return false;
|
||||
|
||||
// 测试某个类型是否是指定的原始接口。
|
||||
bool IsTheRawGenericType(Type test)
|
||||
=> generic == (test.IsGenericType ? test.GetGenericTypeDefinition() : test);
|
||||
}
|
||||
|
||||
public static object GetPropValue(object obj, String name)
|
||||
{
|
||||
foreach (String part in name.Split('.'))
|
||||
{
|
||||
if (obj == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
Type type = obj.GetType();
|
||||
PropertyInfo info = type.GetProperty(part);
|
||||
if (info == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
obj = info.GetValue(obj, null);
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
|
||||
public static T GetPropValue<T>(object obj, String name)
|
||||
{
|
||||
object retval = GetPropValue(obj, name);
|
||||
if (retval == null)
|
||||
{
|
||||
return default(T);
|
||||
}
|
||||
|
||||
// throws InvalidCastException if types are incompatible
|
||||
return (T)retval;
|
||||
}
|
||||
|
||||
public static object GetFieldValue(object obj, String name)
|
||||
{
|
||||
foreach (String part in name.Split('.'))
|
||||
{
|
||||
if (obj == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
Type type = obj.GetType();
|
||||
FieldInfo info = type.GetField(part);
|
||||
if (info == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
obj = info.GetValue(obj);
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
|
||||
public static T GetFieldValue<T>(object obj, String name)
|
||||
{
|
||||
object retval = GetFieldValue(obj, name);
|
||||
if (retval == null)
|
||||
{
|
||||
return default(T);
|
||||
}
|
||||
|
||||
// throws InvalidCastException if types are incompatible
|
||||
return (T)retval;
|
||||
}
|
||||
|
||||
public static T CreateInstance<T>(string typeName, params object[] args) where T : class
|
||||
{
|
||||
if (string.IsNullOrEmpty(typeName) || typeName == "")
|
||||
{
|
||||
typeName = typeof(T).FullName;
|
||||
}
|
||||
|
||||
Type type = Type.GetType(typeName);
|
||||
if (type == null)
|
||||
{
|
||||
Debug.LogError($"Get Type from type name:{type} return null");
|
||||
return null;
|
||||
}
|
||||
|
||||
if (typeof(T).IsAssignableFrom(type) == false)
|
||||
{
|
||||
Debug.LogError($"{type} is not assignable from {typeof(T).Name}");
|
||||
return null;
|
||||
}
|
||||
|
||||
T instance = Activator.CreateInstance(type, args) as T;
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
public static object CopyObject(object srcObject)
|
||||
{
|
||||
Type type = srcObject.GetType();
|
||||
object newObject = Activator.CreateInstance(type);
|
||||
|
||||
FieldInfo[] fields = type.GetFields(BindingFlags.NonPublic | BindingFlags.Public
|
||||
| BindingFlags.Instance | BindingFlags.Static);
|
||||
for (int i = 0; i < fields.Length; ++i)
|
||||
{
|
||||
FieldInfo fi = fields[i];
|
||||
fi.SetValue(newObject, fi.GetValue(srcObject));
|
||||
}
|
||||
|
||||
PropertyInfo[] props = type.GetProperties(BindingFlags.NonPublic | BindingFlags.Public
|
||||
| BindingFlags.Instance | BindingFlags.Static);
|
||||
for (int i = 0; i < props.Length; ++i)
|
||||
{
|
||||
PropertyInfo fi = props[i];
|
||||
fi.SetValue(newObject, fi.GetValue(srcObject));
|
||||
}
|
||||
|
||||
return newObject;
|
||||
}
|
||||
|
||||
public static bool CopyObject(object srcObject, object targetObject)
|
||||
{
|
||||
Type srcType = srcObject.GetType();
|
||||
Type targetType = targetObject.GetType();
|
||||
|
||||
if (srcType != targetType)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
FieldInfo[] fields = srcType.GetFields(BindingFlags.NonPublic | BindingFlags.Public
|
||||
| BindingFlags.Instance | BindingFlags.Static);
|
||||
for (int i = 0; i < fields.Length; ++i)
|
||||
{
|
||||
FieldInfo fi = fields[i];
|
||||
fi.SetValue(targetObject, fi.GetValue(srcObject));
|
||||
}
|
||||
|
||||
PropertyInfo[] props = srcType.GetProperties(BindingFlags.NonPublic | BindingFlags.Public
|
||||
| BindingFlags.Instance | BindingFlags.Static);
|
||||
for (int i = 0; i < props.Length; ++i)
|
||||
{
|
||||
PropertyInfo fi = props[i];
|
||||
fi.SetValue(targetObject, fi.GetValue(srcObject));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static object CopyFields(object src)
|
||||
{
|
||||
Type t = src.GetType();
|
||||
object res = Activator.CreateInstance(t);
|
||||
FieldInfo[] list = t.GetFields();
|
||||
for (int i = 0; i < list.Length; ++i)
|
||||
{
|
||||
FieldInfo fi = list[i];
|
||||
fi.SetValue(res, fi.GetValue(src));
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
public static T ParseEnum<T>(string value, T defaultValue) where T : struct
|
||||
{
|
||||
T v;
|
||||
return Enum.TryParse<T>(value, true, out v) ? v : defaultValue;
|
||||
}
|
||||
|
||||
|
||||
public static void ThrowError(string fmt, params object[] args)
|
||||
{
|
||||
string msg = String.Format(fmt, args);
|
||||
throw new Exception(msg);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 计算字符串的MD5值
|
||||
/// </summary>
|
||||
public static string GetStringMd5(string source)
|
||||
{
|
||||
MD5CryptoServiceProvider md5 = new MD5CryptoServiceProvider();
|
||||
byte[] data = System.Text.Encoding.UTF8.GetBytes(source);
|
||||
byte[] md5Data = md5.ComputeHash(data, 0, data.Length);
|
||||
md5.Clear();
|
||||
|
||||
string destString = "";
|
||||
for (int i = 0; i < md5Data.Length; i++)
|
||||
{
|
||||
destString += System.Convert.ToString(md5Data[i], 16).PadLeft(2, '0');
|
||||
}
|
||||
destString = destString.PadLeft(32, '0');
|
||||
return destString.ToUpper();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 计算文件的MD5值
|
||||
/// </summary>
|
||||
public static string GetFileMd5(string file)
|
||||
{
|
||||
try
|
||||
{
|
||||
FileStream fs = new FileStream(file, FileMode.Open);
|
||||
System.Security.Cryptography.MD5 md5 = new System.Security.Cryptography.MD5CryptoServiceProvider();
|
||||
byte[] retVal = md5.ComputeHash(fs);
|
||||
fs.Close();
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (int i = 0; i < retVal.Length; i++)
|
||||
{
|
||||
sb.Append(retVal[i].ToString("x2"));
|
||||
}
|
||||
return sb.ToString();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new Exception("md5file() fail, error:" + ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
public static string GetBytesMd5(byte[] bytes)
|
||||
{
|
||||
System.Security.Cryptography.MD5 md5 = new System.Security.Cryptography.MD5CryptoServiceProvider();
|
||||
byte[] retVal = md5.ComputeHash(bytes);
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (int i = 0; i < retVal.Length; i++)
|
||||
{
|
||||
sb.Append(retVal[i].ToString("x2"));
|
||||
}
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
public static long GetTimeTick()
|
||||
{
|
||||
var ts = DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0);
|
||||
return Convert.ToInt64(ts.TotalMilliseconds);
|
||||
}
|
||||
public static double XWorldGetTime()
|
||||
{
|
||||
return Time.realtimeSinceStartupAsDouble;
|
||||
}
|
||||
|
||||
public static bool IsPossibleSimulator()
|
||||
{
|
||||
if (Application.isEditor)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool isSimulator = false;
|
||||
|
||||
isSimulator = isSimulator || SystemInfo.graphicsDeviceName == "Netease";
|
||||
isSimulator = isSimulator || SystemInfo.deviceModel == "Netease MuMu";
|
||||
|
||||
string processorType = SystemInfo.processorType.ToLower();
|
||||
isSimulator = isSimulator || processorType.Contains("intel") || processorType.Contains("amd");
|
||||
|
||||
return isSimulator;
|
||||
}
|
||||
|
||||
// 格式化文件大小
|
||||
private static string[] sSuffix = { "B", "KB", "MB", "GB", "TB" };
|
||||
public static string FormatBytesStr(long bytes)
|
||||
{
|
||||
float size = Convert.ToSingle(bytes);
|
||||
int sufIdx = 0;
|
||||
for(sufIdx = 0; sufIdx < sSuffix.Length; sufIdx++)
|
||||
{
|
||||
if(size >= 1024)
|
||||
{
|
||||
size = Mathf.Ceil(size / 1024);
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
string format = size + sSuffix[sufIdx];
|
||||
return format;
|
||||
}
|
||||
|
||||
public static bool Contains<T>(T[] array, T value) where T : class
|
||||
{
|
||||
for (int i = 0; i < array.Length; ++i)
|
||||
{
|
||||
if (array[i] == value)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static bool Contains(string[] array, string value)
|
||||
{
|
||||
for (int i = 0; i < array.Length; ++i)
|
||||
{
|
||||
if (array[i].CompareTo(value) == 0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static int RandomRangeToInt(int min,int max)
|
||||
{
|
||||
return UnityEngine.Random.Range(min,max);
|
||||
}
|
||||
|
||||
public static void CreateMulDirectory(string path)
|
||||
{
|
||||
if (Directory.Exists(path))
|
||||
return;
|
||||
int n = path.LastIndexOf('/');
|
||||
if(n == -1)
|
||||
n = path.LastIndexOf('\\');
|
||||
if (n == -1)
|
||||
{
|
||||
Directory.CreateDirectory(path);
|
||||
return;
|
||||
}
|
||||
string subpath = path.Substring(0, n);
|
||||
if (Directory.Exists(subpath))
|
||||
{
|
||||
Directory.CreateDirectory(path);
|
||||
}
|
||||
else
|
||||
{
|
||||
CreateMulDirectory(subpath);
|
||||
Directory.CreateDirectory(path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user